我想:
检查字符串是否包含对象属性
如果是,则访问属性
所以对于类对象
class Person(object):
name = ""
age = 0
major = ""
def __init__(self, name="", surname="", father="", age =0):
self.name = name
self.surname = surname
self.father = father
self.age = age
self.identity = name +" "+ surname
def __str__(self):
return self.identity
__repr__ = __str__
和对象
person = Person("Earl", "Martin", "Jason", 40)
我想要字符串“名字是什么”
返回person.name
(我已经知道字符串是关于哪个对象的)
最基本的解决方案是对每个存在的属性执行case,但是实际的代码有很多,我确信我不需要手动地将它们写出来,我只是刚刚开始编程,所以我不确定为此使用什么语法
感谢任何帮助
最佳答案
正如其他人所指出的,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:
...
为了避免LEGB查找、函数调用和属性查找的数量加倍。
或者,对于重复拉取命名属性,
operator.attrgetter
基本上允许您制作一个优化版本的getattr
,该版本预先将属性名称绑定到查找(使其非常适合与map
和filter
函数一起使用,因为它使它们比等价的listcomps/genexpr更有效)。除此之外,取决于你的目标是什么,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