python使用_dict获取对象属性__
使用py3,我有一个使用@property装饰器的对象python使用_dict获取对象属性__,python,python-3.x,Python,Python 3.x,使用py3,我有一个使用@property装饰器的对象 class O(object): def __init__(self): self._a = None @property def a(self): return 1 通过dict(使用_a)访问属性a似乎不会返回属性修饰值,而是返回初始化值None o = O() print(o.a, o__dict__['_a']) >>> 1, None 有没有一种通用的
class O(object):
def __init__(self):
self._a = None
@property
def a(self):
return 1
通过dict(使用_a)访问属性a似乎不会返回属性修饰值,而是返回初始化值None
o = O()
print(o.a, o__dict__['_a'])
>>> 1, None
有没有一种通用的方法来实现这一点?我最需要的是这个
def __str__(self):
return ' '.join('{}: {}'.format(key, val) for key, val in self.__dict__.items())
属性基本上是一个“计算属性”。通常,属性的值不会存储在任何位置,而是根据需要计算。这就是为什么您在目录中找不到它的原因
@property
decorator用描述符对象替换类方法,然后描述符对象调用原始方法作为其getter。这发生在班级层面
o.a
的查找从实例开始。该类不存在,将在下一步中检查该类O.a
存在并且是一个描述符(因为它对描述符协议有特殊的方法),因此调用描述符的getter并使用返回值
(编辑)
没有一种通用的方法来转储描述符的name:value对。必须检查包括基础在内的课程,这一部分并不困难。但是,检索值相当于函数调用,可能会产生意外的副作用。从另一个角度来看,我想引用bruno desthuilliers的一句评论:“属性get不应该有不必要的副作用(如果有副作用,那么就会有明显的设计错误)。属性基本上是一个“计算属性”。通常,属性的值不会存储在任何位置,而是根据需要计算。这就是为什么您在目录中找不到它的原因
@property
decorator用描述符对象替换类方法,然后描述符对象调用原始方法作为其getter。这发生在班级层面
o.a
的查找从实例开始。该类不存在,将在下一步中检查该类O.a
存在并且是一个描述符(因为它对描述符协议有特殊的方法),因此调用描述符的getter并使用返回值
(编辑)
没有一种通用的方法来转储描述符的name:value对。必须检查包括基础在内的课程,这一部分并不困难。但是,检索值相当于函数调用,可能会产生意外的副作用。从另一个角度来看,我想引用bruno desthuilliers的一句评论:“property get不应该有不必要的副作用(如果有,那么就会有明显的设计错误)”。当然是self.\uu dict\uu[“\u a”]
将返回self.\u a
(实际上是另一种方式-self.\u a
将返回self.\u dict\u[“\u a”]
,但无论如何,)不是self.a
。属性在这里所做的唯一事情就是自动调用它的getter(你的a(self)
函数)因此,您不必键入paren,否则它只是一个简单的方法调用
如果您想要与属性一起工作的东西,您必须从dir(self.\uuuu class\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
def __str__(self):
# py2
attribs = self.__dict__.items()
# py3
# attribs = list(self.__dict__.items())
for name in dir(self.__class__):
obj = getattr(self.__class__, name)
if isinstance(obj, property):
val = obj.__get__(self, self.__class__)
attribs.append((name, val))
return ' '.join('{}: {}'.format(key, val) for key, val in attribs)
请注意,这不会阻止\u a
出现在attribs
中-如果要避免这种情况,您还必须从attribs
列表中筛选出受保护的名称(所有受保护的名称,因为您要求的是通用名称):
还要注意,这不会处理其他计算属性(property
只是描述符协议的一个通用实现).在这一点上,对于仍然尽可能通用但可以根据需要定制的东西,您最好的选择是将上述内容实现为一个mixin类,并带有几个专门化的挂钩:
class PropStrMixin(object):
# add other descriptor types you want to include in the
# attribs list
_COMPUTED_ATTRIBUTES_CLASSES = [property,]
def _get_attr_list(self):
attribs = [(k, v) for k, v in self.__dict__.items() if not k.startswith("_")]
for name in dir(self.__class__):
# a protected property is somewhat uncommon but
# let's stay consistent with plain attribs
if name.startswith("_"):
continue
obj = getattr(self.__class__, name)
if isinstance(obj, *self._COMPUTED_ATTRIBUTES_CLASSES):
val = obj.__get__(self, self.__class__)
attribs.append((name, val))
return attribs
def __str__(self):
attribs = self._get_attr_list()
return ' '.join('{}: {}'.format(key, val) for key, val in attribs)
class YouClass(SomeParent, PropStrMixin):
# here you can add to _COMPUTED_ATTRIBUTES_CLASSES
_COMPUTED_ATTRIBUTES_CLASSES = PropStrMixin + [SomeCustomDescriptor])
当然self.\u dict\u[“\u a”]
将返回self.\u a
(事实上,它是另一种方式-self.\u a
将返回self.\u dict\u[“\u a”]
,但无论如何,self.a
。属性所做的唯一事情就是自动调用它的getter(你的a(self)
function),因此您不必键入参数,否则它只是一个简单的方法调用
如果您想要与属性一起工作的东西,您必须从dir(self.\uuuu class\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
def __str__(self):
# py2
attribs = self.__dict__.items()
# py3
# attribs = list(self.__dict__.items())
for name in dir(self.__class__):
obj = getattr(self.__class__, name)
if isinstance(obj, property):
val = obj.__get__(self, self.__class__)
attribs.append((name, val))
return ' '.join('{}: {}'.format(key, val) for key, val in attribs)
请注意,这不会阻止\u a
出现在attribs
中-如果要避免这种情况,您还必须从attribs
列表中筛选出受保护的名称(所有受保护的名称,因为您要求的是通用名称):
还要注意,这不会处理其他计算属性(property
只是描述符协议的一个通用实现).在这一点上,对于仍然尽可能通用但可以根据需要定制的东西,您最好的选择是将上述内容实现为一个mixin类,并带有几个专门化的挂钩:
class PropStrMixin(object):
# add other descriptor types you want to include in the
# attribs list
_COMPUTED_ATTRIBUTES_CLASSES = [property,]
def _get_attr_list(self):
attribs = [(k, v) for k, v in self.__dict__.items() if not k.startswith("_")]
for name in dir(self.__class__):
# a protected property is somewhat uncommon but
# let's stay consistent with plain attribs
if name.startswith("_"):
continue
obj = getattr(self.__class__, name)
if isinstance(obj, *self._COMPUTED_ATTRIBUTES_CLASSES):
val = obj.__get__(self, self.__class__)
attribs.append((name, val))
return attribs
def __str__(self):
attribs = self._get_attr_list()
return ' '.join('{}: {}'.format(key, val) for key, val in attribs)
class YouClass(SomeParent, PropStrMixin):
# here you can add to _COMPUTED_ATTRIBUTES_CLASSES
_COMPUTED_ATTRIBUTES_CLASSES = PropStrMixin + [SomeCustomDescriptor])
您还可以将self.\u a
更新为getter,因为getter的返回应该始终反映self.\u a
存储的内容:
O类(对象):
定义初始化(自):
self.\u a=self.a
@财产
def a(自我):
自我评价。_a=1
回归自我
可能有点多余,但在这种情况下,设置self.\u A=None
最初是无用的
以防你需要一个二传手
如果删除getter中的第一行,这也将是兼容的:
@a.setter
def a(self, value):
self._a = value
您还可以将self.\u a
更新为getter,因为getter的返回应该始终反映self.\u a
存储的内容:
O类(对象):
定义初始化(自):
self.\u a=self.a
@财产
def a(自我):
自我评价。_a=1
回归自我
可能有点多余,但设置self.\u A=None
最初是可用的