Рубрики
Без рубрики

Метаклассы в Питоне

На большинстве языков программирования классы – это просто куски кода, которые определяют правила для объекта, B … Теги с производительностью, метаклассами, Python, учебником.

На большинстве языков программирования классы – это просто куски кода, которые определяют правила для объекта, но в Python, поскольку вы должны услышать, что все является объектом: оказывается, что это верно для самих классов. Классы фактически являются первоклассными объектами, они могут быть созданы во время выполнения, передаваемые в качестве параметров, возвращаемых из функций и назначаемых переменным.

Давайте посмотрим на пример ниже –

class Tutorial:
    pass

print(Tutorial())

# Output - 
# <__main__.Tutorial object at 0x7fd92c1500f0>

Как мы можем видеть экземпляр Учебное пособие Класс говорит нам, что это объект главного учебного объекта. в некотором месте.

Теперь просто распечатайте сам класс –

print(Tutorial)

# Output - 
# 

Причина, по которой мы можем сделать это, потому что Учебное пособие Класс – это объект, как и любой другой объект. Когда вы используете класс Ключевое слово, Python создает этот объект автоматически. Это пример метакласса – Тип Отказ

Метакласс – это класс класса; Определяет, как класс ведет себя.

Теперь для того, чтобы сделать это легче, отпустить углубления, Может быть, вы нашли на Тип Ключевое слово в Python? Который используется для поиска типа объекта –

print(type(1))

# Output - 
# 

print(type('Hey'))

# Output - 
# 

Как и ожидалось 1 Тип int сорт, Эй, Тип ул ...| класс, давайте узнаем тип нашего класса -

print(type(Tutorial))

# Output - 
# 

На этот раз мы получаем распечатка, которую Учебное пособие имеет тип Тип класса Отказ Но как насчет Тип сам? Какой тип Тип ?

print(type(type))

# Output - 
# 

Тип Тип это Тип класса Возможно, вы найдете это странно. Таким образом, мы находим, что Тип также его собственная метакласс!

Понимание того, как Metaclasses работает

Тип это встроенный метакласс в Python. Используется для построения классов, таких как класс, используется для построения объектов. Итак, когда мы создаем любой класс, то метакласс по умолчанию ( тип ) вызывается и дает нам возможность использовать его в качестве объекта. Это означает, что каждый класс в Python также является объектом тип , Поэтому мы можем использовать Тип непосредственно сделать класс, без синтаксиса класса. Функция типа () может использоваться для непосредственного определения классов, используя следующие три аргумента –

type(, , )
  • Имя – Это внутреннее представление класса. Это название класса.

  • Основы – Это указывает все, что мы наследуем от суперкласса или родительского класса. Это кортеж родительского класса.

  • DCT – Это указывает словарь пространств имен, содержащий определения методов класса и переменных.

Чтобы сделать его более понятно –

Test = type('Test', (), {})

так что вышеуказанная линия кода полностью эквивалентна этому ниже коду –

class Test:
    pass

Там нет абсолютно ничего другого.

Следовательно, если мы хотим изменить поведение классов, нам нужно будет написать на заказ Metaclass.

Чтобы создать наш собственный пользовательский метакласс, мы сначала наследовать Metaclass по умолчанию Тип и внедрить метакласс __new__ Метод и/или __init__ метод.

  • __new__ : Этот метод dunder обычно переопределяет тип __new__ , чтобы изменить некоторые свойства класса, который будет создан, Перед тем, как позвонить на оригинал __new__ что создает класс.

  • __init__ : Этот метод называется, когда вы хотите управлять инициализацией после создания экземпляра/объекта.

class MyMeta(type):
    def __new__(self, name, bases, attr):
        print(attr)
        return type(name, bases, attr)

Так что здесь я определил простое метакласс Mymeta И мы просто собираемся распечатать атрибуты, чтобы мы могли видеть, как они выглядят так. После этого я определил другой класс Образец и у него есть метакласс Mymeta , с имя и возраст Переменная –

class Sample(metaclass=MyMeta):
    name = 'bob'
    age = 24

Сейчас Не создавая экземпляр, это все еще работает так, как вы можете увидеть вывод ниже –

