首页 > 解决方案 > 为什么我需要使用“self”来引用类方法中的类变量?

问题描述

class Channel(object)
  channel_mapping = {
    'a': 001,
    'b': 002,
    'c': 003
  }

  def __init__(self):
    ...

  def process(self, input):
    channels = input.split(',')
    for channel in channels:
       if channel in self.channel_mapping:
          channel = self.channel_mapping[channel]
          break
     ...

我定义channel_mapping为类变量,为什么我需要使用self来引用它?我想我应该只在函数中使用channel_mapping或。cls.channel_mappingprocess()

此外,要定义channel_mapping为这样的类变量,或将其定义为初始化程序中的实例变量,在这两种情况下是否存在线程安全问题?

标签: python

解决方案


我将'channel_mapping'定义为类变量,为什么我需要使用'self'来引用它?

self您可以通过(如果您确保它是只读的)和cls类内部及其方法以及通过类对象或类外部的实例来引用类变量。

使用cls和 和有什么不一样selfcls正在类方法中使用,因为它们不需要初始化,因此不需要对象的实例,并且self在需要对象实例的方法中使用。

我想我应该只使用'channel_mapping'

例如,python 中的作用域不像在 C# 中那样工作,您可以通过编写类变量的名称来调用类变量,而省略this它的冗余位置。在 Python 中,您必须使用self来引用实例的变量。类变量也是如此,但使用cls(or self) 代替。

如果您正在引用channel_mapping,那么您只是从当前或全局范围内引用一个变量,无论它是否存在,而不是来自类或其实例。

或“进程”函数中的 cls.channel_mapping ?

从您肯定要使用的类方法中,cls.channel_mapping因为cls代表类对象。但是从实例的方法中,clsself可以使用self.__class__.channel_mapping. 它所做的只是返回实例的等于 的类cls,然后调用类变量channel_mapping

self.channel_mapping虽然会返回相同的结果,但这只是因为在您的代码中没有调用实例属性channel_mapping,因此 python 可以解析您对类变量的引用。但是,如果channel_mapping实例内部有变量,它将不再与原始类变量相关,因此在这种情况下,您需要保持channel_mapping只读状态。

总而言之,要从类方法中引用类变量,您只想使用 acls并从实例方法中引用类变量,您最好使用self.__class__.var构造而不是self.var一个。

此外,将“channel_mapping”定义为这样的类变量,或将其定义为初始化程序中的实例变量,在这两种情况下是否存在线程安全问题?

在某些情况下,您希望同时更改所有实例中的变量,这时类变量就派上用场了,您不需要更新每个实例中的每个负责的实例变量,您只需更新类变量即可。

但是谈到线程安全,我不确定它是否会在每个线程中同时更新,但self.__class__会在更新后立即返回类的更新版本,因此self.__class__每次调用它时变量都是最新的最小化不同线程将使用同一变量的不同值的时间段。

但是,如果使用初始化变量,如果有多个实例,更新将需要更长的时间,所以我认为它的线程安全性较低。


推荐阅读