Magic methods

How is the magic method architecture implemented in python? For example:

class SomeClass:
    def __init__(self, x):
        self.x = x

    def __repr__(self):
        return "({})".format(self.x)

a = SomeClass(23)
print(repr(a))

That is, how is the call of the desired method of the desired class determined? (repr of the SomeClass class)?

Author: jfs, 2017-03-30

3 answers

A little supplement to the previous answers. According to the official documentation, here here, special methods (this is what magic methods are called in the documentation) this is python's approach to operator overloading, allowing classes to define their behavior in with respect to language operators. From this we can conclude that the interpreter has a "certain table" (let's call it so) of the correspondence of operators to the methods of the class. By overloading these methods, you can control the "behavior" language operators relative to your class.

Also, if you make any special (magic) method None in some class, it means that this operation is not available for some class, and the corresponding operator applied to this class will return TypeError.

The signature of the function repr for CPython, you can only see in the source code on C. In the module builtins.py it looks like this

def repr(obj): # real signature unknown; restored from __doc__
    """
    Return the canonical string representation of the object.

    For many object types, including most builtins, eval(repr(obj)) == obj.
    """
    pass

But I think here and so I see.

When you create your class without inheritors, you implicitly inherit the object class with all its special methods, including and repr. In the module builtins.py it looks like this:

class object:
    """ The most base type """
    .... # ещё порядка 20 магических методов
    def __repr__(self, *args, **kwargs): # real signature unknown
    """ Return repr(self). """
    pass

Thus, we can draw another conclusion that even an "empty" user class is ready for use, in one form or another, by operators (functions) the language.

And a little more about the correspondence here

 4
Author: ivan_susanin, 2017-03-31 09:05:48

A magic method is simply a method that is called implicitly, often to perform an operation on a type. For example, you can define __bool__ the method to specify whether an object is True/False in a boolean context (if the default behavior based on __len__ or True is not appropriate). So many aspects of the behavior of objects in Python can be changed in this way. For example, plumbum the module , due to operator overloading, embeds sh-similar language directly in Python:

#!/usr/bin/env python
from plumbum.cmd import awk, sort

(awk["-f", "script.awk"] << "input data" | sort > "outfile.txt")()

How is the magic method architecture implemented in python?
How does the definition of the call to the desired method of the desired class occur?

repr(SomeClass()) results in a call to SomeClass.__repr__ (if defined), because the documentation of the repr() function says so.

In general, nothing particularly happens, for example, you can define your protocol:

def quack(obj):
    return getattr(obj, 'quack', None)()

Any object for which the {[16] method is defined]}, regardless of its base classes, you can pass to the quack () function:

class Duck:
    def quack(self):
        return "Quack! Quack! Quack!"

print(quack(Duck()))

For the other classes, TypeError is thrown out:

try:
    quack(1)
except TypeError:
    print("целое число не квакает")

Difference between quack() and true magic methods, that does not use the double underscore in the method name, by convention, reserved for protocols defined by the language itself and there is no requirement define a method in the class itself (definitions from the Meta class or assigning a method to an object they may not work directly for magic methods):

>>> class C:
...     pass    
>>> c = C()    
>>> c.__len__ = lambda: 0    
>>> len(c)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: object of type 'C' has no len()

For comparison, quack() can be directly assigned to the object itself:

>>> c.quack = lambda: "ga ga"
>>> quack(c)
'ga ga'

But for len() to work, you need to put the definition in the class itself:

>>> class C:
...     def __len__(self):
...         return 0

>>> len(C())
0

This is done to optimize the speed of calling such methods and to avoid the "metaclass confusion" described above at the link. In CPython, almost all special methods are (the term for magic methods is from the language specification) are stored in special slots in the type.

 4
Author: jfs, 2017-05-23 12:39:01

Look at this question like this

def __repr__(self):
     return "({x})".format(x=self.x)

class SomeClass:pass

a = SomeClass()
a.x = 23

print(__repr__(a))
 0
Author: vadim vaduxa, 2017-03-30 17:44:15