函数的参数(Python)

位置参数

调用函数时根据函数定义的参数位置来传递参数。

编写x的n次方的函数

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

x,n为位置函数,两个参数的顺序必须一一对应,且少一个参数都不行。


默认参数

为避免代码少一个参数而无法正常调用,故使用默认参数。

还是编写x的n次方的函数

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

当调用power(9)时,相当用调用power(9, 2)

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

从上面的例子可以看出,默认参数可以简化函数的调用。设置默认参数时,有几点要注意:

1. 必选参数在前,默认参数在后,否则Python的解释器会报错;

2. 是如何设置默认参数

当函数有多个参数时,把变化大的参数放前面,变化小的参数放后面。变化小的参数就可以作为默认参数。

默认参数易错点:

定义一个函数

>>> def add_end(L = []):
	L.append('end')
	return L
>>> add_end([1,2,3])
[1, 2, 3, 'end']

若使用默认参数时,出现以下结果

>>> add_end()
['end']
>>> add_end()
['end', 'end']
>>> add_end()
['end', 'end', 'end']

第一次使用默认参数L = [],结果为L = ['end'],在第二次调用默认参数时,L变量发生了变化,默认参数随着发生变化,不再是最初定义的[]。

由此可得:默认参数必须指向不变对象!

为避免以上情况,可使用None这个不变对象

>>> def add_end(L = None):
	if L is None:
		L = []
	L.append('end')
	return L
>>> add_end()
['end']
>>> add_end()
['end']
>>> add_end()
['end']

为什么要设计str、None这样的不变对象?

因为不变对象一旦创建,对象内部的数据就不能修改,这样就减少了由于修改数据导致的错误。此外,由于对象不变,多任务环境下同时读取对象不需要加锁,同时读一点问题都没有。我们在编写程序时,如果可以设计一个不变对象,那就尽量设计成不变对象。


可变参数

可变参数意思是传入的参数个数是可变的。

>>> def calc(*num):
	sum = 0
	for i in num:
		sum = sum + i * i
	return sum
>>> calc(1,2,3)
14
>>> calc(2,3,5,6)
74
>>> calc()
0

可变参数是在参数前添加一个*号,在使用该函数时,在函数内部,参数num接收到的是一个tuple,而针对使用可变参数*num,可以传入任意个参数,包括0个参数。

同理,在list或tuple前加一个*号,即可将list或tuple元素变为可变参数传入函数中。


关键字参数

可变参数允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple。而关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict,例如:

>>> def person(name, age, **kw):
	print('name: ', name, 'age: ', age, 'other: ', kw)
>>> person('Nelson', 27, 'Xi\'an')
Traceback (most recent call last):
  File "<pyshell#7>", line 1, in <module>
    person('Nelson', 27, 'Xi\'an')
TypeError: person() takes 2 positional arguments but 3 were given

关键字参数必须传入参数名。


>>> person('Nelson', 27, city = 'Xi\'an')
name:  Nelson age:  27 other:  {'city': "Xi'an"}

关键字参数可以扩展函数的功能,如以上person函数中,可以保证接收到name,age两个参数,但是如果调用者愿意提供更多的信息,同样可以收到。

与可变参数类似,可将一个dict转换为关键字参数传进函数中,

>>> extra = {'city': 'Xi\'an', 'sex': 'male'}
>>> extra
{'city': "Xi'an", 'sex': 'male'}
>>> person('Nelson', 27, city = extra['city'], sex = extra['sex'])
name:  Nelson age:  27 other:  {'city': "Xi'an", 'sex': 'male'}
>>> person('Nelson', 27, **extra)
name:  Nelson age:  27 other:  {'city': "Xi'an", 'sex': 'male'}

1. 将dict中的key对应的value传入关键字参数中;

2. (简化)**extra表示把extra这个dict中的所用key-value用关键字参数传入到函数的**kw参数中,kw获得了一个dict。注意:kw获得的dict只是对extra的一份拷贝,改动kw不会影响extra。


