2

そのような動作を実装する必要があります:

obj.attr1.attr2.attr3 --> obj.attr1__attr2__attr3

obj のクラスをオーバーライドし__getattribute__、何らかの形で Python 記述子も使用する必要があるようです。

アップデート:

私はdjangoプロジェクトを持っています。

obj は django-haystack の SearchResult インスタンスであり、django モデルからの多くの非正規化データ ( user__name、 ) が含まれており、互換性の理由user__addressからアクセスする必要があります。result.user.name

THC4kの回答の更新:

私が持っている場合:

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'

どんな助けでも大歓迎です。

4

3 に答える 3

3

これは、既存のコードの修正を回避するための単なるスキームではありません。

これを行うには正当な理由があると思います.Luaで同様のことを行って、公開されたすべての関数のコードを実際に記述することなく、一部のCコードのラッパーを実装しました.

ただし、少なくとも実際のクラスをプロキシから分離する必要があります。

# 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 提案:

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
于 2010-11-22T16:01:28.807 に答える
2

属性名のリストがある場合は、itertools()関数 ( python-3.x functools.reduce()) とgetattr()組み込み関数を使用できます。

次に例を示します。

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
于 2017-05-21T08:27:22.560 に答える
0
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
于 2010-11-22T15:48:27.340 に答える