I have a class who's fields are an instance of another class.
class Field:
def get[self]:
def set[self, value]:
def delete[self]:
class Document:
def __init__[self]:
self.y = Field[]
self.z = True
What I'd like to be able to do is when an instance of the parent refers to its attributes, instead it calls the child's methods.
d = Document[]
d.y = 'some value' # Calls the `set` function of the Field
d.y == 'some value' # Calls the `get` function of the Field
del d.y # Calls the `delete` function of the Field
The other catch is that I only want this behavior when the field is of type Field
.
I'm running into recursion problems try to use __getattr__
and the like, along the lines of:
def __getattr__[self, key]:
if isinstance[getattr[self, key], Field]:
return getattr[self, key].get[]
return getattr[self, key]
The recursion is fairly obvious why its happening... but how do I avoid it?
I've seen a few examples already on StackOverflow, but I can't seem to figure out how to get around it.
- Maximum recursion depth error with getattr
- Understanding the difference between __getattr__ and __getattribute__
Python getattr[] function is used to access the attribute value of an object and also gives an option of executing the default value in case of unavailability of the key.
Syntax : getattr[obj, key, def]
Parameters :
- obj : The object whose attributes need to be processed.
- key : The attribute of object
- def : The default value that need to be printed in case attribute is not found.
Returns : Object value if value is available, default value in case attribute is not present
and returns AttributeError in case attribute is not present and default value is not
specified.
How getattr[] works in Python
Example 1: Demonstrating working of getattr[]
Python3
class
GfG:
name
=
"GeeksforGeeks"
age
=
24
obj
=
GfG[]
print
[
"The name is "
+
getattr
[obj,
'name'
]]
print
[
"Description is "
+
getattr
[obj,
'description'
,
'CS Portal'
]]
print
[
"Motto is "
+
getattr
[obj,
'motto'
]]
Output:
The name is GeeksforGeeks Description is CS Portal
Exception:
AttributeError: GfG instance has no attribute 'motto'
Example 2: getattr[] when named attribute is not found
Python3
class
GfG:
name
=
"GeeksforGeeks"
age
=
24
obj
=
GfG[]
print
[
"Gender is "
+
getattr
[obj,
'gender'
]]
Output:
AttributeError: 'GfG' object has no attribute 'gender'
Example 3: Performance Analysis and getattr python with parameter
Python3
import
time
class
GfG:
name
=
"GeeksforGeeks"
age
=
24
obj
=
GfG[]
start_getattr
=
time.time[]
print
[
"The name is "
+
getattr
[obj,
'name'
]]
print
[
"Time to execute getattr "
+
str
[time.time[]
-
start_getattr]]
start_obj
=
time.time[]
print
[
"The name is "
+
obj.name]
print
[
"Time to execute conventional method "
+
str
[time.time[]
-
start_obj]]
Output:
The name is GeeksforGeeks Time to execute getattr 5.0067901611328125e-06 The name is GeeksforGeeks Time to execute conventional method 1.1920928955078125e-06
Example 4: getattr Python default value
Python3
class
GfG:
name
=
"GeeksforGeeks"
age
=
24
obj
=
GfG[]
print
[
"Motto is "
+
getattr
[obj,
'motto'
]]
Output:
AttributeError: 'GfG' object has no attribute 'motto'
Example 5: Python getattr[] function call
Python3
class
GfG:
def
__init__[
self
, name, age]:
self
.name
=
name
self
.age
=
age
def
call[
self
, x]:
print
[f
"{self.name} called with parameters '{x}'"
]
return
obj
=
GfG[
"Vivek"
,
10
]
print
[obj]
print
[GfG]
print
[
getattr
[obj,
'call'
]]
getattr
[obj,
'call'
][
'arg'
]
Output:
Vivek called with parameters 'arg'
Result : Conventional method takes less time than getattr[], but when default values have to be used in case of missing attributes, getattr[] is a good choice.
Applications: The are many applications of getattr[], a few of them already mentioned in cases of absence of attributes of objects, in web developments where some of the form attributes are optional. Also useful in cases of Machine Learning feature collections in case some features sometimes go missing in data collection.