首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >__getattribute__递归

__getattribute__递归
EN

Stack Overflow用户
提问于 2010-11-22 15:31:39
回答 3查看 2.5K关注 0票数 2

我需要实现这样的行为:

代码语言:javascript
运行
复制
obj.attr1.attr2.attr3 --> obj.attr1__attr2__attr3

看起来,我必须重写obj的类__getattribute__,并以某种方式使用python描述符。

更新:

我有个django项目。

obj是django -haystack的SearchResult实例,它包含了来自django模型的大量非规范化数据(user__nameuser__address),出于兼容性原因,我需要以result.user.name的形式访问它。

THC4k答案的更新:

如果我有:

代码语言:javascript
运行
复制
class Target(object):
    attr1 = 1
    attr1__attr2__attr3 = 5

>>> proxy.attr1
1
>>> proxy.attr1.attr2.attr3
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'int' object has no attribute 'attr2'

任何帮助都将不胜感激。

EN

回答 3

Stack Overflow用户

发布于 2010-11-22 16:01:28

我希望您知道自己在做什么,这不仅仅是一个避免修复现有代码的方案。

我认为这样做是有正当理由的,因为我在Lua中做了一些类似的工作,以实现一些C代码的包装器,而不必为每个公开的函数实际编写代码。

但是,至少应该将实际类从代理中分离出来:

代码语言:javascript
运行
复制
# the proxy maps attribute access to another object
class GetattrProxy(object):
    def __init__(self, proxied, prefix=None):
        self.proxied = proxied
        self.prefix = prefix

    def __getattr__(self, key):
        attr = (key if self.prefix is None else self.prefix + '__' + key)
        try:
            # if the proxied object has the attr return it
            return getattr(self.proxied, attr)
        except AttributeError:
            # else just return another proxy
            return GetattrProxy(self.proxied, attr)


# the thing you want to wrap
class Target(object):
    attr1__attr2__attr3 = 5


t = Target()
proxy = GetattrProxy(t)

print proxy.attr1.attr2.attr3

@katrielalex建议:

代码语言:javascript
运行
复制
class GetattrProxy2(GetattrProxy):
    def __getattr__(self, key):
            attr = (key if self.prefix is None else self.prefix + '__' + key)
            proxy = GetattrProxy2(self.proxied, attr)

            # store val only if the proxied object has the attribute, 
            # this way we still get AttributeErrors on nonexisting items 
            if hasattr(self.proxied, attr):
                proxy.val = getattr(self.proxied, attr)
            return proxy

proxy = GetattrProxy2(t)
proxy.attr1.val # 1
proxy.attr1.attr2.attr3.val # 5
proxy.attr1.attr2.val # raise AttributeError
票数 3
EN

Stack Overflow用户

发布于 2017-05-21 08:27:22

对于有属性名称列表的情况,可以使用itertools()函数(在python-3.x functools.reduce()中)和getattr()内置函数:

下面是一个示例:

代码语言:javascript
运行
复制
In [1]: class A:
   ...:     def __init__(self):
   ...:         self.a1 = B()
   ...:         

In [2]: class B:
   ...:     def __init__(self):
   ...:         self.b1 = C()
   ...:         

In [3]: class C:
   ...:     def __init__(self):
   ...:         self.c1 = 7
   ...:         

In [4]: from functools import reduce 
In [5]: reduce(getattr, [A(), 'a1', 'b1', 'c1'])
Out[5]: 7
票数 2
EN

Stack Overflow用户

发布于 2010-11-22 15:48:27

代码语言:javascript
运行
复制
class A:
    def __init__(self, a):
        self.a = a

# create objects with many a  atributes..        
a = A(A(A(A('a'))))


x = a
# as long as a has atribute a continue...
while hasattr(x, 'a'):
    print x
    x = x.a
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4247036

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档