In Python 2
class P(object):
def M1(self): print 'inside P class M1())'
class Q(P):
def M1(self): print 'inside Q class M1()'
@classmethod
def M2(cls):
super(Q,cls).M1(cls)
s = Q()
s.M2()
----------------In Python3-------
class P(object):
def M1(self): print ('inside M1 Method of P class')
class Q(P):
@classmethod
def M2(cls):
super().M1(cls) or super(Q,cls)M1(cls)
s = Q()
s.M2()
In Python2: super(Q,cls).M1(cls)#Getting error from here,But we can use same statement in python 3 and it works . I just wondering whether python 2.7 can have any similar way to call parent class implementation by using super() or not .
`
Modifying the print statements to functions, this seems to run happily inside of Python 3.7
Python 3.7.1 (default, Dec 10 2018, 22:54:23) [MSC v.1915 64 bit (AMD64)]
Type 'copyright', 'credits' or 'license' for more information
IPython 7.2.0 -- An enhanced Interactive Python. Type '?' for help.
In [1]: class P(object):
...: def M1(self): print('inside P')
...: class Q(P):
...: def M1(self): print('inside Q')
...: @classmethod
...: def M2(cls):
...: super(Q, cls).M1(cls)
...:
In [2]: s = Q()
In [3]: s.M2()
inside P
But fails in Python2 with the error
TypeError: unbound method M1() must be called with Q instance as first argument (got type instance instead)
Exactly as the error says, because M1
is an instance method its argument must be an instance, not a class. You can get around this by making M1
static and take no arguments.
I suspect this works in Python3 because of tricks inside the implementation of super()
to support usage inside of methods.Reading through the standard library docs and this recommended post were helpful.
This works in Python3 because it doesn't assert the type of the first argument -- it assumes the value is suitable and doesn't hit an error. An example of duck typing.
The error OP is seeing is not actually due to super()
but due to how Python 3 handles instance methods differently than Python 2. An example class could be
>>> class Foo(object):
>>> def __init__(self):
>>> self._bar = 0
>>> def bar(self):
>>> print('baz')
>>> def boo(self):
>>> self._bar+=1
>>> print(self._bar)
>>> f = Foo()
>>> Foo.bar(Foo) # fine in Python3, TypeError in Python2
>>> Foo.bar(None) # fine in Python3, TypeError in Python2
>>> f.bar() # fine in both
baz
>>> Foo.boo(Foo) # AttributeError in Python3, TypeError in Python2
In both cases for, Python2 has an embedded assertion that the first argument of an instance method must be an instance type of the matching class. Python3 does not have this assertion for -- it's happy receiving None
or a type
type, at least until whatever argument it received fails to work. This is a great example of ducktyping .
So Foo.bar
works in Python3 because it doesn't actually care what the value of the argument is -- it doesn't use it. In Foo.boo
, however, it fails with an AttributeError
when trying to increment the Foo._bar
instance property (because that instance property doesn't exist in the argument it was given).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.