python - 使用 'self' 调用类方法?

标签 python class-method

class Hello:
    def load(self):
        self.open('World')
    @classmethod
    def open(cls,print_string):
        print 'Hello ' + print_string


class Hello:
    def load(self):
        Hello.open('World')
    @classmethod
    def open(cls,print_string):
        print 'Hello ' + print_string

我发现很难从以上两个类中理解调用类方法的不同风格。调用时使用self和另一个类名,什么时候先用什么时候用第二个?

好的解释会真正阐明 @classmethod 的概念。

最佳答案

这里的核心问题实际上不是 classmethod,而是 Python 如何处理属性。有两种不同的属性,类级属性(在其他语言中有时称为“静态”属性)和实例属性。

考虑:

>>> class A:
...    a = 'foo'
...    def __init__(self):
...       self.x = 42
...    def method(self):
...       print(A.a)
...       print(self.a)
...       print(self.x)
...
>>> a = A()
>>> a.method()
foo
foo
42

现在,在 Python 中,类级属性(包括方法本身)属于类命名空间,可通过 __dict__ 属性访问:

>>> from pprint import pprint
>>> pprint(A.__dict__)
mappingproxy({'__dict__': <attribute '__dict__' of 'A' objects>,
              '__doc__': None,
              '__init__': <function A.__init__ at 0x101589d90>,
              '__module__': '__main__',
              '__weakref__': <attribute '__weakref__' of 'A' objects>,
              'a': 'foo',
              'method': <function A.method at 0x10863a620>})

instance 属性只是那些你使用 self.something = somethingsomething 显式分配给实例的属性:

>>> pprint(a.__dict__)
{'x': 42}

但是,当您访问 一个属性时,您可以认为 Python 首先 检查实例的 __dict__。如果没有找到,它会检查 的命名空间。如果它仍然没有找到它,它会按照方法解析顺序(即继承)检查任何父类的命名空间。

因此,如果您这样做,类本身就是其他对象:

Hello.open('World')

这会检查 Hello 对象命名空间并找到它。同样,如果您在实例上使用该方法,

self.open('World')

它检查实例命名空间,没有找到,然后检查类命名空间并找到了。现在,如果您不希望扩展该类(class),那么真的没有区别。但是如果你这样做那么语义就会改变。如果您从 Hello 派生,并覆盖 open 而不是 loadHello.open始终调用父类(super class)open 方法。但是,self.open 版本会在类命名空间中找到它,而不会检查父类。因此,根据您想要的行为,您可以使用其中任何一种,但通常如果您的类设计正确,那么 self 是可行的方法。但也许不是。所以,给你一个具体的例子:

>>> class B(A):
...    a = 'bar'
...
>>> b = B()
>>> b.method()
foo
bar
42
>>>

关于python - 使用 'self' 调用类方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44228916/

相关文章:

javascript - Javascript 中的类方法

python - 函数中的局部变量输出让我感到惊讶

python - 查找文件被删除的 bzr 修订版

objective-c - 在两个 nib 之间传递参数 : suggestion?

ios - 在 OCMPartialMock 上 stub 类方法?

python - 从模块调用类函数?

python - 检测具有混合变量类型的几乎重复的行

python - 如何向 Tkinter 表单添加高度和宽度

用于大型制表符/逗号分隔文本文件的 python 库

python - 如何从基类引用 Python 派生类的 __init__ 方法?