我可以使用self访问类变量吗?

11

我有一个名为Foo的类,其中包含一个类变量remote。我能否使用self.remote来访问这个类变量remote

class Foo:
   remote = False

   def __init__(self):
       self.remote = True 

   @classmethod
   def print_remote(cls):
       print(cls.remote) #prints False but why? 

1
你同时拥有 remote类级别实例级别 - 你究竟想做什么? - Jon Clements
1
我想知道 self.remote 和 cls.remote 是相同的变量还是不同的变量。 - 2ank3th
3个回答

18

__init__中将remote赋值给self意味着当你通过self访问它时(如果没有描述符),会首先找到instance.remote。为了获得两种选项,可以从实例self或类type(self)进行访问:

def print_remote(self):
    print(type(self).remote) # class remote
    print(self.remote)       # instance remote

type(self).remote本质上相当于self.__class__.remote,但一般情况下,在有内置方法(type)可以替代魔术方法(__ * __)的情况下,应避免使用魔术方法。

这两个变量存储在不同的字典中且为不同的变量。self.remote 存储在实例字典中,而 class.remote 则存储在类字典中。

>>> Foo().__dict__['remote']
True
>>> Foo.__dict__['remote']
False

使用classmethod访问类属性时(或在普通方法中使用type(self)访问),您将获得类的属性;而使用self访问时,则获得实例的属性。


1
能够访问两个“remote”变量很好,但我不喜欢两个不同的东西有相同的名称。关于常用的实例成员m_符号,我喜欢使用c_前缀来定义我的类变量。这可以消除调用self.remote的歧义,它可以变成self.c_remote或者self.m_remote - Right leg
非常好的解释。谢谢。 - 2ank3th
请注意,self.__class__.remote 等同于 type(self).remote - Right leg
@Rightleg 对,我会澄清的。谢谢!不客气,2ank3th。 - Dimitris Fasarakis Hilliard

6
In [1]: class Foo:
   ...:     x = 0
   ...:

In [2]: f = Foo()

In [4]: f.__dict__ # empty
Out[4]: {}

In [5]: Foo.__dict__ # have the variable x = 0
Out[5]:
mappingproxy({'__dict__': <attribute '__dict__' of 'Foo' objects>,
              '__doc__': None,
              '__module__': '__main__',
              '__weakref__': <attribute '__weakref__' of 'Foo' objects>,
              'x': 0})

当您尝试访问对象中的变量时,Python会首先查找对象,如果没有找到,则会在类字典中查找。
In [6]: Foo.x = 10 # changing class variable

In [7]: f.__dict__ # still empty.
Out[7]: {}

In [8]: f.x # gives you Foo's x as object doesn't have that item.
Out[8]: 10

In [9]: f.x = 20 # this line creates a new variable in x. Now both class and object has their own variable x

In [10]: f.__dict__ # f has its own x.
Out[10]: {'x': 20}

In [11]: Foo.__dict__ # Foo has its own x.
Out[11]:
mappingproxy({'__dict__': <attribute '__dict__' of 'Foo' objects>,
              ...
              'x': 10})
In [12]: f.x # always you will get the value from f.__dict__
Out[12]: 20
In [16]: f.x = 50 # changing the value of object's variable

In [17]: Foo.x # above statement didn't affect class's variable.
Out[17]: 10

In [13]: del f.x # delete object's x

In [14]: f.x # now f doesn't have x, you get the value from class Foo.
Out[14]: 10

5

是的,你可以使用self访问类变量。但是,如果你有一个实例变量,当你使用self时,你将访问实例变量,因为它会遮盖类变量。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接