func(arguments)
notationprint()
, len()
object.method(arguments)
help('FUNCTIONS')
help('METHODS')
help('def')
def mylen(a):
count = 0
for a in a:
count = count +1
return count
str = [1 ,2 ,6, 8]
mylen(str)
v = "Hello World, this is fun"
rv = mylen(v)
print(rv)
help(len)
def func(a, b):
c = a + b
return c
rv = func(2, 3)
print(rv)
def func(a):
count = 2
count = count + a
return count
b = int(input("Enter a number:"))
c = func(b)
print(c)
#defining a function
def func1():
print("Functions in Python")
#calling a function (A function must be defined before it is called)
func1()
func1()
help
function.#defining a function
def func1():
""" This is a docstring that describes what the function do
It simply display a welcome message"""
print("Welcome to Learning Functions in Python")
#calling a function
func1()
# We can access the docstring using the built-in command __doc__.
# Any identifier that starts with a double underscore is a Python builtin command
func1.__doc__
help(func1)
return
statement is used to end the execution of the function or method and send the function’s result back to the caller. A return statement consists of the return
keyword followed by an optional return value.return
statement are not executed.return
keyword without a return value. You can also omit the entire return statement. In both cases, the return value will be None.help('return')
#defining a function
def mysum2():
total = 5 + 7
return total
#calling a function
rv = mysum2()
print("5 + 7 = ", rv)
#Returning multiple values from a function
def func():
str1 = "hello"
str2= "bye"
return str1, str2
#calling a function
rv1, rv2 = func()
print(rv1)
print(rv2)
rv = func()
print(rv)
subtract(a, b)
# A function that is passed two numbers and it returns their sum
def mysum3(a, b):
"""Calculates and return the sum of two numbers.
Arguments:
a - First number
b - Second number
"""
total = a + b
return total
#calling a function
a = 10
b = 15
rv = mysum3(a, b)
print(a, " + ", b, " = ", rv)
help(mysum3)
# A function that receives a list and returns a Number data type containing sum of squares of its elements
def sumofsquares(l1):
rv = 0
for i in l1:
rv = rv + i*i
return rv
#calling a function
list1 = [1, 2, 3]
rv = sumofsquares(list1)
print("Sum of Square of List elements are: ", rv)
print("Return type = ", type(rv))
# A function that receives a list and returns a List data type containing sub-list containing even numbers
def filter_even(number_list):
result_list = []
for number in number_list:
if (number % 2 == 0):
result_list.append(number)
return result_list
even_list = filter_even([1, 2, 3, 4, 5, 6, 7])
even_list
print(type(even_list))
# Function arguments of intrinsic types like int, float, strings are passed by value
def myfunc(nam):
nam = "Arif Butt"
a = "Kakamanna"
print("Before calling: ", a)
rv = myfunc(a)
print("After calling: ", a)
# Function arguments of intrinsic types like int, float, strings are passed by value
def myfunc(x, y, z):
x = x + 1
y = y + 1
z = z + 1
a = 10
b = 20
c = 30
myfunc(a, b, c)
print(a, b, c)
# Lists, Tuples, Sets, and Dictionary objects are passed to functions as reference
# The changes made by the callee are visible to the caller (but not for tuples as they are immutable)
def func1(l1):
l1[2] = 'x'
mylist = ['a', 'b', 'c', 'd', 'e', 'f']
print("Before calling: ", mylist)
func1(mylist)
print("After calling: ", mylist)
# Example:
def func1(list2):
l3 = list2[1:4]
l3[0] = 'x'
print("List l3 is local to the function having: ", l3)
list1 = ['a', 'b', 'c', 'd', 'e', 'f']
print("Before calling: ", list1)
func1(list1)
print("After calling: ", list1)
# Example:
def func1(list2):
l3 = list2[1:4]
print("List l3 is local to the function having: ", l3)
return l3
list1 = ['a', 'b', 'c', 'd', 'e', 'f']
print("Before calling list1: ", list1)
returned_list = func1(list1)
print("After calling list1: ", list1)
print("Returned list is : ", returned_list)
# Tuples are mutable: proof of concept
def func1(t1):
t1[2] = 'x'
mytuple = ('a', 'b', 'c', 'd', 'e', 'f')
print("Before calling: ", mytuple)
func1(mytuple)
print("After calling: ", mytuple)
A List sorting example to differentiate between Pass By Value and Pass by Reference
# Example: The function sort the list that is passed by reference (Selection Sort)
def sel_sort1(mylist):
for i in range(len(mylist)):
min_idx = i
for j in range(i+1, len(mylist)):
if mylist[min_idx] > mylist[j]:
min_idx = j
mylist[i], mylist[min_idx] = mylist[min_idx], mylist[i] # Swap minimum element with the first element
numbers = [25, 15, -6, 8, 2]
rv = sel_sort1(numbers)
print("Passed list is sorted: ", numbers)
print("Returned value: ", rv)
# Example: The function creates a new copy of the list that is passed by reference, sort the copy and return
# The passed list remains unchanged
def sel_sort2(mylist):
newlist = mylist[:]
for i in range(len(mylist)):
min_idx = i
for j in range(i+1, len(mylist)):
if newlist[min_idx] > newlist[j]:
min_idx = j
newlist[i], newlist[min_idx] = newlist[min_idx], newlist[i] # Swap minimum element with the first element
return newlist
numbers = [25, 15, -6, 8, 2]
rv = sel_sort2(numbers)
print("Returned list: ", rv)
print("Passed list is unchanged: ", numbers)
def mysub(a, b):
return a - b
x = 8
y = 3
# calling a function with both arguments (order matters)
rv = mysub(x, y)
rv
mysub(3, 2, 4)
# Function with default arguments
def display(name = 'kakamanna', age = 35):
print ("Name: ", name, ", Age: ", age)
return;
# calling a function with both arguments (order matters)
display("Arif Butt", 51)
# calling a function with one argument only (the default value of age will be printed)
display("Mujahid Butt" )
# You cannot skip the first default argument and give the second
display(,51 )
#Solution is keyword arguments (discussed below)
# Function calling with key word arguments
def display(name, age):
print ("Name: ", name, ", Age: ", age)
return;
# Sequence/order of arguments matter
display(25, "Arif Butt")
# Sequence/order of arguments DOES NOT matter now
display(age=25, name="Mujahid Butt") # passing parameters in any order using keyword argument
def mysub(a, b):
return a - b
# calling a function using named arguments is always a better programming practice
rv = mysub(b = 3, a = 8)
rv
*
) before the variable name.def my_function(*args): # Whatever is passed to this function, it will create an iterable out of it
print(type(args))
my_function('arif','rauf')
print("\n")
# Example: Passing variable number of arguments to a function
def my_function(*args): # Whatever is passed to this function, it will create an iterable out of it
for i in args: # We can use the iter() and next() function to iterate through the iterable
print(i, end=' ')
my_function()
my_function('arif','rauf')
print("\n")
my_function(1, 2, 3, 4, 5, 6, 7, 8)
print("\n")
my_function(5, 2.5, 9)
**kwarg
) is just like variable length arguments (*arg
). The difference is instead of accepting positional arguments, it accepts keyword (or named) arguments.def myfunc(**kwargs):
# Iterating over the key:value pairs of kwargs dictionary
for arg in kwargs.items():
print(arg)
myfunc(a = "Learning", b = 'Is', c = 'Fun')
def myfunc(**kwargs):
result = ""
# Iterating over the values only of kwargs dictionary
for arg in kwargs.values():
print(arg)
myfunc(a = "Learning", b = 'Is', c = 'Fun', d ='with', e='Arif')
def greet(**kwargs):
print('Hello, ', kwargs['fname'], kwargs['mname'], kwargs['lname'])
greet(lname='Butt', fname='Muhammad', mname= 'Arif')
def myconcat(**kwargs):
result = ""
# Iterating over the values of kwargs dictionary
for arg in kwargs.values():
result += arg + ' '
return result
rv = myconcat(a = "Learning", b='Is', c='Fun')
rv
sys.argv
getopt
moduleargparse
module%pycat cmd_arg1.py
# %load cmd_arg1.py
# Python script to demonstrate command line arguments
import sys
# `sys.argv` is a list of command line arguments
n = len(sys.argv) # number of command line arguments.
print("Total arguments passed:", n)
print("\nName of Python script:", sys.argv[0]) #name of the current Python script.
print("\nArguments passed:", end = " ")
for i in range(1, n):
print(sys.argv[i], end = " ")
# add command line arguments and print result
sum = 0
for i in range(1, n):
sum += int(sys.argv[i])
print("\n\nResult:", sum)
%run cmd_arg1.py 5 7 2 -10
def outerFunction():
name = 'Arif'
def innerFunction():
print(name)
innerFunction()
outerFunction()
#innerFunction() # This line will raise a NameErrror
# because an innerFunction() can only be accessed in the outerFunction() body, and not outside it
- Local Scope
- Nonlocal/Enclosing Scope
- Global Scope
- Built-in Scope
Local Scope: Python first tries to search for an identifier (variable) in Local scope. The local variable exists only within the block/function that it is declared in. When that block/function ends, the local variable has no significance, it gets destroyed. We cannot use it outside the function where it is declared.
# Example 1: Understanding Local Scope
# The variable 'bb' declared inside the function is local to that function
# When you try to access (read/write) it outside the function, Python raises a NameError
def my_function():
bb = 1234 # a new local variable named 'a' is created
print("Value of variable 'bb' inside function: ", bb)
my_function()
#print("Value of variable 'bb' outside function: ", bb) #Raise NameError, as the variable 'bb' no longer exists
Enclosing Scope: Enclosing (or nonlocal) scope is a special scope that only exists for nested functions. If Python does not find an identifier (variable) within the local scope, it will examine the Enclosing scope to see if it can find the variable there.
# Example 1: Understanding Enclosing / Non-Local Scope
def f1():
x = 4
def f2():
print(x) #Since there is no variable 'x' defined in f2(), so it will search it in the non-local scope
f2()
print(x) #The variable 'x' is defined in the local scope of f1() function
f1()
# Example 2: Understanding Enclosing / Non-Local Scope
def f1():
cc = 1234 # cc is local variable to f1()
def f2():
cc = 4321 # cc is local variable to f2()
print("Inside the f2() function: cc = ", cc)
f2()
print("Inside the f1() function: cc = ", cc)
f1()
- Global Scope: A global variable is accessible from anywhere in your script, including from within a function. It is usually defined at the top of the script or outside of the function.
- Python first tries to find an identifier in the local scope, then in the non-local/enclosing scope. If it cannot find it in those two scopes then it will search the identifier in the global scope.
# Example 1: Understanding Global Scope
b = 9999 # a global variable
def my_function():
print("Value of variable 'b' inside function: ", b)
my_function()
print("Value of global variable 'b' outside function: ", b)
# Example 2: Understanding Global Scope
c = 1234 # a global variable named 'c'
def my_function():
c = 4321 # a new local variable named 'c' is created
print("Value of variable 'c' inside function: ", c)
my_function()
# Over here the local variable c containing 4321 does not exist, therefore, Python interpreter will look
# in the non-local/enclosing scope, it also doesnot contain variable c, so
# finally the Python interpreter will look in the global scope, where it exist with value of 1234
print("Value of variable 'c' outside function: ", c)
- The Built-in scope has all the functions and variables that are there, when we start the Python interpreter, e.g., the
print()
,len()
andid()
functions are in the built-in scope.- If an identifier is not found in local, enclosing and global scopes within a module, then Python will examine the built-in scope to see if it is defined there.
# Example: Since the identifier `len` is not found in local, enclosing and global scopes, therefore,
# Python would consult the Built-In scope, where it will find the len function and outputs 12
x = len ('Data Science')
print(x)
# Example: Since the identifier `len` is there in the local scope, therefore
# Python would use the `len` function defined in local scope and not the Built-In scope, and outputs 54
def len(x):
return 54
x = len('Data Science')
print(x)
global
Keyword¶
- The
global
keyword is used to tell the Python interpreter to use the globally defined variable instead of locally defining it.- Let us understand this with example:
We cannot update the value of a global variable inside a function (local scope). If you try to do so it will raise an error
# Example:
c = 1234 # c is a global variable
def my_function():
c = c + 1 # Updating global variable inside function
print("Value of variable 'c' inside function: ", c)
my_function()
print("Value of variable 'c' outside function: ", c)
If you want to update the value of a global variable inside a function, simply type global
followed by the variable name. This will tell Python interpreter to use the globally defined variable instead of locally defining it
# Example: To update a global variable inside a function, you use the global keyword
d = 1234
def my_function():
global d # global keyword does not create a new local variable, rather allows you to access the global var
d = d + 1 # Updating global variable inside function
print("Value of variable 'd' inside function: ", d)
my_function()
print("Value of variable 'd' outside function: ", d)
nonlocal
Keyword¶
- Python
nonlocal
keyword is used to make the variable which refers to the variable bounded in the nearest scope.- Scope to which variable it bound should not be global or local scope.
- The main use of nonlocal variable is in a nested function.
# Example 1: You get an error if you try to update a non-local variable inside a function
def f1():
a = 1234
def f2():
a = a + 1
print("Inside the f2() function: a = ", a)
f2()
print("Inside the f1() function: a = ", a)
f1()
# Example 2: To update a nonlocal variable inside the inner function, you use the nonlocal keyword
def f1():
a = 1234
def f2():
nonlocal a
a = a + 1
print("Inside the f2() function: a = ", a)
f2()
print("Inside the f1() function: a = ", a)
f1()
# QUIZ: Give the output by assuming memory addresses at your own.
# Do mention the scope of all the identifiers used
x = 5
print(x, id(x))
def number():
x = 3
print(x, id(x))
def f1():
nonlocal x
x = x * 5
print(x, id(x))
f1()
def numb():
global x
x = x * 5
print(x, id(x))
number()
numb()
print(x, id(x))
Try answering the following questions to test your understanding of the topics covered in this notebook:
return
keyword in Python?return
statement be used inside an if
block or a for
loop?return
keyword be used outside a function?sys.argv[]
, and getopt.getopt()
a = 5
print(a)
def myfunc():
a = 3
print(a)
def f1():
nonlocal a
a = a * 2
print(a)
f1()
print(a)
myfunc()
print(a)