Skip to content

Refactored code for better readabitlity #98

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/additions/test_generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def lottery():


def test_generators():
"""Yield statement"""
#Yield statement
for number_index, random_number in enumerate(lottery()):
if number_index < 3:
assert 0 <= random_number <= 10
Expand Down
12 changes: 6 additions & 6 deletions src/classes/test_class_and_instance_variables.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@


def test_class_and_instance_variables():
"""Class and Instance Variables."""
#Class and Instance Variables.

# pylint: disable=too-few-public-methods
class Dog:
"""Dog class example"""
kind = 'canine' # Class variable shared by all instances.
Expand All @@ -31,11 +30,12 @@ def __init__(self, name):
# Unique to buddy.
assert buddy.name == 'Buddy'

# Shared data can have possibly surprising effects with involving mutable objects such as lists
# and dictionaries. For example, the tricks list in the following code should not be used as a
# class variable because just a single list would be shared by all Dog instances.
""" Shared data can have possibly surprising effects with involving mutable objects such as lists
and dictionaries. For example, the tricks list in the following code should not be used as a
class variable because just a single list would be shared by all Dog instances.

# pylint: disable=too-few-public-methods
pylint: disable=too-few-public-methods
"""
class DogWithSharedTricks:
"""Dog class example with wrong shared variable usage"""
tricks = [] # Mistaken use of a class variable (see below) for mutable objects.
Expand Down
25 changes: 14 additions & 11 deletions src/classes/test_class_definition.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@


def test_class_definition():
"""Class definition."""

# Class definitions, like function definitions (def statements) must be executed before they
# have any effect. (You could conceivably place a class definition in a branch of an if
# statement, or inside a function.)
"""Class definition.

Class definitions, like function definitions (def statements) must be executed before they
have any effect. (You could conceivably place a class definition in a branch of an if
statement, or inside a function.)
"""

class GreetingClass:
"""Example of the class definition

Expand All @@ -23,23 +24,25 @@ class GreetingClass:
name = 'user'

def say_hello(self):
"""Class method."""
# The self parameter is a reference to the class itself, and is used to access variables
# that belongs to the class. It does not have to be named self , you can call it
# whatever you like, but it has to be the first parameter of any function in the class.
"""Class method.
The self parameter is a reference to the class itself, and is used to access variables
that belongs to the class. It does not have to be named self , you can call it
whatever you like, but it has to be the first parameter of any function in the class.
"""
return 'Hello ' + self.name

def say_goodbye(self):
"""Class method."""
return 'Goodbye ' + self.name

# When a class definition is entered, a new namespace is created, and used as the local scope —
""" When a class definition is entered, a new namespace is created, and used as the local scope —
# thus, all assignments to local variables go into this new namespace. In particular, function
# definitions bind the name of the new function here.

# Class instantiation uses function notation. Just pretend that the class object is a
# parameterless function that returns a new instance of the class. For example the following
# code will creates a new instance of the class and assigns this object to the local variable.
# code will creates a new instance of the class and assigns this object to the local variable."
"""
greeter = GreetingClass()

assert greeter.say_hello() == 'Hello user'
Expand Down
10 changes: 5 additions & 5 deletions src/classes/test_class_objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ def test_class_objects():
Class objects support two kinds of operations:
- attribute references
- instantiation.

ATTRIBUTE REFERENCES use the standard syntax used for all attribute references in
Python: obj.name. Valid attribute names are all the names that were in the class’s namespace
when the class object was created. For class MyCounter the following references are valid
attribute references:
"""

# ATTRIBUTE REFERENCES use the standard syntax used for all attribute references in
# Python: obj.name. Valid attribute names are all the names that were in the class’s namespace
# when the class object was created. For class MyCounter the following references are valid
# attribute references:

class ComplexNumber:
"""Example of the complex numbers class"""

Expand Down
47 changes: 24 additions & 23 deletions src/classes/test_method_objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,20 @@ def increment_counter(self):


