python tutorial - Python Functions - Def, *Arg, **Kwargs - learn python - python programming




Functions def

  • The def create a function object and assigns it to a name. Its general format is:
def <name>(arg1, arg2,...,argN)
	<statement>
click below button to copy the code. By Python tutorial team
  • The statement block becomes the function's body. The def header line specifies a function name and the function bodies often contain a return statement:
def <name>(arg1, arg2,...,argN)
	return <value>
click below button to copy the code. By Python tutorial team
  • The notable thing here is that the function doesn't define a return datatype.
  • Python functions do not specify the datatype of their return value. They don't even specify whether or not they return a value.
  • Actually, however, every Python function returns a value if the function ever executes a return statement, and it will return that value. Otherwise, it will return None.
  • Everything in Python is a function, all functions return a value even if it is None, and all functions start with def.
  • def is an executable code.
    • Python functions are written with a new statement, the def. Unlike functions in compiled language def is an executable statement.
    • Our function does not exist until Python reaches and runs the def.
    • Actually, it's legal to nest def statements inside if statement, while loops, and even other defs.
    • In general, def statements are coded in module files and are naturally run to generate functions when a module file is first imported.
  • def creates an object and assigns it to a name.
    • When Python reaches and runs a def statement, it generates a new function object and assigns it to the function's name.
    • As with all assignments, the function name becomes a reference to the function object.
    • There's nothing magic about the name of a function. The function object can be assigned to other names, stored in a list, and so son.
    • Functions objects may also have arbitrary user-defined attributes attached to them to record data.
  • return sends a result object back to the caller.
    • When a function is called, the caller stops until the function finishes its work and returns control to the caller.
    • Functions that compute a value send it back to the caller with a return statement. The returned value becomes the result of the function call.

def Execute at Runtime

  • The def is an executable statement. When it runs, it creates a new function object and assigns it to a name.
  • Because it's a statement, a def can appear anywhere a statement can even nested in other statements:
# function.py
def func():
    print('func()')
    def func1():
        print('func1')
        def func2():
            print('func2')
        func2()
    func1()

func()
click below button to copy the code. By Python tutorial team
  • Output should look like this:
$ python function.py
func()
func1
func2
  • Because function definition happens at runtime, there's nothing special about the function name. What's important is the object to which it refers:
>>> def func():
    print('func()')
    def func1():
        print('func1')
        def func2():
            print('func2')
        func2()
    func1()

>>> othername = func    # Assign function object
>>> othername()         # Call func again
func()
func1
func2
>>> othername2 = func() # Call func one more time
func()
func1
func2
click below button to copy the code. By Python tutorial team
  • Here, the function was assigned to a different name and called through the new name. Functions are just object.
  • They are recorded explicitly in memory at program execution time.
  • In fact, besides calls, functions allow arbitrary attributes to be attached to record information for later use:
def func():...		# Create function object
func()			# Call object
func.attr = value	# Attach attributes
click below button to copy the code. By Python tutorial team

Definitions and Calls

  • Here, we typed the definition of a function, times, interactively. It returns the product of its two arguments:
>>> # Create and assign function
>>> def times(x, y):     # Create and assign function
	return x * y     # Body executed when called

>>> times(2, 5)          # Arguments in parentheses
10
click below button to copy the code. By Python tutorial team
  • When Python reaches and runs this def, it creates a new function object that packages the function's code and assigns the object to the name times.
  • After the def has run, we can call (run) the function as shown above.
  • The times function's body is just a return statement that sends back the result as the value of the call.
  • If we want to use it later we could instead assign it to a variable:
>>> x = times(365,5)
>>> x
1825
click below button to copy the code. By Python tutorial team
  • Let's call the function again with different objects passed in:
>>> times('blah!', 4)
'blah!blah!blah!blah!'
click below button to copy the code. By Python tutorial team
  • That was possible because we never declared the types of variables , argument, or return values in Python.
  • We can use times to either multiply numbers or repeat sequences. In other words, what our times function means depends on what we pass into it.
  • This is core idea in Python and it is polymorphism.

Intersecting Sequences

  • Let's make a function that collects items held in common in two strings:
>>> def intersect(seq1, seq2):
	res = []			# Start empty
	for x in seq1:			# Scan seq1
		if x in seq2:		# Common item?
			res.append(x)	# Add to the end
	return res
click below button to copy the code. By Python tutorial team
  • The algorithm of the function is:
  • for every item in the first argument, if that item is also in the second argument, append the item to the result.
  • Now, let's call the intersect function:
>>> s1 = "WORLD"
>>> s2 = "WORDS"
>>> intersect(s1, s2)
['W', 'O', 'R', 'D']
click below button to copy the code. By Python tutorial team
  • We could have used a single list comprehension expression giving the same result:
>>> 
>>> [x for x in s1 if x in s2]
['W', 'O', 'R', 'D']
>>> 
click below button to copy the code. By Python tutorial team
  • The function intersect is polymorphic. It works on arbitrary types as long as they support the expected object interface:
