Here is my code 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()
When i run this code, i am confused with the output:
C:\Users\elqstux\Desktop>python wy.py
args = ({},)
kwds = {}
For c = C()
, i think the code will raise a Error, because args
will be ()
in this case, but from the output, args
is ({},)
, what't the reason?
self, args = args[0], args[1:] # allow the "self" keyword be passed
*args
is ({},)
because you didn't declare an explicit self
parameter. So when __init__
is called, the self
parameter ends up becoming the first element in args
. Since you inherit from dict
, you get dict
's repr
, which is {}
.
This trick is used intentionally in Python's dict
subclasses nowadays, because otherwise code that initialized the dict
subclass with mydict(self=123)
would break the initializer. The fix is to do:
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:]
which forces self
to be accepted purely as a positional argument (which is passed implicitly by the instance construction machinery). For an example of real world usage, see the implementation of collections.Counter
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With