问题描述
我理解 python 描述符,但我对此有点困惑..
如果你有一个如下的类描述符
类描述符(对象):def __get__(self, instance, owner):打印得到"返回 self.valuedef __set__(self, instance, value):打印设置"self.value = 价值def __delete__(self, instance):打印删除"自我价值
我们想要管理其属性的类是这样的..
类测试(对象):名称 = 描述符()def __init__(self, name):打印初始化测试"self.name = 姓名
当我创建类 Test 的对象并做一些事情时,它给了我这样的答案......
t = Test('abc')初始化测试环境>>>名称得到'ABC'>>>删除名称删除>>>吨<__main__.Test object at 0x013FCCD0>>>>名称得到
现在我想要一个类 Test1 像这样..
class Test1(object):def __init__(self, value):打印 'init test1'self.name = Descriptor()自己.价值 = 价值
如果我创建 Test1 的对象并尝试访问 Test1 实例的属性,我会得到类似这样的输出..
t1 = Test1(12)t1.name>>>得到>>>12>>>t1.name = 30>>>环境
Q 1) 我的问题是这个名称属性是否在 Test1 的 init 中声明,是否绑定到 Test1 的实例...因为当我尝试获取 t1 的属性字典时,它返回空字典...
t1.__dict__>>>{}
类 Test 的实例 t 相同
t.__dict__>>>{}
当我向这些实例中的任何一个添加新属性时,就像这样...
t.some = 'some'>>>t1.some = '一些'
再一次,如果我尝试访问属性字典,它只会给我刚刚添加的内容..现在所有实例属性
t.__dict__>>>{'一些':'一些'}>>>t1.__dict__>>>{'一些':'一些'}
Q 2) 那么在 init 中定义的实例属性(如类 Descriptor 和 Test 中的变量名和值)与实例创建后定义的属性(如变量 t.some)有什么区别.
Q 3) Test 类与 Test1 类有何不同.
在 Test1
中,您的 Descriptor
并没有真正用作描述符,它只是一个名为name
,那正好有一些特殊的方法.但这并不能真正使它成为一个描述符.
如果您阅读有关如何调用描述符的文档,您将看到用于调用描述符方法的机制.在您的情况下,这意味着 t.name
将大致相当于:
type(t).__dict__['name'].__get__(t, type(t))
和t1.name
:
type(t1).__dict__['name'].__get__(t1, type(t1))
name
在类的 __dict__
中查找,而不是在实例中查找,所以这就是区别所在,Test1.__dict__
没有名为 name
的描述符:
>>>测试.__dict__['name']<__main__.Descriptor object at 0x7f637a57bc90>>>>Test1.__dict__['name']回溯(最近一次调用最后一次):文件<stdin>",第 1 行,位于 <module>密钥错误:'名称'
您还应该考虑的是,您的描述符为自身设置了 value
属性,这意味着 Test
的所有实例将共享相同的值:
我认为你真正想要做的是在 instance
上设置 value
而不是 self
,这会让你得到预期的行为在 Test
中.
I understood python descriptor but I have a little confusion about this..
if you have a class descriptor as follows
class Descriptor(object):
def __get__(self, instance, owner):
print 'getting'
return self.value
def __set__(self, instance, value):
print 'setting'
self.value = value
def __delete__(self, instance):
print 'deleting'
del self.value
and a class whose attributes we want to manage is something like this..
class Test(object):
name = Descriptor()
def __init__(self, name):
print 'init test'
self.name = name
when I create object of class Test and do something it gives me answer like this...
t = Test('abc')
init test
setting
>>> t.name
getting
'abc'
>>> del t.name
deleting
>>> t
<__main__.Test object at 0x013FCCD0>
>>> t.name
getting
Now I want to have a class Test1 something like this..
class Test1(object):
def __init__(self, value):
print 'init test1'
self.name = Descriptor()
self. value = value
and if I create object of Test1 and try to access attribute of instance of Test1, I get output something like this..
t1 = Test1(12)
t1.name
>>> getting
>>> 12
>>> t1.name = 30
>>> setting
Q 1) my question is that is this name attribute declared in init of Test1, is bound to instance of Test1 or not... because when I try to get attribute dictionary of t1, it return empty dict...
t1.__dict__
>>> {}
same for class Test's instance t
t.__dict__
>>> {}
When I add a new attribute to any of these instances, like this...
t.some = 'some'
>>> t1.some = 'some'
and again if I try to access attribute dictionary it gives me only which I have added just now.. now all instance attribute
t.__dict__
>>> {'some': 'some'}
>>> t1.__dict__
>>> {'some': 'some'}
Q 2) So what is the difference between instance attributes defined in init (like variable name and value in class Descriptor and Test) and attributes defined after instance creation (like variable t.some).
Q 3) How class Test is different than class Test1.
In Test1
your Descriptor
isn't really used as a descriptor, it's just a normal attribute called name
, that happens to have some the special methods. But that doensn't really make it a descriptor yet.
If you read the docs about how descriptors are invoked, youll see the mechanism that is used to invoke the descriptors methods. In your case this would mean t.name
woud be roughly equivalent to:
type(t).__dict__['name'].__get__(t, type(t))
and t1.name
:
type(t1).__dict__['name'].__get__(t1, type(t1))
name
is looked up in the __dict__
of the class, not of the instance, so that's where the difference is, Test1.__dict__
doesn't have a descriptor called name
:
>>> Test.__dict__['name']
<__main__.Descriptor object at 0x7f637a57bc90>
>>> Test1.__dict__['name']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'name'
What you also should consider, is that your descriptor sets the value
attribute on itself, that means all instances of Test
will share the same value:
>>> t1 = Test(1)
init test
setting
>>> t2 = Test(2)
init test
setting
>>> t1.name
getting
2
>>> t2.name
getting
2
>>> t1.name = 0
setting
>>> t2.name
getting
0
I think that what yo acutally want to do is to set value
on instance
instead of self
, that would get you the expected behaviour in Test
.
这篇关于python中描述符概念的行为(令人困惑)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!