繁体   English   中英

用self调用类变量

[英]Calling class variable with self

我将如何提出这个有趣的(至少对我来说)示例。

import numpy as np


class Something(object):
    a = np.random.randint(low=0, high=10)

    def do(self):
        self.a += 1
        print(self.a)

if __name__ == '__main__':
    something = Something()
    print(something.__str__())
    something.do()
    something2 = Something()
    print(something2.__str__())
    something2.do()
    something3 = Something()
    print(something3.__str__())
    something3.do()

上面在控制台中打印了以下内容:

$ python test.py
<__main__.Something object at 0x7f03a80e0518>
1
<__main__.Something object at 0x7f03a80cfcc0>
1
<__main__.Something object at 0x7f03a80cfcf8>
1

我有点困惑,因为我(错误地)假定值a会有所增加。

如果使用@classmethod装饰器,我可以获得我期望的行为。

import numpy as np


class Something(object):
    a = np.random.randint(low=0, high=10)

    @classmethod
    def do(cls):
        cls.a += 1
        print(cls.a)

if __name__ == '__main__':
    something = Something()
    print(something.__str__())
    something.do()
    something2 = Something()
    print(something2.__str__())
    something2.do()
    something3 = Something()
    print(something3.__str__())
    something3.do()

这样可以在控制台中正确打印以下内容。

python test.py
<__main__.Something object at 0x7faac77becc0>
3
<__main__.Something object at 0x7faac77becf8>
4
<__main__.Something object at 0x7faac77c3978>
5

现在,在第一个示例中,我想知道当我调用self.a ,我正在访问什么? 它不是类变量,因为我似乎无法更改其值。 它也不是实例变量,因为它似乎在同一类的不同对象之间共享。 你怎么称呼它?

这是我使用错误的类变量吗? 我知道cls名称是否是约定俗成的,所以也许我确实在访问类变量,但是由于我没有用@classmethod装饰器修饰该方法,所以我无法更改其值。

这是对语言的一种非法使用吗? 我的意思是最好的做法是为了避免在以后的阶段中引入错误,最好不要这样做?

发生的事情是self.a在不同时间指的是件事。

当名称不存在实例变量时,Python将在类上查找值。 因此,为self.a检索的值将是class变量。

但是,当通过self 设置属性时,Python 总是会设置一个实例变量。 所以self.a现在是一个新的实例变量,其值等于类变量+1。此属性遮盖了class属性,您不能再通过self而是通过类来访问它。

(一个小问题,与问题无关:您永远不要直接访问双下划线方法。不要调用something2.__str__() ,而是调用str(something2)等。)

Daniel Roseman的回答清楚地说明了问题所在。 以下是一些其他要点,希望对您有所帮助。 您可以使用type(self).a代替self.a。 还请参见以下讨论:Python:self vs type(self)以及类变量的正确使用以及Python:self .__ class__ vs.type(self)

import numpy as np


class Something(object):
    a = np.random.randint(low=0, high=10)

    def do(self):
        type(self).a += 1
        print(type(self).a)

if __name__ == '__main__':
    something = Something()
    print(str(something ))
    something.do()
    something2 = Something()
    print(str(something2))
    something2.do()
    something3 = Something()
    print(str(something3))
    something3.do()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM