Reputation: 51
See code below:
class MyClass:
# instance method.
def printline(self):
print('This is an instance method!')
@classmethod
def printline(cls):
print('This is a class method!')
# class MyClass ends.
obj = MyClass()
obj.printline()
Output:
This is a class method!
So why is the class method overriding the instance method? Ignoring the fact that we can simply change the name of one of the method, how do access the instance method in the above code?
Upvotes: 1
Views: 635
Reputation: 77347
Class function definitions are always placed on the class object itself. Decorators are really just a quick way to reassign a object with the named descriptor to the variable. The longer way to write your code is
class MyClass:
# instance method.
def printline(self):
print('This is an instance method!')
# make classmethod manually instead of using @classmethod
def printline(cls):
print('This is a class method!')
printline = classmethod(printline)
obj = MyClass()
obj.printline()
The second printline
overwrote the first printline
on the class object after becoming a classmethod
descriptor for the function.
Upvotes: 0
Reputation: 1365
You might get a clearer understanding if you were to look inside the class dictionary of MyClass
:
>>> pp(MyClass.__dict__)
mappingproxy({'__dict__': <attribute '__dict__' of 'MyClass' objects>,
'__doc__': None,
'__module__': '__main__',
'__weakref__': <attribute '__weakref__' of 'MyClass' objects>,
'printline': <classmethod object at 0x109d67dd0>})
Here you will see there is only one reference to the method printline
. That is because you over-rode it - like a dictionary, a MappingProxy
's keys are unique. Notice the classmethod
value attached to it, if you were to do what @hobbs and @Arun suggested, you would see this:
>>> MyClass.__dict__['printline']
<function MyClass.printline at 0x10979a710>
Upvotes: 0
Reputation: 1086
The latest definition of the function will mask the previous one. If the instance method was defined like the 2nd example below, you would be calling it:
In [1]: class MyClass:
...:
...: # instance method.
...: def printline(self):
...: print('This is an instance method!')
...:
...: @classmethod
...: def printline(cls):
...: print('This is a class method!')
...:
In [2]: m = MyClass()
In [3]: m.printline()
This is a class method!
In [4]: class MyClass1:
...:
...: @classmethod
...: def printline(cls):
...: print('This is a class method!')
...:
...: # instance method.
...: def printline(self):
...: print('This is an instance method!')
In [5]: m1 = MyClass1()
In [6]: m1.printline()
This is an instance method!
Upvotes: 5
Reputation: 239980
Because you defined printline
twice, and the later definition wins. Class methods and instance methods are both just functions in the class, they don't have separate namespaces, so there can only be one function with a given name in a scope.
Upvotes: 1