The magic method is simply a method that is called implicitly, often to perform an operation on a type. For example, you can define a __bool__ method to indicate whether a True/False object is in a boolean context (if the default behavior, based on __len__ or True , is not appropriate). Many aspects of the behavior of objects in Python can be changed in this way. For example, the plumbum module , due to operator overloading, embeds sh -like language directly into 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 is the definition of calling the right method of the desired class?
repr(SomeClass()) causes a call to SomeClass.__repr__ (if defined), because the documentation for the repr() function says so .
In general, nothing especially happens, for example, you can define your protocol:
def quack(obj): return getattr(obj, 'quack', None)()
Any object for which the quack() method is quack() , regardless of its base classes , can be passed to the quack () function:
class Duck: def quack(self): return "Quack! Quack! Quack!" print(quack(Duck()))
For other classes, TypeError thrown:
try: quack(1) except TypeError: print("целое число не квакает")
The difference of quack() from real magic methods is that double underlining is not used in the method name, by agreement , reserved for protocols defined by the language itself and there is no requirement to define a method in the class itself (definitions from the Meta class or method assignment to an object may not work for magical 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 in order for len() work, it is necessary to place 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 by reference . In CPython, almost all special methods (a term for magic methods from a language specification) are stored in special slots in a type .
return "({x})".format(x)should bereturn "({})".format(self.x)- Xander