使用 self 调用 class 变量
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
时,我正在访问什么?它不是 class 变量,因为我似乎无法更改它的值。它也不是实例变量,因为它似乎在同一 class 的不同对象之间共享。你会怎么称呼它?
这是我使用错误的 class 变量吗?我知道 cls
名称如果约定,所以也许我真的在访问 class 变量,但我无法更改它的值,因为我没有用 [= 修饰方法16=]装饰器。
这是对语言的一种非法使用吗?我的意思是最好不要这样做以避免在后期引入错误?
发生的事情是 self.a
在不同的时间指的是 两个 事物。
当名称不存在实例变量时,Python 将查找 class 上的值。因此 self.a
检索到的值将是 class 变量。
但是当通过self
设置一个属性时,Python将总是设置一个实例变量。所以现在 self.a
是一个新的实例变量,它的值等于 class 变量 + 1。这个属性隐藏了 class 属性,你不能再通过 self
访问它但只能通过 class.
(一个小问题,与问题无关:你永远不应该直接访问 double-underscore 方法。不要调用 something2.__str__()
,而是调用 str(something2)
等)
Daniel Roseman 的回答清楚地说明了问题。下面补充几点,希望对大家有所帮助。
您可以使用 type(self).a 代替 self.a。也看看讨论
Python: self vs type(self) and the proper use of class variables 和
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()
你怎么想出这个有趣的(至少对我来说)例子。
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
时,我正在访问什么?它不是 class 变量,因为我似乎无法更改它的值。它也不是实例变量,因为它似乎在同一 class 的不同对象之间共享。你会怎么称呼它?
这是我使用错误的 class 变量吗?我知道 cls
名称如果约定,所以也许我真的在访问 class 变量,但我无法更改它的值,因为我没有用 [= 修饰方法16=]装饰器。
这是对语言的一种非法使用吗?我的意思是最好不要这样做以避免在后期引入错误?
发生的事情是 self.a
在不同的时间指的是 两个 事物。
当名称不存在实例变量时,Python 将查找 class 上的值。因此 self.a
检索到的值将是 class 变量。
但是当通过self
设置一个属性时,Python将总是设置一个实例变量。所以现在 self.a
是一个新的实例变量,它的值等于 class 变量 + 1。这个属性隐藏了 class 属性,你不能再通过 self
访问它但只能通过 class.
(一个小问题,与问题无关:你永远不应该直接访问 double-underscore 方法。不要调用 something2.__str__()
,而是调用 str(something2)
等)
Daniel Roseman 的回答清楚地说明了问题。下面补充几点,希望对大家有所帮助。 您可以使用 type(self).a 代替 self.a。也看看讨论 Python: self vs type(self) and the proper use of class variables 和 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()