>>> 
>>> x = intersect([1, 2, 3],(1, 4))	# Mixed types
>>> x
[1]
>>> 
click below button to copy the code. By Python tutorial team
  • We passed in different types of objects: a list and a tuple.
  • It's working because we don't have to specify the types of argument ahead of time.
  • For intersect, this means that the first argument should support the for loop and the second has to support the in membership test.
  • If we pass in objects that do not support these interfaces (e.g., numbers), Python will detect mismatch and raise an exception:
>>> 
>>> x = intersect(1, 4)
Traceback (most recent call last):
  File "<pyshell#35>", line 1, in <module>
    x = intersect(1, 4)
  File "<pyshell#22>", line 3, in intersect
    for x in seq1:			# Scan seq1
TypeError: 'int' object is not iterable
>>> 
</pyshell#22></module></pyshell#35>
click below button to copy the code. By Python tutorial team

Local Variables

  • The variable res inside intersect is what is called a local variable. It is visible only to code inside the function def and that exists only while the function runs.
  • All names assigned inside a function are classified as local variables by default.
  • They appear when the function is called and disappear when the function exits.
  • The return statement at the end of intersect sends back the result object, but the name res goes away.

Argument Matching

Keyword

  • Here is the keyword example:
>>> def f(a, b, c):
	print(a, b, c)
	
>>> f(1, 2, 3)
1 2 3
>>> f(c=3, b=2, a=1)
1 2 3
>>> f(1, c=3, b=2)
1 2 3
click below button to copy the code. By Python tutorial team

Default

>>> def f(a, b=2, c=3):
	print(a, b, c)

>>> f(1)
1 2 3
>>> f(10, 50)
10 50 3
>>> f(10, 70, 90)
10 70 90
>>> f(10, 200)
10 200 3
click below button to copy the code. By Python tutorial team

Argument Matching Table

Syntax Location Descruption
func(value) Caller Normal argument: matched by position
func(name=value) Caller Keyword argument: matched by name
func(*sequence) Caller Pass all object in sequence as individual positional arguments
func(**dict) Caller Pass all key/value pairs in dict as individual keyword arguments
def func(name) Function Normal argument: matched any passed value by position or name
def func(name=value) Function Default argument value, if not passed in the call
def func(*name) Function Matches and collects remaining positional arguments in a tuple
def func(**name) Function Matches and collects remaining keyword arguments in a dictionary
def func(*args, name) Function Arguments that must be passed by keyword only in calls

*args and **kwargs - Collecting and Unpacking Arguments

  • Putting *args and/or **kwargs as the last items in our function definition's argument list allows that function to accept an arbitrary number of anonymous and/or keyword arguments.
  • Those arguments are called Keyword Arguments. Actually, they are place holders for multiple arguments, and they are useful especially when we need to pass a different number of arguments each time we call the function.
  • We may want to use *args when we're not sure how many arguments might be passed to our function, i.e. it allows us to pass an arbitrary number of arguments to our function.

Collecting arguments

>>> def f(*args):
	print(args)
	
>>> f()
()
>>> f(10)
(10,)
>>> f(10, 20, 30)
(10, 20, 30)
click below button to copy the code. By Python tutorial team
  • When the f() is called, Python collects all the positional arguments into a new tuple and assigns the variable args to that tuple. Since it is a normal tuple object, it can be indexed:
>>> def print_all(*args):
	for x in enumerate(args):
		print x
		
>>> print_all('A','b','b','a')
(0, 'A')
(1, 'b')
(2, 'b')
(3, 'a')
click below button to copy the code. By Python tutorial team
  • We can pass in lists for the args:
>>> def print_all(*args):
...    for x in enumerate(args):
...       print x
... 
>>> print_all([1,2,3],[4,5,6])
(0, [1, 2, 3])
(1, [4, 5, 6])
click below button to copy the code. By Python tutorial team
  • The ** is similar but it only works for keyword arguments. In other words, it collects them into a new dictionary. Actually, ** allows us to convert from keywords to dictionaries:
>>> def f(**kwargs):
	print(kwargs)
	
>>> f()
{}
>>> f(a=10, b=20)
{'a': 10, 'b': 20}
click below button to copy the code. By Python tutorial team
  • The keyword arguments is a special name=value syntax in function calls that specifies passing by name.
  • It is often used to provide configuration options.
>>> def kwargs_function(**kwargs):
	for k,v in kwargs.items():
		print (k,v)

>>> kwargs_function(**{'uno':'one','dos':'two','tres':'three'})
('dos', 'two')
('tres', 'three')
('uno', 'one')
>>>
>>> kwargs_function(dos='two', tres='three', uno='one')
('dos', 'two')
('tres', 'three')
('uno', 'one')
click below button to copy the code. By Python tutorial team

Unpacking arguments

  • We can use the * or ** when we call a function. In other words, it unpacks a collection of arguments, rather than constructing a collection of arguments.
  • In the following example, we pass five arguments to a function in a tuple and let Python unpack them into individual arguments:
>>> def f(a, b, c, d, e):
	print(a, b, c, d, e)
	
>>> args = (10, 20)
>>> args += (30, 40, 50))
>>> f(*args)
10 20 30 40 50
click below button to copy the code. By Python tutorial team
  • In the same way, the ** in a function call unpacks a dictionary of key/value pairs into separate keyword arguments:
