假设我有一个这样的类:
class Test(object):
prop = property(lambda self: "property")每当我尝试访问Test().prop时,描述符都会优先处理。所以这将返回'property'。如果我想访问对象的实例存储,我可以这样做:
x = Test()
x.__dict__["prop"] = 12
print(x.__dict__["prop"])但是,如果我将类更改为:
class Test(object):
__slots__ = ("prop",)
prop = property(lambda self: "property")既然12已不复存在,我该如何做同样的事情,并访问x.__dict__的内部存储,以写入并读回它?
我是Python的新手,但我理解Python的理念是完全控制,那么为什么实现细节会阻止我这样做呢?
Python是否缺少一个可以从实例内部存储中读取的内置函数,例如:
instance_vars(x)["prop"] = 12
print(instance_vars(x)["prop"])它的工作方式与vars类似,不同之处在于它还适用于__slots__以及没有__dict__的内置类型
发布于 2012-05-15 21:30:45
简短的回答:You‘t
问题是插槽本身是根据描述符实现的。给定:
class Test(object):
__slots__ = ("prop",)
t = Test()这句话:
t.prop翻译过来,大约是:
Test.prop.__get__(t, Test)其中,Test.prop是一个由运行时定制的<type 'member_descriptor'>,专门用来从Test实例的保留空间中加载prop值。
如果在类体定义中添加另一个描述符,它将屏蔽允许您访问时隙属性的member_descriptor;没有办法请求它,它已经不在那里了。这实际上就像是在说:
class Test(object):
@property
def prop(self):
return self.__dict__['prop']
@property
def prop(self):
return "property"您已经定义了它两次。没有办法“理解”第一个prop定义。
但是:
很长的答案,你不能在一般的方式中。你可以
您仍然可以滥用python类型系统来使用另一个类定义来获取它。您可以更改python对象的类型,只要它具有完全相同的类布局,这大致意味着它具有所有相同的插槽:
>>> class Test1(object):
... __slots__ = ["prop"]
... prop = property(lambda self: "property")
...
>>> class Test2(object):
... __slots__ = ["prop"]
...
>>> t = Test1()
>>> t.prop
'property'
>>> t.__class__ = Test2
>>> t.prop = 5
>>> t.prop
5
>>> t.__class__ = Test1
>>> t.prop
'property'但是没有通用的方法来反省一个实例来确定它的类布局;你只需要从上下文中知道。您可以查看它的__slots__类属性,但这不会告诉您超类中提供的插槽(如果有的话),也不会给您任何提示,如果属性在类定义后由于某种原因发生了更改。
发布于 2012-05-15 21:00:08
我不太明白你为什么要这么做,但是这对你有帮助吗?
>>> class Test(object):
__slots__ = ("prop",)
prop = property(lambda self: "property")
>>> a = Test()
>>> b = Test()
>>> a.prop
'property'
>>> tmp = Test.prop
>>> Test.prop = 23
>>> a.prop
23
>>> Test.prop = tmp; del tmp
>>> b.prop
'property'当然,您不能在每个实例的基础上覆盖属性,这就是时隙描述符的全部意义所在。
请注意,具有__slots__的类的子类确实具有__dict__,除非您手动定义__slots__,因此您可以这样做:
>>> class Test2(Test):pass
>>> t = Test2()
>>> t.prop
'property'
>>> t.__dict__['prop'] = 5
>>> t.__dict__['prop']
5
>>> Test2.prop
<property object at 0x00000000032C4278>但仍然是这样:
>>> t.prop
'property'这不是因为__slots__,而是描述符的工作方式。
你的__dict__在属性查找时被绕过了,你只是在滥用它作为数据结构,恰好在那里存储状态。它等同于这样做:
>>> class Test(object):
__slots__ = ("prop", "state")
prop = property(lambda self: "property")
state = {"prop": prop}
>>> t.prop
'property'
>>> t.state["prop"] = 5
>>> t.state["prop"]
5
>>> t.prop
'property'发布于 2012-05-15 21:25:30
如果你真的想做这样的事情,你真的需要这样的东西,你总是可以覆盖__getattribute__和__setattribute__,它就是一样愚蠢……这只是为了证明给你看:
class Test(object):
__slots__ = ("prop",)
prop = property(lambda self: "property")
__internal__ = {}
def __getattribute__(self, k):
if k == "__dict__":
return self.__internal__
else:
try:
return object.__getattribute__(self, k)
except AttributeError, e:
try:
return self.__internal__[k]
except KeyError:
raise e
def __setattribute__(self, k, v):
self.__internal__[k] = v
object.__setattribute__(self, k, v)
t = Test()
print t.prop
t.__dict__["prop"] = "test"
print "from dict", t.__dict__["prop"]
print "from getattr", t.prop
import traceback
# These won't work: raise AttributeError
try:
t.prop2 = "something"
except AttributeError:
print "see? I told you!"
traceback.print_exc()
try:
print t.prop2
except AttributeError:
print "Haha! Again!"
traceback.print_exc()(在Python2.7上试用)我想这正是您所期望的。别这么做,没用的。
https://stackoverflow.com/questions/10600813
复制相似问题