def test_method_objects():
"""Method Objects."""
"""Method Objects.

# The other kind of instance attribute reference is a method. A method is a function that
# “belongs to” an object. (In Python, the term method is not unique to class instances: other
# object types can have methods as well. For example, list objects have methods called append,
# insert, remove, sort, and so on. However, in the following discussion, we’ll use the term
# method exclusively to mean methods of class instance objects, unless explicitly stated
# otherwise.)
The other kind of instance attribute reference is a method. A method is a function that
“belongs to” an object. (In Python, the term method is not unique to class instances: other
object types can have methods as well. For example, list objects have methods called append,
insert, remove, sort, and so on. However, in the following discussion, we’ll use the term
method exclusively to mean methods of class instance objects, unless explicitly stated
otherwise.)

# But be aware that counter.get_counter() is not the same thing as MyCounter.get_counter() —
# it is a method object, not a function object.
But be aware that counter.get_counter() is not the same thing as MyCounter.get_counter() —
it is a method object, not a function object.

# Usually, a method is called right after it is bound
Usually, a method is called right after it is bound"
"""
counter = MyCounter()
assert counter.get_counter() == 10

Expand All @@ -43,18 +44,18 @@ def test_method_objects():
get_counter = counter.get_counter
assert get_counter() == 10

# What exactly happens when a method is called? You may have noticed that counter.get_counter()
# was called without an argument above, even though the function definition for get_counter()
# specified an argument (self). What happened to the argument? Surely Python raises an
# exception when a function that requires an argument is called without any — even if the
# argument isnt actually used…

# Actually, you may have guessed the answer: the special thing about methods is that the
# instance object is passed as the first argument of the function. In our example, the call
# counter.get_counter() is exactly equivalent to MyCounter.get_counter(counter). In general,
# calling a method with a list of n arguments is equivalent to calling the corresponding
# function with an argument list that is created by inserting the method’s instance object
# before the first argument.

""" What exactly happens when a method is called? You may have noticed that counter.get_counter()
was called without an argument above, even though the function definition for get_counter()
specified an argument (self). What happened to the argument? Surely Python raises an
exception when a function that requires an argument is called without any — even if the
argument isn't actually used…

Actually, you may have guessed the answer: the special thing about methods is that the
instance object is passed as the first argument of the function. In our example, the call
counter.get_counter() is exactly equivalent to MyCounter.get_counter(counter). In general,
calling a method with a list of n arguments is equivalent to calling the corresponding
function with an argument list that is created by inserting the method’s instance object
before the first argument.
"""
assert counter.get_counter() == 10
assert MyCounter.get_counter(counter) == 10
3 changes: 2 additions & 1 deletion src/control_flow/test_continue.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@


def test_continue_statement():
"""CONTINUE statement in FOR loop"""
"""CONTINUE statement in FOR loop

# Let's

# This list will contain only even numbers from the range.
"""
even_numbers = []
# This list will contain every other numbers (in this case - ods).
rest_of_the_numbers = []
Expand Down
9 changes: 5 additions & 4 deletions src/control_flow/test_for.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,11 @@ def test_range_function():

assert list(range(5)) == [0, 1, 2, 3, 4]

# The given end point is never part of the generated sequence; range(10) generates 10 values,
# the legal indices for items of a sequence of length 10. It is possible to let the range start
# at another number, or to specify a different increment (even negative; sometimes this is
# called the ‘step’):
"""The given end point is never part of the generated sequence; range(10) generates 10 values,
the legal indices for items of a sequence of length 10. It is possible to let the range start
at another number, or to specify a different increment (even negative; sometimes this is
called the 'step'):"
"""

assert list(range(5, 10)) == [5, 6, 7, 8, 9]
assert list(range(0, 10, 3)) == [0, 3, 6, 9]
Expand Down
14 changes: 7 additions & 7 deletions src/exceptions/test_handle_exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ def test_handle_exceptions():

assert exception_has_been_handled

# A try statement may have more than one except clause, to specify handlers for different
# exceptions. At most one handler will be executed. Handlers only handle exceptions that occur
# in the corresponding try clause, not in other handlers of the same try statement. An except
# clause may name multiple exceptions as a parenthesized tuple, for example:

"""A try statement may have more than one except clause, to specify handlers for different
exceptions. At most one handler will be executed. Handlers only handle exceptions that occur
in the corresponding try clause, not in other handlers of the same try statement. An except
clause may name multiple exceptions as a parenthesized tuple, for example:
"""
exception_has_been_handled = False
try:
result = 10 * (1 / 0) # division by zero
Expand All @@ -85,10 +85,10 @@ def test_handle_exceptions():

assert exception_has_been_handled

# The try … except statement has an optional else clause, which, when present, must follow all
""" The try … except statement has an optional else clause, which, when present, must follow all
# except clauses. It is useful for code that must be executed if the try clause does not raise
# an exception. For example:

"""
exception_has_been_handled = False
no_exceptions_has_been_fired = False

