Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python使用_dict获取对象属性___Python_Python 3.x - Fatal编程技术网

python使用_dict获取对象属性__

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 有没有一种通用的

使用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
有没有一种通用的方法来实现这一点?我最需要的是这个

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
最初是可用的