Python 为什么“*args”的值很奇怪?
这是我的代码快照:Python 为什么“*args”的值很奇怪?,python,Python,这是我的代码快照: class C(dict): def __init__(*args, **kwds): print 'args = {}'.format(args) print 'kwds = {}'.format(kwds) if not args: raise TypeError("descriptor '__init__' of 'Counter' object needs an argument")
class C(dict):
def __init__(*args, **kwds):
print 'args = {}'.format(args)
print 'kwds = {}'.format(kwds)
if not args:
raise TypeError("descriptor '__init__' of 'Counter' object needs an argument")
self = args[0]
args = args[1:]
if len(args) > 1:
raise TypeError('expected at most 1 arguments, got %d' % len(args))
super(C, self).__init__()
if __name__ == '__main__':
c = C()
运行此代码时,我对输出感到困惑:
C:\Users\elqstux\Desktop>python wy.py
args = ({},)
kwds = {}
对于c=c()
,我认为代码会产生错误,因为在这种情况下args
将是()
,但是从输出来看,args
是({},)
,原因是什么
self,args=args[0],args[1:]#允许传递“self”关键字
我对您的输出很感兴趣!原因很清楚:您在函数定义中输入了self
。使用常规类运行该示例将明确发生了什么:
>>> class C():
... def __init__(*args, **kwargs):
... print args, kwargs
...
>>> C()
(<__main__.C instance at 0x103152368>,) {}
<__main__.C instance at 0x103152368>
>>C类()
... 定义初始值(*args,**kwargs):
... 打印args,kwargs
...
>>>C()
(,) {}
当然,self
作为args
元组的单个元素被困在args
中<毕竟,code>self就像其他任何参数一样
在你的例子中,更令人费解的是,由于你将
dict
子类化,你的类在那时的repr()
是{}
,即空dict的repr()
。因此({},)
*args
是({},)
因为您没有声明显式的self
参数。因此,当调用\uuuu init\uuuu
时,self
参数最终成为args
中的第一个元素。由于继承自dict
,因此将获得dict
的repr
,即{}
现在Python的dict
子类中故意使用了这个技巧,因为如果用mydict(self=123)
初始化dict
子类,则会破坏初始值设定项。解决方法是:
def __init__(*args, **kwargs):
self, *args = args
# On Python 2 without unpacking generalizations you'd use the more repetitive:
# self, args = args[0], args[1:]
它迫使self
被接受为纯粹的位置参数(由实例施工机械隐式传递)。有关实际使用的示例,请参见。您的类\uuuuu init\uuuu
函数使用单个参数调用,即隐式self
参数(即正在创建的新类实例)。通常这将作为类实例打印。但是因为类子类dict
,它以dict
的形式打印,最初没有元素。可能重复@Signal,我知道*args
将是一个元组,但为什么它是({},)
在我的情况下,为什么不()
?@信号无效重复。为什么mydict(self=123)
如果我写def\uuuu init\uuuu(self,*args,**kwds):
?使用def\uuuu init\uuu(*args,**kwds)的目的是什么?
?@BlackMamba:自己试试。问题是,当您按名称接受self
时,它可以按位置(通过Python初始化机制)和关键字传递,而doingmydict(self=123)
现在正试图传递self
两次(而不是用键'self'
创建一个dict
),哪个触发器TypeError:\uuuu init\uuuu()为参数“self”获取了多个值
。Python不够聪明,无法使用定位的self
并将关键字self
放在kwargs
中,因此您需要帮助解决这个问题。self,args=args[0],args[1:]#允许传递“self”关键字。
@BlackMamba:在Python 2中,您必须这样做;在Python3中,在普通表达式(不仅仅是函数调用)中使用*
是可能的(并且在3.5中几乎完全通用),因此您可以执行self、*args=args
,这是重复性较小的操作,可以推广到其他场景(args
在这种情况下始终是一个序列,因此切片是可能的,但不能通过迭代器/生成器来完成,而x,*y,z=mygeneratorfunction()
在Py3中仍然可以无缝且快速地工作,但需要丑陋/缓慢的:gen=mygeneratorfunction()
,x=next(gen)
,y=list(gen)
,z=y.pop()
用于Py2)。