I want to:
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
__repr__ = __str__
person = Person("Earl", "Martin", "Jason", 40)
As others have noted,
getattr is generally useful.
hasattr is of lesser utility; internally, it's basically a
getattr call in a
except AttributeError: block (if
AttributeError occurs, it returns
False, no exception means
True), so if you're considering code like:
if hasattr(myobj, attrname): attr = getattr(myobj, attrname) ...
try: attr = getattr(myobj, attrname) except AttributeError: pass else: ...
to avoid doubling the number of LEGB lookups, function calls and attribute lookups.
Alternatively, for repeatedly pulling named attribute(s),
operator.attrgetter basically lets you make an optimized version of
getattr that pre-binds the attribute name to lookup (making it ideal for use with stuff like the
filter functions, as it makes them more efficient than their equivalent listcomps/genexprs).
On top of those, depending on what your goal is, the
dir and (slightly less reliably, due to issues with classes that use
__slots__ to define a known set of variables to reduce memory usage and prevent auto-vivification)
vars functions may be useful.
For example, in your example case of pulling any attributes corresponding to a word from a string, you could do a bulk identification of legal attribute names using
dir() and your choice of
set operations (or a mix) depending on the importance of order, uniqueness, etc.:
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)
Then usage is:
>>> 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