Expand Down
24 changes: 13 additions & 11 deletions src/functions/test_function_arbitrary_arguments.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,26 @@


def test_function_arbitrary_arguments():
"""Arbitrary Argument Lists"""

# When a final formal parameter of the form **name is present, it receives a dictionary
# containing all keyword arguments except for those corresponding to a formal parameter.
# This may be combined with a formal parameter of the form *name which receives a tuple
# containing the positional arguments beyond the formal parameter list.
# (*name must occur before **name.) For example, if we define a function like this:
"""Arbitrary Argument Lists

When a final formal parameter of the form **name is present, it receives a dictionary
containing all keyword arguments except for those corresponding to a formal parameter.
This may be combined with a formal parameter of the form *name which receives a tuple
containing the positional arguments beyond the formal parameter list.
(*name must occur before **name.) For example, if we define a function like this:
"""
def test_function(first_param, *arguments):
"""This function accepts its arguments through "arguments" tuple"""
assert first_param == 'first param'
assert arguments == ('second param', 'third param')

test_function('first param', 'second param', 'third param')

# Normally, these variadic arguments will be last in the list of formal parameters, because
# they scoop up all remaining input arguments that are passed to the function. Any formal
# parameters which occur after the *args parameter are ‘keyword-only’ arguments, meaning that
# they can only be used as keywords rather than positional arguments.
""" Normally, these variadic arguments will be last in the list of formal parameters, because
they scoop up all remaining input arguments that are passed to the function. Any formal
parameters which occur after the *args parameter are 'keyword-only' arguments, meaning that
they can only be used as keywords rather than positional arguments.
"""
def concat(*args, sep='/'):
return sep.join(args)

Expand Down
26 changes: 15 additions & 11 deletions src/functions/test_function_decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@


def test_function_decorators():
"""Function Decorators."""
"""Function Decorators.

# Function decorators are simply wrappers to existing functions. Putting the ideas mentioned
# above together, we can build a decorator. In this example let's consider a function that
# wraps the string output of another function by p tags.

# This is the function that we want to decorate.
"""

def greeting(name):
return "Hello, {0}!".format(name)

Expand All @@ -32,12 +34,14 @@ def function_wrapper(name):

# Here we go, we've just decorated the function output without changing the function itself.
assert my_get_text('John') == '<p>Hello, John!</p>' # With decorator.
assert greeting('John') == 'Hello, John!' # Without decorator.
assert greeting('John') == 'Hello, John!'
""" Without decorator.

# Now, Python makes creating and using decorators a bit cleaner and nicer for the programmer
# through some syntactic sugar There is a neat shortcut for that, which is to mention the
# name of the decorating function before the function to be decorated. The name of the
# decorator should be prepended with an @ symbol.
"""

@decorate_with_p
def greeting_with_p(name):
Expand Down Expand Up @@ -65,17 +69,17 @@ def greeting_with_div_p(name):

assert greeting_with_div_p('John') == '<div><p>Hello, John!</p></div>'

# One important thing to notice here is that the order of setting our decorators matters.
# If the order was different in the example above, the output would have been different.

# Passing arguments to decorators.
""" One important thing to notice here is that the order of setting our decorators matters.
If the order was different in the example above, the output would have been different.

# Looking back at the example before, you can notice how redundant the decorators in the
# example are. 2 decorators(decorate_with_div, decorate_with_p) each with the same
# functionality but wrapping the string with different tags. We can definitely do much better
# than that. Why not have a more general implementation for one that takes the tag to wrap
# with as a string? Yes please!
Passing arguments to decorators.

Looking back at the example before, you can notice how redundant the decorators in the
example are. 2 decorators(decorate_with_div, decorate_with_p) each with the same
functionality but wrapping the string with different tags. We can definitely do much better
than that. Why not have a more general implementation for one that takes the tag to wrap
with as a string? Yes please!
"""
def tags(tag_name):
def tags_decorator(func):
def func_wrapper(name):
Expand Down
3 changes: 2 additions & 1 deletion src/functions/test_function_default_arguments.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@ def power_of(number, power=2):


def test_default_function_arguments():
"""Test default function arguments"""
"""Test default function arguments

# This function power_of can be called in several ways because it has default value for
# the second argument. First we may call it omitting the second argument at all.
"""
assert power_of(3) == 9
# We may also want to override the second argument by using the following function calls.
assert power_of(3, 2) == 9
Expand Down
Loading