正如其他人指出,getattr
一般是有用的。
hasattr
具有較低的實用性;在內部,它基本上是一個getattr
中的呼叫try
/except AttributeError:
塊(如果發生AttributeError
,它返回False
,也不例外意味着True
),所以如果你正在考慮類似的代碼:
if hasattr(myobj, attrname):
attr = getattr(myobj, attrname)
...
只需使用:
try:
attr = getattr(myobj, attrname)
except AttributeError:
pass
else:
...
避免使查找,函數調用和屬性查找的數量翻倍。
或者,反覆拉動命名的屬性(S),operator.attrgetter
基本上可讓您的getattr
的優化版,預綁定屬性名稱查找(使它適合與像map
和filter
功能材料的使用,如它使它們比它們等價的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_包含屬性名稱'「名」'。我假設你寧願在這種情況下返回'姓氏',但問題(如書面)是不明確的。另外,你想用字符串做什麼,顯然包含多個屬性名稱? (例如「名字和姓氏是什麼?」) – mgilson
@ mgilson感謝您指出它;是的,你的解釋是正確的;至於第二個問題,我只能返回單個字符串,因此可能以先到者爲準 – temo
@mgilson:貪婪是一個體面的解決方案;只需從恰好是對象屬性的字符串中拉出第一個完整的「單詞」(例如匹配正則表達式「r」\ w +「',甚至可以處理下劃線)。如果你永遠不會看到'name'作爲一個單獨的單詞,你甚至不會檢查它。比試圖在查詢中執行'name'更安全的檢查將匹配查詢字符串中的部分字詞。 – ShadowRanger