*args
和**kwargs
是什么意思?def foo(x, y, *args):
pass
def bar(x, y, **kwargs):
pass
参见函数调用中的双星号和单星号有什么区别?了解有关参数的补充问题。
*args
和**kwargs
是什么意思?def foo(x, y, *args):
pass
def bar(x, y, **kwargs):
pass
参见函数调用中的双星号和单星号有什么区别?了解有关参数的补充问题。
*
表示接收可变参数元组
**
表示接收可变参数字典
用法如下:
1) 单个 *
def foo(*args):
for arg in args:
print(arg)
foo("two", 3)
输出:
two
3
2) 现在**
def bar(**kwargs):
for key in kwargs:
print(key, kwargs[key])
bar(dic1="two", dic2=3)
输出:
dic1 two
dic2 3
在Python 3.5中,您还可以在list
、dict
、tuple
和set
显示(有时也称为文字)中使用此语法。请参见PEP 488:附加解包概述。
>>> (0, *range(1, 4), 5, *range(6, 8))
(0, 1, 2, 3, 5, 6, 7)
>>> [0, *range(1, 4), 5, *range(6, 8)]
[0, 1, 2, 3, 5, 6, 7]
>>> {0, *range(1, 4), 5, *range(6, 8)}
{0, 1, 2, 3, 5, 6, 7}
>>> d = {'one': 1, 'two': 2, 'three': 3}
>>> e = {'six': 6, 'seven': 7}
>>> {'zero': 0, **d, 'five': 5, **e}
{'five': 5, 'seven': 7, 'two': 2, 'one': 1, 'three': 3, 'six': 6, 'zero': 0}
它还允许在单个函数调用中解包多个可迭代对象。
>>> range(*[1, 10], *[2])
range(1, 10, 2)
(感谢mgilson提供的PEP链接。)
该函数将传递给函数的参数分别打包到函数体内的list
和dict
中。 当您定义如下的函数签名时:
def func(*args, **kwds):
# do stuff
这个函数可以用任意数量的参数和关键字参数调用。非关键字参数被打包成一个名为args
的列表放在函数体内,而关键字参数则被打包成一个名为kwds
的字典放在函数体内。
func("this", "is a list of", "non-keyowrd", "arguments", keyword="ligma", options=[1,2,3])
现在在函数体内,当函数被调用时,有两个本地变量,args
是一个列表,其值为 ["this", "is a list of", "non-keyword", "arguments"]
,而 kwds
是一个字典,其值为 {"keyword" : "ligma", "options" : [1,2,3]}
。
这也适用于反向操作,即来自调用方的情况。例如,如果你定义了一个函数:
def f(a, b, c, d=1, e=10):
# do stuff
你可以通过解包迭代器或映射来调用它,这些对象必须在调用作用域中存在:
您可以通过解包可迭代对象或映射,在当前作用域内调用该函数:
iterable = [1, 20, 500]
mapping = {"d" : 100, "e": 3}
f(*iterable, **mapping)
# That call is equivalent to
f(1, 20, 500, d=100, e=3)
我想举一个其他人没有提到的例子
* 也可以解包生成器
一则来自Python3文档的例子
x = [1, 2, 3]
y = [4, 5, 6]
unzip_x, unzip_y = zip(*zip(x, y))
unzip_x将是(1,2,3),unzip_y将是(4,5,6)
zip()接受多个可迭代参数并返回一个生成器。
zip(*zip(x,y)) -> zip((1, 4), (2, 5), (3, 6))
(1, 2, 3)
而不是 [1, 2, 3]
。unzip_y 同理。 - EduardoSaverin在nickd的答案的基础上建立...
def foo(param1, *param2):
print(param1)
print(param2)
def bar(param1, **param2):
print(param1)
print(param2)
def three_params(param1, *param2, **param3):
print(param1)
print(param2)
print(param3)
foo(1, 2, 3, 4, 5)
print("\n")
bar(1, a=2, b=3)
print("\n")
three_params(1, 2, 3, 4, s=5)
输出:
1
(2, 3, 4, 5)
1
{'a': 2, 'b': 3}
1
(2, 3, 4)
{'s': 5}
除了函数调用之外,*args和**kwargs在类层次结构中也很有用,并且可以避免在Python中编写__init__方法。类似的用法可以在Django代码等框架中看到。
例如:
def __init__(self, *args, **kwargs):
for attribute_name, value in zip(self._expected_attributes, args):
setattr(self, attribute_name, value)
if kwargs.has_key(attribute_name):
kwargs.pop(attribute_name)
for attribute_name in kwargs.viewkeys():
setattr(self, attribute_name, kwargs[attribute_name])
class RetailItem(Item):
_expected_attributes = Item._expected_attributes + ['name', 'price', 'category', 'country_of_origin']
class FoodItem(RetailItem):
_expected_attributes = RetailItem._expected_attributes + ['expiry_date']
food_item = FoodItem(name = 'Jam',
price = 12.0,
category = 'Foods',
country_of_origin = 'US',
expiry_date = datetime.datetime.now())
__init__
来卸载属性设置。 这是通过*args和**kwargs完成的。 kwargs主要用于使用命名参数使代码可读。 例如,class ElectronicAccessories(RetailItem):
_expected_attributes = RetailItem._expected_attributes + ['specifications']
# Depend on args and kwargs to populate the data as needed.
def __init__(self, specifications = None, *args, **kwargs):
self.specifications = specifications # Rest of attributes will make sense to parent class.
super(ElectronicAccessories, self).__init__(*args, **kwargs)
可以实例化为
usb_key = ElectronicAccessories(name = 'Sandisk',
price = '$6.00',
category = 'Electronics',
country_of_origin = 'CN',
specifications = '4GB USB 2.0/USB 3.0')
给定一个有三个参数的函数
sum = lambda x, y, z: x + y + z
sum(1,2,3) # sum 3 items
sum([1,2,3]) # error, needs 3 items, not 1 list
x = [1,2,3][0]
y = [1,2,3][1]
z = [1,2,3][2]
sum(x,y,z) # ok
sum(*[1,2,3]) # ok, 1 list becomes 3 items
想象一下,有一个装有三个物品:三角形、圆形和矩形的袋子。这个袋子不能直接使用。你需要打开袋子,取出这三个物品,现在它们可以使用了。Python中的 * 运算符就像是这个解包过程。
*args
和**kwargs
:允许您向函数传递可变数量的参数。
*args
:用于向函数发送非关键字可变长度参数列表:
def args(normal_arg, *argv):
print("normal argument:", normal_arg)
for arg in argv:
print("Argument in list of arguments from *argv:", arg)
args('animals', 'fish', 'duck', 'bird')
normal argument: animals
Argument in list of arguments from *argv: fish
Argument in list of arguments from *argv: duck
Argument in list of arguments from *argv: bird
**kwargs*
**kwargs
允许您向函数传递关键字变量长度的参数。如果您想在函数中处理命名参数,则应使用**kwargs
。
def who(**kwargs):
if kwargs is not None:
for key, value in kwargs.items():
print("Your %s is %s." % (key, value))
who(name="Nikola", last_name="Tesla", birthday="7.10.1856", birthplace="Croatia")
将产生:
Your name is Nikola.
Your last_name is Tesla.
Your birthday is 7.10.1856.
Your birthplace is Croatia.
>>> def foo(*arg,**kwargs):
... print arg
... print kwargs
>>>
>>> a = (1, 2, 3)
>>> b = {'aa': 11, 'bb': 22}
>>>
>>>
>>> foo(*a,**b)
(1, 2, 3)
{'aa': 11, 'bb': 22}
>>>
>>>
>>> foo(a,**b)
((1, 2, 3),)
{'aa': 11, 'bb': 22}
>>>
>>>
>>> foo(a,b)
((1, 2, 3), {'aa': 11, 'bb': 22})
{}
>>>
>>>
>>> foo(a,*b)
((1, 2, 3), 'aa', 'bb')
{}
*args
、**kwargs
、super
和继承。class base(object):
def __init__(self, base_param):
self.base_param = base_param
class child1(base): # inherited from base class
def __init__(self, child_param, *args) # *args for non-keyword args
self.child_param = child_param
super(child1, self).__init__(*args) # call __init__ of the base class and initialize it with a NON-KEYWORD arg
class child2(base):
def __init__(self, child_param, **kwargs):
self.child_param = child_param
super(child2, self).__init__(**kwargs) # call __init__ of the base class and initialize it with a KEYWORD arg
c1 = child1(1,0)
c2 = child2(1,base_param=0)
print c1.base_param # 0
print c1.child_param # 1
print c2.base_param # 0
print c2.child_param # 1
def func(*args)
)。如果你想要了解在函数调用中func(*[1,2])
表示什么,请参见 这里。如果你想了解如何展开参数列表,请参见 这里。如果你想了解在 字面量 中 ([*[1, 2]]
)*
的含义,请参见 这里。 - Aran-Fey*
而不是**
)。 - Karl Knechtel