Metaclasses in Python

The translation of the article was prepared in anticipation of the start of the " Python Developer. Basic" course .


– , . , «» , , .

- . , , . Python .

Python «, ».

. :

  • ;

  • ;

  • ;

  • ;

  • ;

  • / .

, , Python, , «». , , , , . , metaclass ( ), type() (.. _call_ ). , metaclass , type.

. , _new_ type._new_:

class LittleMeta(type):
    def __new__(cls, clsname, superclasses, attributedict):
        print("clsname: ", clsname)
        print("superclasses: ", superclasses)
        print("attributedict: ", attributedict)
        return type.__new__(cls, clsname, superclasses, attributedict)

LittleMeta :

class S:
    pass


class A(S, metaclass=LittleMeta):
    pass


a = A()
clsname:  A
superclasses:  (<class '__main__.S'>,)
attributedict:  {'__module__': '__main__', '__qualname__': 'A'}

, LittleMeta._new_, type._new_

EssentialAnswers, augment_answer


x = input("Do you need the answer? (y/n): ")
if x.lower() == "y":
    required = True
else:
    required = False

    
def the_answer(self, *args):              
        return 42

    
class EssentialAnswers(type):
    
    def __init__(cls, clsname, superclasses, attributedict):
        if required:
            cls.the_answer = the_answer
                           
    
class Philosopher1(metaclass=EssentialAnswers): 
    pass


class Philosopher2(metaclass=EssentialAnswers): 
    pass


class Philosopher3(metaclass=EssentialAnswers): 
    pass
    
    
plato = Philosopher1()
print(plato.the_answer())


kant = Philosopher2()
# let's see what Kant has to say :-)
print(kant.the_answer())
Do you need the answer? (y/n): y
42
42

«Type and Class Relationship» , Python :

type(classname, superclasses, attributes_dict)

, . . Philosopher1, Philosopher2 Philosopher3 «» EssentialAnswers. EssentialAnswers type:

EssentialAnswer(classname, superclasses, attributes_dict)

, :

EssentialAnswer('Philopsopher1', 
                (), 
                {'__module__': '__main__', '__qualname__': 'Philosopher1'})

Philosopher .

  - , . , . , . , , , .

class Singleton(type):
    _instances = {}
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(Singleton,                                      cls).__call__(*args, **kwargs)
        return cls._instances[cls]
    
    
class SingletonClass(metaclass=Singleton):
    pass


class RegularClass():
    pass


x = SingletonClass()
y = SingletonClass()
print(x == y)


x = RegularClass()
y = RegularClass()
print(x == y)
True
False

Singleton-, Singleton, :

class Singleton(object):
    _instance = None
    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = object.__new__(cls, *args, **kwargs)
        return cls._instance

    
class SingletonClass(Singleton):
    pass

class RegularClass():
    pass


x = SingletonClass()
y = SingletonClass()
print(x == y)


x = RegularClass()
y = RegularClass()
print(x == y)
True
False

.


:




All Articles