正如其他人指出,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