{'__module__': '__main__', '__qualname__': 'Sample', 'name': 'bob', 'age': 24}

Так как этот класс Образец был создан –

Переводчик видит метаклас = Mymeta Определяется в Образец Итак, теперь интерпретатор имеет информацию, которую Metaclass по умолчанию Тип не должен использоваться для создания Образец класс, вместо Mymeta должен быть использован для создания Образец сорт.

Итак, переводчик звонит на Mymeta создать класс Образец С Когда Mymeta называется, __new__ MyMeta вызывается, и он распечатает атрибуты и используя Тип его построить экземпляр Mymeta который является Образец и возвращает нам объект.

Этот метакласс только переопределяет создание объекта. Все остальные аспекты поведения класса и объекта все еще обрабатываются по типу.

Теперь мы накрыли достаточно теории, чтобы понять, какие метаклассы и как писать пользовательские метаклассы. Теперь давайте посмотрим простой сценарий реального дела –

Предположим, у нас есть требование, чтобы все атрибуты вашего класса должны быть в верхнем регистре, есть несколько способов достижения этой функции, но здесь мы собираемся достичь этого, используя Метакласс на уровне модуля, Так Если в словаре пространства имен (атрибуты), если ключ не запускается с двойного подчеркивания, нам нужно изменить его в верхнем регистре –

class MyMeta(type):
    def __new__(self, name, bases, atts):

        print(f'current_attributes - {atts}\n')
        new_atts = {}

        for key, val in atts.items():
            if key.startswith('__'):
                new_atts[key] = val
            else:
                new_atts[key.upper()] = val

        print(f'modified_attributes - {new_atts}')        
        return type(name, bases, new_atts)


class Sample(metaclass=MyMeta):
    x = 'bob'
    y = 24

    def say_hi(self):
        print('hii')

Выход –

current_attributes - {'__module__': '__main__', '__qualname__': 'Sample', 'x': 'bob', 'y': 24, 'say_hi': }

modified_attributes - {'__module__': '__main__', '__qualname__': 'Sample', 'X': 'bob', 'Y': 24, 'SAY_HI': }

Как вы можете видеть выше, мы напечатали текущие атрибуты и создали словарь, который мы использовали для представления наших измененных атрибутов.

Здесь мы просто проверяем, запускается ли ключ с двойной подчеркиванием, просто добавляет правильное значение, в противном случае мы добавляем атрибут верхнего регистра с этим соответствующим значением.

Теперь, чтобы убедиться, что это работает, давайте попробуем, я создал экземпляр Образец и просто напечатайте один из старых атрибутов.

s = Sample()
s.x

Выход –

AttributeError Traceback (most recent call last)
 in 
      1 s = Sample()
----> 2 s.x

AttributeError: 'Sample' object has no attribute 'x'

Как и ожидалось, у нас есть ошибка AttributeError , что совершенно нормально, потому что мы только что модифицировали строительство объекта, давайте попробуем доступ к модифицированным атрибутам –

print(s.X)

s.SAY_HI()

Выход –

bob
hii

Вот почему они называют это магией, потому что с таком крючком в создании классов вы действительно можете обеспечить принуждение довольно ограничения на то, как создаются классы

Таким образом, если вы хотите, если вы хотите, чтобы каждый класс в конкретном модуле никогда не разрешается использовать определенный атрибут или для выполнения определенного шаблона, который вы можете установить метаклассы для этих конкретных модулей.

Заключение

Целью метакласов не заменяет различие класса/объекта с метакласс/классом – это изменить поведение определений классов (и, следовательно, их экземпляры). Разумный характер использования метакласса делает что-то один раз, когда класс определен, а не повторно, когда тот же класс создается. Когда несколько классов разделяют одно и то же специальное поведение, повторение metaclass = x Очевидно, лучше, чем повторять код специального назначения и/или внедрения специальных общих суперкласс.

Ссылка

https://stackoverflow.com/questions/100003/what-are-metaclasses-in-python

https://stackoverflow.com/questions/392160/what-are-some-concrete-use-cases-for-metaclasses/393368

Оригинал: “https://dev.to/sharmapacific/metaclasses-in-python-1oc3”