在Python中__slots__的目的是什么——特别是当我想要使用它时,什么时候不使用它?
当前回答
从Python 3.9开始,字典可用于通过__slots__向属性添加描述。没有描述的属性可以使用None,即使给出了描述,私有变量也不会出现。
class Person:
__slots__ = {
"birthday":
"A datetime.date object representing the person's birthday.",
"name":
"The first and last name.",
"public_variable":
None,
"_private_variable":
"Description",
}
help(Person)
"""
Help on class Person in module __main__:
class Person(builtins.object)
| Data descriptors defined here:
|
| birthday
| A datetime.date object representing the person's birthday.
|
| name
| The first and last name.
|
| public_variable
"""
其他回答
本质上,你没有使用__slots__。
当你认为你可能需要__slots__时,你实际上想要使用轻量级或Flyweight设计模式。在这些情况下,您不再希望使用纯Python对象。相反,您需要一个Python类对象的包装器来包装数组、结构体或numpy数组。
class Flyweight(object):
def get(self, theData, index):
return theData[index]
def set(self, theData, index, value):
theData[index]= value
类包装器没有属性——它只提供作用于底层数据的方法。方法可以简化为类方法。实际上,它可以简化为仅对底层数据数组进行操作的函数。
类实例的属性有3个属性:实例、属性名和属性值。
在常规属性访问中,实例充当字典,属性名充当字典查找值中的键。
实例(属性)——>值
在__slots__访问中,属性的名称充当字典,实例充当字典查找值中的键。
属性(实例)——>值
在flyweight模式中,属性的名称充当字典,值充当查找实例的字典中的键。
属性(value)——>实例
从Python 3.9开始,字典可用于通过__slots__向属性添加描述。没有描述的属性可以使用None,即使给出了描述,私有变量也不会出现。
class Person:
__slots__ = {
"birthday":
"A datetime.date object representing the person's birthday.",
"name":
"The first and last name.",
"public_variable":
None,
"_private_variable":
"Description",
}
help(Person)
"""
Help on class Person in module __main__:
class Person(builtins.object)
| Data descriptors defined here:
|
| birthday
| A datetime.date object representing the person's birthday.
|
| name
| The first and last name.
|
| public_variable
"""
除了其他答案,这里还有一个使用__slots__的例子:
>>> class Test(object): #Must be new-style class!
... __slots__ = ['x', 'y']
...
>>> pt = Test()
>>> dir(pt)
['__class__', '__delattr__', '__doc__', '__getattribute__', '__hash__',
'__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__',
'__repr__', '__setattr__', '__slots__', '__str__', 'x', 'y']
>>> pt.x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: x
>>> pt.x = 1
>>> pt.x
1
>>> pt.z = 2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Test' object has no attribute 'z'
>>> pt.__dict__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Test' object has no attribute '__dict__'
>>> pt.__slots__
['x', 'y']
因此,要实现__slots__,它只需要额外的一行(并使您的类成为一个新样式的类,如果它还不是的话)。通过这种方式,您可以将这些类的内存占用减少5倍,代价是必须编写自定义pickle代码(如果需要的话)。
插槽对于库调用非常有用,可以在进行函数调用时消除“命名方法分派”。SWIG文档中提到了这一点。对于想要减少常用调用函数的函数开销的高性能库来说,使用插槽要快得多。
这可能和OPs问题没有直接关系。它更多地与构建扩展有关,而不是与在对象上使用插槽语法有关。但它确实有助于完善插槽的使用情况以及它们背后的一些原因。
推荐文章
- 证书验证失败:无法获得本地颁发者证书
- 当使用pip3安装包时,“Python中的ssl模块不可用”
- 无法切换Python与pyenv
- Python if not == vs if !=
- 如何从scikit-learn决策树中提取决策规则?
- 为什么在Mac OS X v10.9 (Mavericks)的终端中apt-get功能不起作用?
- 将旋转的xtick标签与各自的xtick对齐
- 为什么元组可以包含可变项?
- 如何合并字典的字典?
- 如何创建类属性?
- 不区分大小写的“in”
- 在Python中获取迭代器中的元素个数
- 解析日期字符串并更改格式
- 使用try和。Python中的if
- 如何在Python中获得所有直接子目录