Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use __getattr__ to delegate methods to attribute?

I have the following class:

class MyInt:
    def __init__(self, v):
        if type(v) != int:
            raise ValueError('value must be an int')
        self.v = v

    def __getattr__(self, attr):
        return getattr(self.v, attr)

i = MyInt(0)
print(i + 1)

I get the error: TypeError: unsupported operand type(s) for +: 'MyInt' and 'int'

Shouldn't i.__add__(1) be called? And shouldn't __getattr__ be called when no such method is found in the MyInt class?

like image 621
Jon McClung Avatar asked Jul 10 '16 17:07

Jon McClung


People also ask

Does Getattr work with methods?

Okay, so it's cool that you can use getattr to get methods as well as properties, but how does that help us? Well, this can definitely be useful in keeping your code DRY if you have some common logic surrounding branching method calls.

What does __ Getattr __ do in Python?

Python getattr() function is used to get the value of an object's attribute and if no attribute of that object is found, default value is returned.

What is Getattr () used for l1?

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. Parameters : obj : The object whose attributes need to be processed. key : The attribute of object.

What would happen if Getattr () tried to retrieve an attribute of an object that did not exist?

The getattr() method returns the value of the named attribute of an object. If not found, it returns the default value provided to the function.


1 Answers

__getattr__ cannot be used to generate other magic methods. You'll need to implement all of them individually.

When the Python language internals look up magic methods like __add__, they completely bypass __getattr__, __getattribute__, and the instance dict. The lookup goes roughly like

def find_magic_method(object, method_name):
    for klass in type(object).__mro__:
        if method_name in klass.__dict__:
            return klass.__dict__[method_name]
    raise AttributeError

If you want to see the exact lookup procedure, it's _PyObject_LookupSpecial in Objects/typeobject.c.

If you're wondering why Python does this, there are a lot of magic methods for which it would be really awkward or impossible to do what you were expecting. For example, Python couldn't possibly use __getattribute__ to look up __getattribute__, as that would cause infinite recursion with no base case.

like image 197
user2357112 supports Monica Avatar answered Nov 15 '22 09:11

user2357112 supports Monica