>>> kwargs = {'a':10, 'b':20, 'c':30}
>>> kwargs['d']=40
>>> kwargs['e']=50
>>> f(**kwargs)
10 20 30 40 50
click below button to copy the code. By Python tutorial team
  • Also, with various combinations:
>>> f(*(10, 20), **{'d':40, 'e':50, 'c':30})
10 20 30 40 50
>>> f(10, *(20, 30), **{'d':40, 'e':50})
10 20 30 40 50
>>> f(10, c = 30, *(20,), **{'d':40, 'e':50})
10 20 30 40 50
>>> f(10, *(20,30), d=40, e=50)
10 20 30 40 50
>>> f(10, *(20,), c=30, **{'d':40, 'e':50})
10 20 30 40 50
click below button to copy the code. By Python tutorial team
  • Let's test what we've learned so far:
def fnc(*args, **kwargs):
   print('{} {}'.format(args, kwargs))

print('fnc()')
fnc()
fnc(1,2,3)
fnc(1,2,3,'flask')
fnc(a=1, b=2, c=3)
fnc(a=1, b=2, c=3, d='ansible')
fnc(1, 2, 3, a=1, b=2, c=3)

lst = [1,2,3]
tpl = (4,5,6)
dct = {'a':7, 'b':8, 'c':9}

fnc(*lst, **dct)
fnc(*tpl, **dct)

fnc(1,2,*lst)
fnc(1,2,*tpl)
fnc('jupyter',**dct)
fnc(arg='django',**dct)
fnc(1,2,*tpl,q='bottle',**dct)
print

def fnc2(arg1, arg2, *args, **kwargs):
   print('{} {} {} {}'.format(arg1, arg2, args, kwargs))

print('fnc2()')
#fnc2() # error
fnc2(1,2)
fnc2(1,2,3,'haystack')
fnc2(arg1=1, arg2=2, c=3)
fnc2(arg1=1, arg2=2, c=3, d='Spark')
fnc2(1,2,3, a=1, b=2)
fnc2(*lst, **dct)
fnc2(*tpl, **dct)
fnc2(1,2,*tpl)
fnc2(1,*tpl,d='nltk')
fnc2(1,2,*tpl,d='scikit')
click below button to copy the code. By Python tutorial team

Output:

fnc()
() {}
(1, 2, 3) {}
(1, 2, 3, 'flask') {}
() {'a': 1, 'c': 3, 'b': 2}
() {'a': 1, 'c': 3, 'b': 2, 'd': 'ansible'}
(1, 2, 3) {'a': 1, 'c': 3, 'b': 2}
(1, 2, 3) {'a': 7, 'c': 9, 'b': 8}
(4, 5, 6) {'a': 7, 'c': 9, 'b': 8}
(1, 2, 1, 2, 3) {}
(1, 2, 4, 5, 6) {}
('jupyter',) {'a': 7, 'c': 9, 'b': 8}
() {'a': 7, 'c': 9, 'b': 8, 'arg': 'django'}
(1, 2, 4, 5, 6) {'a': 7, 'q': 'bottle', 'c': 9, 'b': 8}

fnc2()
1 2 () {}
1 2 (3, 'haystack') {}
1 2 () {'c': 3}
1 2 () {'c': 3, 'd': 'Spark'}
1 2 (3,) {'a': 1, 'b': 2}
1 2 (3,) {'a': 7, 'c': 9, 'b': 8}
4 5 (6,) {'a': 7, 'c': 9, 'b': 8}
1 2 (4, 5, 6) {}
1 4 (5, 6) {'d': 'nltk'}
1 2 (4, 5, 6) {'d': 'scikit'}

Arbitrary function

  • In the code below, we support any function with any arguments by passing along whatever arguments that were sent in:
>>> def A_function(f, *args, **kwargs):
	return f(*args, **kwargs)

>>> def f(a, b, c, d, e):
	return a*b*c*d*e

>>> print(A_function(f, 10, 20, c=30, d=40, e=50))
12000000
click below button to copy the code. By Python tutorial team
  • When the code is run, arguments are collected by the A_function.

apply() - deprecated

f(*args, **kwargs)         # newer call syntax: f(*sequence, **dict)
apply(f, args, kwargs)     # deprecated built-in: apply(f, sequence, dict)
click below button to copy the code. By Python tutorial team
  • The following function accepts any number of positional or keyword arguments:
>>> def echo(*args, **kwargs):
	print(args, kwargs)

>>> echo(10, 20, a=30, b=40)
(10, 20) {'a': 30, 'b': 40}
click below button to copy the code. By Python tutorial team
  • If we use the apply():
>>> args = (10, 20)
>>> kwargs = {'a':30, 'b':40}

>>> def echo(*args, **kwargs):
	print(args, kwargs)
	
>>> apply(echo, args, kwargs)
((10, 20), {'a': 30, 'b': 40})
>>> echo(*args, **kwargs)
((10, 20), {'a': 30, 'b': 40})
click below button to copy the code. By Python tutorial team

Related Searches to Python Functions - Def, *Arg, **Kwargs