【问题标题】:Can I access class variables using self?我可以使用 self 访问类变量吗?
【发布时间】:2017-11-11 15:28:20
【问题描述】:

我有一个类 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? 

【问题讨论】:

  • 你有一个 class level 和一个 instance level remote - 你到底想做什么?
  • 我想知道 self.remote 和 cls.remote 是相同的变量还是不同的变量。

标签: python python-3.x class


【解决方案1】:

__init__ 中将remote 分配给self 意味着当您通过self 访问它时首先找到instance.remote(假定周围没有描述符)。要获得这两个选项,请从selftype(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))通过cls 访问时,您将获得类一,当您通过self 访问时,您将获得实例一。

【讨论】:

  • 很高兴能够同时访问remote 变量,但我不喜欢两个不同的事物具有相同名称的事实。关于实例成员广泛使用的m_ 表示法,我喜欢在我的类变量前面加上c_。这消除了诸如self.remote 之类的调用的歧义,它要么变为self.c_remote 要么变为self.m_remote
  • 很好的解释谢谢。
  • 还要注意self.__class__.remote等价于type(self).remote
  • @Rightleg 对,我会澄清这一点。谢谢!不客气,2ank3th。
【解决方案2】:
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 将首先在对象中查找,如果不存在则在类 dict 中查找。

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

【讨论】:

    【解决方案3】:

    是的,您可以使用 self 访问类变量。但是,如果您有一个实例变量,那么当您使用 self 时,您将访问该实例变量,因为它隐藏了类变量。

    【讨论】:

      猜你喜欢
      • 2014-03-06
      • 1970-01-01
      • 2017-12-20
      • 2012-07-27
      • 1970-01-01
      • 1970-01-01
      • 2018-09-26
      • 2014-09-09
      • 2012-06-03
      相关资源
      最近更新 更多