python - 为什么我需要使用“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_mapping
process()
此外,要定义channel_mapping
为这样的类变量,或将其定义为初始化程序中的实例变量,在这两种情况下是否存在线程安全问题?
解决方案
我将'channel_mapping'定义为类变量,为什么我需要使用'self'来引用它?
self
您可以通过(如果您确保它是只读的)和cls
类内部及其方法以及通过类对象或类外部的实例来引用类变量。
使用cls
和 和有什么不一样self
?cls
正在类方法中使用,因为它们不需要初始化,因此不需要对象的实例,并且self
在需要对象实例的方法中使用。
我想我应该只使用'channel_mapping'
例如,python 中的作用域不像在 C# 中那样工作,您可以通过编写类变量的名称来调用类变量,而省略this
它的冗余位置。在 Python 中,您必须使用self
来引用实例的变量。类变量也是如此,但使用cls
(or self
) 代替。
如果您正在引用channel_mapping
,那么您只是从当前或全局范围内引用一个变量,无论它是否存在,而不是来自类或其实例。
或“进程”函数中的 cls.channel_mapping ?
从您肯定要使用的类方法中,cls.channel_mapping
因为cls
代表类对象。但是从实例的方法中,cls
您self
可以使用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__
每次调用它时变量都是最新的最小化不同线程将使用同一变量的不同值的时间段。
但是,如果使用初始化变量,如果有多个实例,更新将需要更长的时间,所以我认为它的线程安全性较低。
推荐阅读
- django - 在 Django 管理站点中显示 ManyToManyField
- qt - QLineEdit 应该有一个固定的大小
- sql - 如何在 SQL Server 中使用联接动态透视表
- linux - 导出无法通过另一个脚本进行
- python - 如何将参数发送到我通过 Klein(Flask) 应用程序提供的 html 文件?
- javascript - TypeScript 中对象字面量的动态泛型类型推断
- select - 如果选择类不起作用,则使用列表处理硒处理下拉菜单
- cassandra - 用于 java 的 DSE cassandra 驱动程序在异步模式下仅返回部分结果
- google-apps-script - 如何从一张工作表复制活动范围并将数据粘贴到谷歌工作表中同一工作簿中不同工作表中的特定范围?
- database - TFS 2017.3.1 合并集合