、getattr
は一般的に有用です。
hasattr
はあまり有効ではありません。あなたは、コードを検討しているので、もし内部で、それはのように、基本的にtry
/except AttributeError:
ブロックでgetattr
コール(AttributeError
が発生した場合、それは例外がTrue
を意味し、False
を返します)です:
if hasattr(myobj, attrname):
attr = getattr(myobj, attrname)
...
だけ使用します。
try:
attr = getattr(myobj, attrname)
except AttributeError:
pass
else:
...
LEG Bルックアップ、関数呼び出し、および属性ルックアップの数を2倍にすることを避ける必要があります。
また、繰り返しという名前の属性(複数可)を引くため、operator.attrgetter
は基本的に、あなたのように、(map
とfilter
機能のようなものの使用に最適です検索する属性名を事前に結合しgetattr
の最適化されたバージョンを作ることができます同等のlistcomps/genexprsより効率的になります)。
あなたの目標に応じて、the dir
(やや信頼性が低い、クラスthat use __slots__
to define a known set of variables to reduce memory usage and prevent auto-vivificationの問題のため)vars
functionが役に立ちます。
例えば、文字列から単語に対応する任意の属性を引っ張るあなたの例の場合には、あなたはvars()
/dir()
とfilter
またはset
操作の選択(またはミックス)を使用して、法的な属性名のバルク識別を行うことができますオーダー、一意性の重要性など:
from future_builtins import filter # Only on Py2, not Py3
import operator
import re
def query_obj(obj, querystr):
# Extract list of legal attribute names from string
words = re.findall(r'\w+', querystr)
# Reduce to names present on object's __dict__; no need to construct temporaries
attrnames = filter(vars(obj).__contains__, words)
# Alternate if __slots__ might be an issue (temp list & frozenset):
attrnames = filter(frozenset(dir(obj)).__contains__, words)
# Or combine the two to be sure (on Py3, use .keys() instead of .viewkeys())
# (temp list and set):
attrnames = filter((vars(obj).viewkeys() | dir(obj)).__contains__, words)
# Convenient way to get all names discovered at once; returns single object
# for single attr, tuple of objects for multiple attrs:
return operator.attrgetter(*attrnames)(obj)
# If you want a tuple unconditionally, use this instead:
return tuple(getattr(obj, name) for name in attrnames)
# Or to only return the first attribute encountered, raising StopIteration
# if no attributes are found:
return next(getattr(obj, name) for name in attrnames)
に応じて、次に使用方法は次のとおりです。
>>> person = Person("Earl", "Martin", "Jason", 40)
>>> query_obj(person, "What is the name?")
'Earl' # Would be ('Earl',) in unconditional tuple case
>>> query_obj(person, "What is the name and surname?")
('Earl', 'Martin') # Would be 'Earl' in single return case
文字列は、プロパティ名 '「の名前を」'含ま_also_「姓ものです」。私はあなたがむしろ 'surname'を返すと思っていますが、その質問は(書かれているように)あいまいです。また、明らかに複数のプロパティ名を含む文字列で何をしたいですか? (例:「名前と姓は何ですか?」) – mgilson
@mgilsonご指摘いただきありがとうございます。はい、あなたの解釈は正しいです。 2番目の質問については、おそらくどちらか早いほうに1文字列しか返せません。 – temo
@mgilson:貪欲はまともな解決策です。オブジェクト上の属性である文字列から、最初の完全な "単語"(正規表現の 'r '\ w +''と一致するハンドルのアンダースコアと一致させるなど)を引っ張ります。あなたが 'name'をスタンドアロンの単語として見たことがないなら、あなたはそれをチェックすることさえありません。クエリー文字列中の部分的な単語と一致する 'name in query'チェックを行うよりも安全です。 – ShadowRanger