Python-depth explanation of the parameters used in the function parameters and the default trap

This article describes the Python function parameters and default parameters trap, the function will be divided into text parameters mandatory parameters, default parameters, variable parameters and keyword parameters is concerned, to friends can refer to the following
in C ++ function can set the default parameters, Java can not, can only be achieved by overloading the way, in python also can set the default parameters, the biggest benefit is to reduce the difficulty of the function, the function definition is only one, and python is a dynamic language, in the same name space can not have wanted more than the name of the function, if there is, it will appear after covering the front of the function.

def power(x, n=2):
  s = 1
  while n > 0:
    n = n - 1
    s = s * x
  return s

Look at the results:

>>> power(5)
25
>>> power(5,3)
125

Note: Required parameter first, followed by the default parameters, otherwise the Python interpreter will complain.
Recommendation: * When there is a function of several parameters, the parameters put in front of big changes, small changes in parameters put back. Small changes in parameters can be used as the default parameters.
The default parameters have pit, look at the following code to define a list, add a back end:

def add_end(L=[]):
  L.append('END')
  return L

Call to see the results:

>>> add_end([1, 2, 3])
[1, 2, 3, 'END']
>>> add_end(['x', 'y', 'z'])
['x', 'y', 'z', 'END']
>>> add_end()
['END']
>>> add_end()
['END', 'END']
>>> add_end()
['END', 'END', 'END']

It should explain, Python function defined at the time, the default value of the parameter L was calculated out, i.e., []. At this point L []. So if the content of L change the contents of the next call is no longer referenced [] a. So keep in mind that the definition of default parameters must point immutable objects! .

Variable parameter
the first method, the parameter passed to a list or tuple.

def calc(numbers):
  sum = 0
  for n in numbers:
    sum = sum + n * n
  return sum

Invocation:

>>> calc([1, 2, 3])
14
>>> calc((1, 3, 5, 7))
84

The second embodiment, a plurality of parameters directly into the internal function automatically received by a tuple.

def calc(*numbers):
  sum = 0
  for n in numbers:
    sum = sum + n * n
  return sum

Invocation:

>>> calc(1, 2)
5
>>> calc()
0

If you want this time a list or tuple in the data transfer into account, it can be:

>>> nums = [1, 2, 3]
>>> calc(*nums)
14

Keyword arguments
keyword arguments allow you pass 0 or any number of parameters including the parameter name, these keyword parameters are automatically assembled into a dict inside the function.

def person(name, age, **kw):
  print 'name:', name, 'age:', age, 'other:', kw

Call:

>>> person('Michael', 30)
name: Michael age: 30 other: {}
>>> person('Bob', 35, city='Beijing')
name: Bob age: 35 other: {'city': 'Beijing'}
>>> person('Adam', 45, gender='M', job='Engineer')
name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}

Parameter combination
defined in function Python, can be a mandatory parameter, default parameters and the variable parameters keyword parameters, these four parameters may be used together, or only some, but please note that the order parameters are defined to be They are: mandatory parameters, default parameters, variable parameters and keyword parameters.
Recursive function
basic nothing to talk about, and Java / C ++ in the same, that call one's own. Here focus on what tail recursion optimization. In fact tail recursive loop and effect is the same, it is clear that one advantage is that we can prevent the recursive call stack overflow.
Definition: calls itself when the function returns, and, return statement can not contain expressions. Compiler or interpreter can do to optimize it, no matter how many times to call, it only takes a stack frame, overflow does not occur.
Here is a simple example to the factorial function as an example:

def fact(n):
  if n==1:
    return 1
  return n * fact(n - 1)

If the incoming n is large, it may overflow, which is due to return n * fact (n - 1) introduces a multiplication expression, it is not tail recursion. The change to the code:

def fact(n):
  return fact_iter(n, 1)
 
def fact_iter(num, product):
  if num == 1:
    return product
  return fact_iter(num - 1, num * product)

The default parameters trap
function definition Python provides the default parameters are selected such that the function definition and use of more flexible, but also bring some pit, for example, before an example:
function definition:

def add_end(L=[]):
  L.append('END')
  return L

The result of calling the function:

>>> add_end([1, 2, 3])
[1, 2, 3, 'END']
>>> add_end(['x', 'y', 'z'])
['x', 'y', 'z', 'END']
>>> add_end()
['END']
>>> add_end()
['END', 'END']
>>> add_end()
['END', 'END', 'END']

