在Python中,为什么类方法会覆盖实例方法?

问题描述

请参见下面的代码

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()

输出

This is a class method!

那为什么类方法会覆盖实例方法呢?忽略了我们可以简单地更改方法之一的名称这一事实,如何在上述代码中访问实例方法

解决方法

该函数的最新定义将掩盖前一个函数。如果实例方法的定义类似于下面的第二个示例,则将调用它:

    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!

,

因为您两次定义了printline,所以以后的定义获胜。类方法和实例方法都只是类中的函数,它们没有单独的命名空间,因此在作用域中只能有一个具有给定名称的函数。

,

如果要查看import '@clr/icons'; import '@clr/icons/shapes/essential-shapes'; import '@clr/icons/shapes/media-shapes'; import '@clr/icons/shapes/social-shapes'; import '@clr/icons/shapes/travel-shapes'; import '@clr/icons/shapes/technology-shapes'; import '@clr/icons/shapes/chart-shapes'; 的类字典,您可能会更加清楚:

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>}) 的唯一引用。那是因为您过度使用它-就像字典一样,printline的键是唯一的。请注意附加在其上的MappingProxy值,如果您要执行@hobbs和@Arun建议的操作,则会看到以下内容:

classmethod
,

类函数定义始终放在类对象本身上。装饰器实际上只是将带有命名描述符的对象重新分配给变量的一种快速方法。编写代码的更长方法是

1

第二个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() 在成为函数的printline描述符之后,覆盖了类对象上的第一个printline