I need to create a script that allows you to access object atributes dynamically from getattr()
built-in function, but I'm having lots of troubles when trying to access the object methods, here is an example:
class Dog():
def __init__(self):
self.age = 12
self.name = 'Bobby'
def eat(self):
print("I'm eating!")
If I then initialize the object and try to access their attributes:
mydog = Dog()
res = getattr(mydog, 'age')
print(res)
#--> return: 12
But if I try to access the eat
method:
mydog = Dog()
res = getattr(mydog, 'eat()')
print(res)
#--> return: AttributeError: 'Dog' object has no attribute 'eat()'
I have already tried to write the method name without quotation marks, and the best solution that I found is to write the method without the parentheses and then access the function from res
:
mydog = Dog()
res = getattr(mydog, 'eat')
res()
#--> return: I'm eating!
I could code a conditional that detects if res
contains a variable or a function and call it in case it's a method, but is there a better solution to this?
Using the @property
decorator on the method eat
it will make it so that we can retrieve it without problems with getattr
:
class Dog():
def __init__(self):
self.age = 12
self.name = 'Bobby'
@property
def eat(self):
return "I'm eating!"
mydog = Dog()
res1 = getattr(mydog, 'age')
res2 = getattr(mydog, 'name')
res3 = getattr(mydog, 'eat')
print(res1) #Output: 12
print(res2) #Output: Bobby
print(res3) #Output: I'm eating!
If we don't make eat
into a property, then calling getattr(mydog, "eat")
will return a reference to the method without calling it. However, when you set @property
in a method, that will create a getter
of eat
that will be called when you try to call that attribute.
If we then want to extend the above, so that we can change the value of eat
then we can also create a setter
of eat:
class Dog():
def __init__(self):
self._eat = "I'm eating!"
@property
def eat(self):
return self._eat
@eat.setter
def eat(self, eat_string):
self._eat = eat_string
mydog = Dog()
print(mydog.eat) #Output: I'm eating!
mydog.eat = "Stop bothering me!"
print(mydog.eat) #Output: Stop bothering me!