命令关键字参数

关键字参数可令函数的调用者传入任意不受限制的关键字参数,而命令关键字参数可以限制关键字参数的名字,例如:

>>> def person(name, age, *, city, sex):
	print(name, age, city, sex)

>>> person('Nelson', 27, city = 'Xi\'an', sex = 'male')
Nelson 27 Xi'an male

与关键字参数**kw不同,命名关键字参数需要一个特殊分隔符*,*后面的参数被视为命令关键字参数。

如果函数定义中已经有了一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符*了,例如:

>>> def person(name, age, *args, city, sex):
	print(name, age, args, city, sex)

>>> person('Nelson', 27, 'Xi\'an', 'male')
Traceback (most recent call last):
  File "<pyshell#4>", line 1, in <module>
    person('Nelson', 27, 'Xi\'an', 'male')
TypeError: person() missing 2 required keyword-only arguments: 'city' and 'sex'
>>> person('Nelson', 27, city = 'Xi\'an', sex = 'male')
Nelson 27 () Xi'an male
>>> person('Nelson', 27, 'handsome', city = 'Xi\'an', sex = 'male')
Nelson 27 ('handsome',) Xi'an male

命令关键字参数必须传入参数名,若没有传入参数名,调用就会报错TypeError。

另外,命令关键字参数可以设置缺省值,调用时,可不传入设置了缺省值的参数,例如:

>>> def person(name, age, *args, city = 'Beijing', sex = 'female'):
	print(name, age, args, city, sex)

>>> person('Bob', 12)
Bob 12 () Beijing female
>>> person('Bob', 16, city = 'Shenzhen')
Bob 16 () Shenzhen female

参数组合

在Python中定义函数,可以用位置参数、默认参数、可变参数、关键字参数和命名关键字参数,这5种参数都可以组合使用。

请注意,这五种参数定义的顺序为:位置参数、默认参数、可变参数、命令关键字参数、关键字参数,例如:

>>> def f1(a, b, c = 1, *, d, **kw):
	print('a', a, 'b', b, 'c', c, 'd', d, 'kw', kw)
>>> f1(1,2)
Traceback (most recent call last):
  File "<pyshell#16>", line 1, in <module>
    f1(1,2)
TypeError: f1() missing 1 required keyword-only argument: 'd'
>>> f1(1, 2, d = 'hello', x = 'world', z = '!')
a 1 b 2 c 1 d hello kw {'x': 'world', 'z': '!'}

以上代码中,命令关键字参数d未传入数据,产生TypeError错误。

同时可以使用一个tuple以及一个dict调用以上函数f1(),例如:

>>> def f1(a, b, c = 1, *, d, **kw):
	print('a=', a, 'b=', b, 'c=', c, 'd=', d, 'kw=', kw)

	
>>> f1(1, 2, d = 'hello', x = 'world', z = '!')
a= 1 b= 2 c= 1 d= hello kw= {'x': 'world', 'z': '!'}
>>> args = (1,2,3,4)
>>> kw = {'d':21, 'x':'hello'}
>>> f1(*args, **kw)
Traceback (most recent call last):
  File "<pyshell#23>", line 1, in <module>
    f1(*args, **kw)
TypeError: f1() takes from 2 to 3 positional arguments but 4 positional arguments (and 1 keyword-only argument) were given
>>> args = (1,2,3)
>>> kw = {'d':21, 'x':'hello'}
>>> f1(*args, **kw)
a= 1 b= 2 c= 3 d= 21 kw= {'x': 'hello'}

以上代码中,第一次运行产生错误原因为:传入可变参数与函数定义参数数量不同,发生错误。

故,对于任意函数,都可以利用类似func(*args, **kw)形式调用它。










猜你喜欢

转载自blog.csdn.net/qq_42020470/article/details/80890276