Python:通过**变量(some_class)访问只读属性

时间:2013-09-04 10:48:27

标签: python dictionary properties

我经常使用成语'{var_name}'.format(**vars(some_class))

但是,当我使用属性时,我无法使用它来获取属性值。

考虑这个程序:

#!/usr/bin/env python

class Foo(object):
    def __init__(self):
        self._bar = None
        self.baz = 'baz here'

    @property
    def bar(self):
        if not self._bar:
            # calculate some value...
            self._bar = 'bar here'
        return self._bar

if __name__ == '__main__':
    foo = Foo()

    # works:
    print('{baz}'.format(**vars(foo)))

    # gives: KeyError: 'bar'
    print('{bar}'.format(**vars(foo)))

问题:

有没有办法通过**vars(some_class)访问属性值?

5 个答案:

答案 0 :(得分:4)

简短回答:不,不可能使用.format(**vars(object))来执行您想要的操作,因为属性使用__dict__vars文档:

  

vars(...)

     

vars([object]) - >字典

     
      
  • 没有参数,相当于locals()
  •   
  • 使用参数,相当于object.__dict__
  •   

但是,您可以使用不同的格式说明符来实现所需的目的,例如属性查找:

In [2]: '{.bar}'.format(Foo())
Out[2]: 'bar here'

请注意,您只需在名称中添加前导.(点)即可获得所需内容。


附注:不应使用.format(**vars(object)),而应使用format_map方法:

In [6]: '{baz}'.format_map(vars(Foo()))
Out[6]: 'baz here'

使用format_map参数调用dict相当于使用format表示法调用**,但效率更高,因为它不需要执行任何操作在调用函数之前解压缩。

答案 1 :(得分:1)

使用.表示法 -

print('{0._bar}'.format(foo))

答案 2 :(得分:1)

要完全按照您的要求进行操作,您可以编写一个将项目访问权限转换为属性访问权限的类:

class WrapperDict(object):
    def __init__(self, obj):
        self.obj = obj
    def __getitem__(self, key):
        return getattr(self.obj, key)

示例:

>>> print('{bar}'.format_map(WrapperDict(Foo())))
bar here

另一个相当黑客的选择是添加

__getitem__ = object.__getattribute__

到班级Foo,然后直接使用Foo个实例:

>>> print('{bar}'.format_map(Foo()))
bar here

我认为使用属性访问表示法是更好的解决方案。

答案 3 :(得分:0)

如果我理解你是对的,那么这样的事情应该有效:

print( eval( 'foo.{bar}'.format( **dict( ( v, v ) for v in dir( foo ) ) ) ) )

但不过这感觉“非常糟糕”。

答案 4 :(得分:0)

您可以将其写入实例的__dict__

class Article(object):
    def __init__(self):
        self.content = ""
        self.url = ""

    @property
    def title(self):
        return self.__dict__.get("title", "")

    @title.setter
    def title(self, title):
        self.__dict__["title"] = title

然后:

>>> article = Article()
>>> article.title = "Awesome Title"
>>> vars(article)
{'content': '', 'url': '', 'title': 'Awesome Title'}