为什么`* args`的值很奇怪?

时间:2016-04-06 02:28:55

标签: python

这是我的代码snappt:

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是{{1} ,是什么原因?

({},)

3 个答案:

答案 0 :(得分:6)

*args({},),因为您没有声明明确的self参数。因此,当调用__init__时,self参数最终成为args中的第一个元素。由于您从dict继承,因此dict的{​​{1}}为repr

此技巧现在在Python的{}子类中有意使用,因为否则用dict初始化dict子类的代码会破坏初始化程序。解决方法是:

mydict(self=123)

迫使 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:] 纯粹作为位置参数被接受(由实例构造机制隐式传递)。有关实际使用情况的示例,请参阅the implementation of collections.Counter

答案 1 :(得分:3)

我对你的输出很感兴趣!原因很清楚:您从self函数定义中省略了__init__。使用常规类运行示例将清楚地说明发生了什么:

>>> class C():
...   def __init__(*args, **kwargs):
...     print args, kwargs
...
>>> C()
(<__main__.C instance at 0x103152368>,) {}
<__main__.C instance at 0x103152368>

当然,selfargs作为args元组的单个元素。毕竟,self就像任何其他论点一样。

在你的情况下让你更加困惑的是,由于你已经将dict子类化了,所以此时你班级的repr(){},即repr()空的dict。因此({},)

答案 2 :(得分:1)

使用单个参数调用类__init__函数,隐式self参数(即正在创建的新类实例)。通常这会打印为类实例。但是因为类子类dict,它打印为dict,最初没有元素。