- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我一直在玩弄 __slots__
并稍微搜索一下,但我仍然对某些细节感到困惑:
我知道 __slots__
生成某种描述符:
>>> class C:
... __slots__ = ('x',)
...
>>> C.x
<member 'x' of 'C' objects>
>>> C.x.__get__
<method-wrapper '__get__' of member_descriptor object at 0x7f001de183a8>
>>> C.x.__get__
<method-wrapper '__get__' of member_descriptor object at 0x7f001de183a8>
但我想知道:这些值实际存储在哪里?
因为到目前为止我看到的描述符的常见配方/习语是:
>>> class Descr:
...
... def __init__(self, attrname):
... self.attrname = attrname
...
... def __get__(self, obj, cls):
... return obj.__dict__[self.attrname]
...
... def __set__(self, obj, val):
... obj.__dict__[self.attrname] = val
...
... class C:
...
... def __init__(self, x):
... self.x = x
与__slots__
一起使用时,有两个问题:
>>> class C:
...
... __slots__ = ('x',)
...
... def __init__(self, x):
... self.x = x
...
... x = Descr('x')
...
Traceback (most recent call last)
...
ValueError: 'x' in __slots__ conflicts with class variable
因此,解决方法是将实际属性命名为“_x”。
__dict__
(除非您明确将其添加到 __slots__
):>>> class C:
...
... __slots__ = ('_x',)
...
... def __init__(self, x):
... self._x = x
...
... x = Descr('_x')
...
>>> c = C(0)
>>> c.x
Traceback (most recent call last)
...
AttributeError: 'C' object has no attribute '__dict__'
因此您必须改用 getattr()
和 setattr()
。
您可以以通用描述符结束,该描述符可以与 __dict__
和 __slots__
一起使用:
class WorksWithDictAndSlotsDescriptor:
def __init__(self, attr_name):
self.attr_name = attr_name
def __get__(self, instance, owner):
try:
return instance.__dict__[self.attr_name]
except AttributeError:
return getattr(instance, self.attr_name)
def __set__(self, instance, value):
try:
instance.__dict__[self.attr_name] = value
except AttributeError:
setattr(instance, self.attr_name, value)
(如果同时存在 __slots__
和 __dict__
,则不会正常工作。)
但最近我发现了一种使用包装器劫持 __get__
和 __set__
方法的方法:
def slot_wrapper(cls, slotname, slot, descriptor):
'''Wrapper replacing a slot descriptor with another one'''
class InnerDescr(descriptor):
def __get__(self, obj, cls):
print("Hijacking __get__ method of a member-descriptor")
return slot.__get__(obj, cls)
def __set__(self, obj, val):
print("Hijacking __set__ method of a member-descriptor")
slot.__set__(obj, val)
return InnerDescr(slotname, cls)
(用例是添加类型检查和数据验证,以及强制封装。)
因此,在创建类之后(或在使用元类之前),您可以为插槽和描述符保留相同的名称。
工作得很好,但感觉有点脏……我认为实现我自己的槽以继续为描述符使用同一个名称可能会更好。但我不知道怎么办。
所以这里有一些问题:
实际存储的值在哪里(因为没有字典)?我在想它是用 C 实现的,不能直接用 Python 代码访问。
如何在不损失性能优化的情况下实现纯 Python 等价物?
坚持使用我的 wrapper 更好吗?
最佳答案
Where are actually storerd the values (since there is no dict) ? I was thinking it's something implemented in C and not directly accessible with Python code.
直接在对象本身中为 PyObject *
指针分配内存。您可以在 Objects/typeobject.c
中看到处理.生成的描述符将访问为其在适当类型的对象中的插槽保留的内存。
How can I implement a pure python equivalent without losing performance optimization?
你不能。您可以获得的最接近的是扩展 tuple
。
It is prefarable to stick with my wrapper?
没有。不要将您的插槽命名为与您希望由其他描述符处理的属性相同的名称。这样做就像命名两个非插槽描述符一样;对于如何处理具有该名称的属性,您表达了两个相互矛盾的意图。
关于python - __slots__ 是如何工作的,你如何实现自己的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46028830/
首先让我说我了解槽和元类在 Python 中的工作方式。玩弄这两个,我遇到了一个有趣的问题。这是一个最小的例子: def decorator(cls): dct = dict(cls.__di
__slots__ 的目的是什么?在 Python 中——尤其是关于我什么时候想使用它,什么时候不想使用它? 最佳答案 In Python, what is the purpose of __slot
我在 Python 的输入系统和 __slots__ 之间有冲突。这是一个可重现的小例子。 from typing import TypeVar, Generic, Sequence T = Type
class Foo(object): __slots__ = ('a',) class Bar(Foo): @property def a(self): ret
我有一节课 __slots__ : class A: __slots__ = ('foo',) 如果我创建一个子类而不指定__slots__,子类将有一个__dict__: class B(A
我正在开发一个需要通过 __init__ 注入(inject)来为其赋予 __dict__ 属性的类,如下所示: class Torrent(Model): def __init__(self
我听说 __slots__ 通过避免字典查找使对象更快。我的困惑来自于 Python 是一种动态语言。在静态语言中,我们通过编译时优化将索引保存在我们运行的指令中,从而避免了对 a.test 的字典查
我需要用 None 初始化一个实例的所有插槽。如何获取派生类的所有插槽? 示例(不起作用): class A(object): __slots__ = "a" def __init__
所以,我正在阅读一些关于 Python 中元类的内容,以及如何使用 type()的三参数 alter-ego 用于动态创建类。但是,第三个参数通常是 dict。初始化要创建的类'__dict__变量。
考虑以下代码: from weakref import ref class Klass(object): # __slots__ = ['foo'] def __init__(self
通过学习《Python类变量和实例变量》一节,了解了如何动态的为单个实例对象添加属性,甚至如果必要的话,还可以为所有的类实例对象统一添加属性(通过给类添加属性)。 那么,Python 是否也允许动态地
早上好 我在尝试在我的一门类(class)中使用 __ 插槽 __ 时遇到问题。我想用它来优化 Classifier 对象的多个实例的创建。我正在使用 Python 3.7.1。 这行得通 class
当我运行这个(2.7.3)时,我得到这个输出: 'Slotted1' object has no attribute 'c' attribute c added to 我不明白 Slotted1 和
最近在学习Python,但是我有一个关于__slots__的问题。我认为是为了限制Class中的参数,同时也限制Class中的方法? 例如: from types import MethodType
最近给 friend 讲解了__slots__的用法。我想向他展示结果并使用了以下代码: import sys class Foo: __slots__ = 'a', 'b' def
我一直在玩弄 __slots__ 并稍微搜索一下,但我仍然对某些细节感到困惑: 我知道 __slots__ 生成某种描述符: >>> class C: ... __slots__ = ('x'
在类中创建结果对象时,是否可以在本例中使用__slots__?我想我可以通过将 '__slots__' 传递到 type 的第三个参数的字典中来让它工作: class GeocodeResult(ob
我读入了Usage of __slots__?在 Python 中使用 __slots__ 实际上可以节省时间。但是,当我尝试使用 datetime 查找所花费的时间时,结果却相反。 import d
我正在使用 Python 3.7 和 Django。我正在阅读 __slots__ .显然,__slots__ 可用于通过提前列出所有对象属性来优化大量此类对象的内存分配。 class MyClass
我正在编写一个配置卷的存储自动化模块。我没有传递在存储 Controller 上实际创建卷所需的六个或更多参数,而是使用 __slots__ 创建了一个参数类,它被传递到 create 方法中,如下所
我是一名优秀的程序员,十分优秀!