26

私は、3 つの異なる方法で名前を付けることができる疑似属性または特別な属性を持つオブジェクトを持っています (注: オブジェクトを生成するコードは制御しません)。

属性の値 (設定されている属性に応じて) はまったく同じであり、さらに処理するためにそれを取得する必要があるため、データのソースに応じて、次のようなものを使用できます。

>>> obj.a
'value'
>>> obj.b
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: Obj instance has no attribute 'b'
>>> obj.c
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: Obj instance has no attribute 'c'

また

>>> obj.a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: Obj instance has no attribute 'a'
>>> obj.b
'value'
>>> obj.c
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: Obj instance has no attribute 'c'

また

>>> obj.a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: Obj instance has no attribute 'a'
>>> obj.b
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: Obj instance has no attribute 'b'
 >>> obj.c
'value'

取得に興味が'value'ありますが、残念ながら__dict__そのオブジェクトにはプロパティが存在しません。そのため、その値を取得するために私が行ったことは、一連のgetattr呼び出しを行うことでした。可能性が 3 つだけであると仮定すると、コードは次のようになります。

>>> g = lambda o, l: getattr(o, l[0], getattr(o, l[1], getattr(o, l[2], None)))
>>> g(obj, ('a', 'b', 'c'))
'value'

今、これにもっと良い方法があるかどうか知りたいですか?私は自分がやったことを100%確信しているので:)

前もって感謝します

4

5 に答える 5

55

どうですか:

for name in 'a', 'b', 'c':
    try:
        thing = getattr(obj, name)
    except AttributeError:
        pass
    else:
        break
于 2012-11-28T00:30:28.153 に答える
2

これには、任意の数のアイテムを操作できるという利点があります。

 def getfirstattr(obj, *attrs):
     return next((getattr(obj, attr) for attr in attrs 
                  if hasattr(obj, attr)), None)

これには、最終値に対して 2 つのルックアップを行うという非常に小さな欠点があります。1 回目は属性が存在することを確認するため、もう 1 回は実際に値を取得するためです。これは、ネストされたジェネレーター式を使用することで回避できます。

 def getfirstattr(obj, *attrs):
     return next((val for val in (getattr(obj, attr, None) for attr in attrs)
                  if val is not None), None)

しかし、それが大したことではないと私は本当に感じています。ジェネレーター式は、ダブルルックアップを使用しても、単純な古いループよりもおそらく高速になります。

于 2012-11-28T00:32:23.310 に答える
0

オブジェクトの構造によっては、これを行うためのより良い方法があるかもしれませんが、他に何も知らないので、任意の数の引数で機能することを除いて、現在のソリューションとまったく同じように機能する再帰的なソリューションを次に示します。

g = lambda o, l: getattr(o, l[0], g(o, l[1:])) if l else None
于 2012-11-28T00:32:30.630 に答える
0

dir を使用すると、基本的に__dict__通常と同じことが得られると思います...

targetValue = "value"
for k in dir(obj):
    if getattr(obj,k) == targetValue:
       print "%s=%s"%(k,targetValue)

何かのようなもの

>>> class x:
...    a = "value"
...
>>> dir(x)
['__doc__', '__module__', 'a']
>>> X = x()
>>> dir(X)
['__doc__', '__module__', 'a']
>>> for k in dir(X):
...     if getattr(X,k) == "value":
...        print "%s=%s"%(k,getattr(X,k))
...
a=value
>>>
于 2012-11-28T00:27:50.013 に答える
-1

そしてもう一つ:

reduce(lambda x, y:x or  getattr(obj, y, None),  "a b c".split(), None)

(Python 3 では functools から reduce をインポートする必要があります。これは Python 2 に組み込まれています)

于 2012-11-28T00:45:58.793 に答える