Contents
1 The return
statement
The statement return
exits a function, optionally passing back an expression to the caller. A return
statement with no arguments is the same as return None
.
All the above examples are not returning any value. You can return a value from a function as follows −
#!/usr/bin/python
# Function definition is here
def sum( arg1, arg2 ):
# Add both the parameters and return them."
total = arg1 + arg2
print "Inside the function : ", total
return total;
# Now you can call sum function
total = sum( 10, 20 );
print "Outside the function : ", total
When the above code is executed, it produces the following result −
Inside the function : 30
Outside the function : 30
2 Documentation Strings
Here are some conventions about the content and formatting of documentation strings.
The first line should always be a short, concise summary of the object’s purpose. For brevity, it should not explicitly state the object’s name or type, since these are available by other means (except if the name happens to be a verb describing a function’s operation). This line should begin with a capital letter and end with a period.
If there are more lines in the documentation string, the second line should be blank, visually separating the summary from the rest of the description. The following lines should be one or more paragraphs describing the object’s calling conventions, its side effects, etc.
The Python parser does not strip indentation from multi-line string literals in Python, so tools that process documentation have to strip indentation if desired. This is done using the following convention. The first non-blank line after the first line of the string determines the amount of indentation for the entire documentation string. (We can’t use the first line since it is generally adjacent to the string’s opening quotes so its indentation is not apparent in the string literal.) Whitespace “equivalent” to this indentation is then stripped from the start of all lines of the string. Lines that are indented less should not occur, but if they occur all their leading whitespace should be stripped. Equivalence of whitespace should be tested after expansion of tabs (to 8 spaces, normally).
Here is an example of a multi-line docstring:
>>> def my_function():
... """Do nothing, but document it.
...
... No, really, it doesn't do anything.
... """
... pass
...
>>> print(my_function.__doc__)
Do nothing, but document it.
No, really, it doesn't do anything.
3 Scope of Variables
All variables in a program may not be accessible at all locations in that program. This depends on where you have declared a variable.
The scope of a variable determines the portion of the program where you can access a particular identifier. There are two basic scopes of variables in Python −
- Global variables
- Local variables
Variables that are defined inside a function body have a local scope, and those defined outside have a global scope.
This means that local variables can be accessed only inside the function in which they are declared, whereas global variables can be accessed throughout the program body by all functions. When you call a function, the variables declared inside it are brought into scope. Following is a simple example −
#!/usr/bin/python
total = 0; # This is global variable.
# Function definition is here
def sum( arg1, arg2 ):
# Add both the parameters and return them."
total = arg1 + arg2; # Here total is local variable.
print "Inside the function local total : ", total
return total;
# Now you can call sum function
sum( 10, 20 );
print "Outside the function global total : ", total
When the above code is executed, it produces the following result −
Inside the function local total : 30
Outside the function global total : 0
4 Namespaces in Python
4.1 The Built-In Namespace
The built-in namespace contains the names of all of Python’s built-in objects. These are available at all times when Python is running. You can list the objects in the built-in namespace with the following command:
>>> dir(__builtins__)
['ArithmeticError', 'AssertionError', 'AttributeError',
'BaseException','BlockingIOError', 'BrokenPipeError', 'BufferError',
'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError',
'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError',
'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError',
'Exception', 'False', 'FileExistsError', 'FileNotFoundError',
'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError',
'ImportError', 'ImportWarning', 'IndentationError', 'IndexError',
'InterruptedError', 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt',
'LookupError', 'MemoryError', 'ModuleNotFoundError', 'NameError', 'None',
'NotADirectoryError', 'NotImplemented', 'NotImplementedError', 'OSError',
'OverflowError', 'PendingDeprecationWarning', 'PermissionError',
'ProcessLookupError', 'RecursionError', 'ReferenceError', 'ResourceWarning',
'RuntimeError', 'RuntimeWarning', 'StopAsyncIteration', 'StopIteration',
'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError',
'TimeoutError', 'True', 'TypeError', 'UnboundLocalError',
'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError',
'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError',
'Warning', 'ZeroDivisionError', '_', '__build_class__', '__debug__',
'__doc__', '__import__', '__loader__', '__name__', '__package__',
'__spec__', 'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'bytearray',
'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex',
'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate',
'eval', 'exec', 'exit', 'filter', 'float', 'format', 'frozenset',
'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input',
'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list',
'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct',
'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr',
'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod',
'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']
You’ll see some objects here that you may recognize from previous tutorials—for example, the StopIteration exception, built-in functions like max()
and len()
, and object types like int and str.
The Python interpreter creates the built-in namespace when it starts up. This namespace remains in existence until the interpreter terminates.
4.2 The Global Namespace
The global namespace contains any names defined at the level of the main program. Python creates the global namespace when the main program body starts, and it remains in existence until the interpreter terminates.
Strictly speaking, this may not be the only global namespace that exists. The interpreter also creates a global namespace for any module that your program loads with the import statement. For further reading on main functions and modules in Python, see these resources:
- Defining Main Functions in Python
- Python Modules and Packages—An Introduction
- Course: Python Modules and Packages
You’ll explore modules in more detail in a future tutorial in this series. For the moment, when you see the term global namespace, think of the one belonging to the main program.
4.3 The Local and Enclosing Namespaces
As you learned in the previous tutorial on functions, the interpreter creates a new namespace whenever a function executes. That namespace is local to the function and remains in existence until the function terminates.
Functions don’t exist independently from one another only at the level of the main program. You can also define one function inside another:
>>> def f():
... print('Start f()')
...
... def g():
... print('Start g()')
... print('End g()')
... return
...
... g()
...
... print('End f()')
... return
...
>>> f()
Start f()
Start g()
End g()
End f()
In this example, function g() is defined within the body of f(). Here’s what’s happening in this code:
- Lines 1 to 12 define
f()
, the enclosing function. - Lines 4 to 7 define
g()
, the enclosed function. - On line 15, the main program calls
f()
. - On line 9,
f()
callsg()
.
When the main program calls f()
, Python creates a new namespace for f()
. Similarly, when f()
calls g()
, g()
gets its own separate namespace. The namespace created for g()
is the local namespace, and the namespace created for f()
is the enclosing namespace.
Each of these namespaces remains in existence until its respective function terminates. Python might not immediately reclaim the memory allocated for those namespaces when their functions terminate, but all references to the objects they contain cease to be valid.
5 Recursion
5.1 What is recursion?
Recursion is the process of defining something in terms of itself.
A physical world example would be to place two parallel mirrors facing each other. Any object in between them would be reflected recursively.
5.2 Python Recursive Function
In Python, we know that a function can call other functions. It is even possible for the function to call itself. These types of construct are termed as recursive functions.
The following image shows the working of a recursive function called recurse
.
Following is an example of a recursive function to find the factorial of an integer.
Factorial of a number is the product of all the integers from 1 to that number. For example, the factorial of 6 (denoted as 6!) is 1*2*3*4*5*6 = 720
.
Example of a recursive function
def factorial(x):
"""This is a recursive function
to find the factorial of an integer"""
if x == 1:
return 1
else:
return (x * factorial(x-1))
num = 3
print("The factorial of", num, "is", factorial(num))
Output
The factorial of 3 is 6
In the above example, factorial()
is a recursive function as it calls itself.
When we call this function with a positive integer, it will recursively call itself by decreasing the number.
Each function multiplies the number with the factorial of the number below it until it is equal to one. This recursive call can be explained in the following steps.
factorial(3) # 1st call with 3
3 * factorial(2) # 2nd call with 2
3 * 2 * factorial(1) # 3rd call with 1
3 * 2 * 1 # return from 3rd call as number=1
3 * 2 # return from 2nd call
6 # return from 1st call
Let’s look at an image that shows a step-by-step process of what is going on:
Our recursion ends when the number reduces to 1. This is called the base condition.
Every recursive function must have a base condition that stops the recursion or else the function calls itself infinitely.
The Python interpreter limits the depths of recursion to help avoid infinite recursions, resulting in stack overflows.
By default, the maximum depth of recursion is 1000
. If the limit is crossed, it results in RecursionError
. Let’s look at one such condition.
def recursor():
recursor()
recursor()
Output
Traceback (most recent call last):
File "<string>", line 3, in <module>
File "<string>", line 2, in a
File "<string>", line 2, in a
File "<string>", line 2, in a
[Previous line repeated 996 more times]
RecursionError: maximum recursion depth exceeded
5.3 Advantages of Recursion
- Recursive functions make the code look clean and elegant.
- A complex task can be broken down into simpler sub-problems using recursion.
- Sequence generation is easier with recursion than using some nested iteration.
5.4 Disadvantages of Recursion
- Sometimes the logic behind recursion is hard to follow through.
- Recursive calls are expensive (inefficient) as they take up a lot of memory and time.
- Recursive functions are hard to debug.
6 Exercise
Q: Use a function to implement a program to determine whether the year entered by the user is a leap year.
- Years divisible by 400.
- A year that is divisible by 4 but not divisible by 100.
One of the above two methods is a leap year.
def year_judge():
a = input('Please enter a year: ')
if a.isdigit() and eval(a)>0:
b = int(a)
if b % 400 == 0 or b % 4 == 0 and b % 100 != 0:
print('%s is leap year.'%a)
else:
print('%s is common year.'%a)
else:
year_judge()
year_judge()
Q: Monkey eating peach problem (recursion):
A monkey plucked a few peaches on the first day and ate half of it immediately. It was not enough, so it ate one more peach. The next morning it ate half of the remaining peaches and ate one more. From now on, it eats half of the amount left over from the previous day every morning and eats one more. By the morning of the 10th day when the monkey wanted to eat again, only one peach was left. How many peaches were picked on the first day?
def func1(day):
return 1 if day == 10 else 2 * (func1(day+1) + 1)
func1(1)
The result is 1534