It is clear that the definition does not match the original intention of the function, one sentence explanation is:
the Default values are computed Once, the then Re-Used.
In order to study this issue, we look at another example:

# coding=utf-8
 
def a():
  print "a executed"
  return []
 
def b(x=a()):
  print "id(x):", id(x)
  x.append(5)
  print "x:", x
 
for i in range(2):
  print "不带参数调用,使用默认参数"
  b()
  print b.__defaults__
  print "id(b.__defaults__[0]):", id(b.__defaults__[0])
 
for i in range(2):
  print "带参数调用,传入一个list"
  b(list())
  print b.__defaults__
  print "id(b.__defaults__[0]):", id(b.__defaults__[0])

NOTE: explain a little, all the default values are stored in __defaults__ property function object, which is a list of each element are a default parameter values.
Take a look at the output:

a executed
不带参数调用,使用默认参数
id(x): 140038854650552
x: [5]
([5],)
id(b.__defaults__[0]): 140038854650552
不带参数调用,使用默认参数
id(x): 140038854650552
x: [5, 5]
([5, 5],)
id(b.__defaults__[0]): 140038854650552
带参数调用,传入一个list
id(x): 140038854732400
x: [5]
([5, 5],)
id(b.__defaults__[0]): 140038854650552
带参数调用,传入一个list
id(x): 140038854732472
x: [5]
([5, 5],)
id(b.__defaults__[0]): 140038854650552

Simple analysis of the output:
Line 1
in the definition of the function B (), i.e. def statement execution code line 7 def b (x = a ( )): when these words using default parameters, defined in when will calculate the default value of the parameter x, and this time will call a (), so print out a executed.
6 second to line
the first time through the loop, the code on line 14 to call B () does not pass the parameters, using default parameters, when x = [], so that after a single call

print b.__defaults__

The output is

([5],)

7 to 11 of the row
of the second cycle, the first 14 lines of code to call B () does not pass the parameters, using default parameters.
Note: the default parameters will be counted only once, which means that memory area is fixed, but the address pointed to a list, the content can be changed at this time because the last call x: [5], so

print b.__defaults__

The output is

([5, 5],)

12 to 16 rows of
the second loop, the first loop, the first line of code 20 of incoming List empty, the default parameters is not used, then x = [], so

print b.__defaults__

The output is

([5],)

21, line 18 to
the second loop, the second cycle, the code line 20 passed a List empty, it does not use the default parameters, is still the case x = [], so

print b.__defaults__

The output will still be

([5],)

Functions are objects, so when the definition is executed, default parameters are a function of the property, its value may change as the function is called. Other objects are not all true?
Keep in mind: the default parameters must point to the same objects! Code change as follows:

# coding=utf-8
 
def a():
  print "a executed"
  return None
 
def b(x=a()):
  print "id(x):", id(x)
  if x is None:
    x = []
  x.append(5)
  print "x:", x
 
for i in range(2):
  print "不带参数调用,使用默认参数"
  b()
  print b.__defaults__
  print "id(b.__defaults__[0]):", id(b.__defaults__[0])
 
for i in range(2):
  print "带参数调用,传入一个list"
  b(list())
  print b.__defaults__
  print "id(b.__defaults__[0]):", id(b.__defaults__[0])

Output at this time to see what the result is:

a executed
不带参数调用,使用默认参数
id(x): 9568656
x: [5]
(None,)
id(b.__defaults__[0]): 9568656
不带参数调用,使用默认参数
id(x): 9568656
x: [5]
(None,)
id(b.__defaults__[0]): 9568656
带参数调用,传入一个list
id(x): 140725126699632
x: [5]
(None,)
id(b.__defaults__[0]): 9568656
带参数调用,传入一个list
id(x): 140725126699704
x: [5]
(None,)
id(b.__defaults__[0]): 9568656

I write to you, for everyone to recommend a very wide python learning resource gathering, click to enter , there is a senior programmer before learning to share experiences, study notes, there is a chance of business experience, and for everyone to carefully organize a python zero the basis of the actual project data, daily python to you on the latest technology, prospects, learning to leave a message of small details

Published 34 original articles · won praise 51 · views 40000 +

Guess you like

Origin blog.csdn.net/haoxun10/article/details/104806026