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初始化机制)和关键字传递,而doing
mydict(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)。