Skip to content

ErizoUA/Py7Web

 
 

Repository files navigation

Общий синтаксис MetaClass

Вызов встроенного класса type() может использоваться в качестве динамического эквивалента объявления класса. Ниже приведен пример определения класса с вы- зовом type():

def method(self):
 return 1
MyClass = type('MyClass', (object,), {'method': method})

Это эквивалентно явному определению класса с ключевым словом class:

class MyClass:
 def method(self):
 return 1

Каждый класс, который явно создается таким образом, имеет метакласс type. Такое поведение по умолчанию можно изменить, добавив именованный аргумент metaclass:

class ClassWithAMetaclass(metaclass=type):
 pass

Значение, предоставляемое в качестве аргумента metaclass, — это, как правило, еще один объект класса, но может быть любым другим вызываемым объектом, который принимает те же аргументы, что и класс type, и возвращает другой объект класса. Сигнатура вызова такова: type(name, bases, namespace). Значение аргументов выглядит следующим образом:

  • name — имя класса, которое будет храниться в атрибуте __name__;
  • bases — список родительских классов, которые станут атрибутом __base__ и будут использоваться для построения ПРМ вновь созданного класса;
  • namespace — пространство имен (отображение) с определениями для тела клас- са, который станет атрибутом __dict__.

Метаклассы — это своего рода метод __new__(), но на более высоком уровне определения класса. Несмотря на то что вместо метаклассов можно добавить функции, которые явно вызывают type(), обычно для этого используется другой класс, наследующий от type. Общий шаблон для метакласса выглядит следующим образом:

class Metaclass(type):
  def __new__(mcs, name, bases, namespace):
    return super().__new__(mcs, name, bases, namespace)
  @classmethod
  def __prepare__(mcs, name, bases, **kwargs):
    return super().__prepare__(name, bases, **kwargs)
  def __init__(cls, name, bases, namespace, **kwargs):
    super().__init__(name, bases, namespace)
  def __call__(cls, *args, **kwargs):
    return super().__call__(*args, **kwargs)

Аргументы name, bases, namespace имеют такое же значение, как и в type(), но все эти четыре метода могут иметь различные цели.

  • Метод __new__(mcs, name, bases, namespace) отвечает за фактическое создание объекта класса, как и у обычных классов. Первый аргумент является объектом метакласса. В предыдущем примере это был бы просто Metaclass. Обратите внимание, что mcs — общепринятое имя для данного аргумента.
  • Метод __prepare__(mcs, name, bases, **kwargs) создает пустой объект про- странства имен. По умолчанию возвращает пустой dict, но может возвращать и любой другой тип отображения. Обратите внимание: он не принимает namespace в качестве аргумента, поскольку до вызова пространство имен еще не существует.
  • Метод __init__(cls, name, bases, namespace, **kwargs) не особо популярен в реализации метакласса, но имеет тот же смысл, что и в обычных классах. Он может выполнять дополнительную инициализацию объекта класса, как только тот будет создан с помощью __new__(). Первый позиционный аргумент теперь называется cls и обозначает уже созданный объект класса (экземпляр метакласса), а не объект метакласса. В момент вызова __init__() класс уже был создан, и поэтому данный метод не так полезен, как __new__(). Реализация такого метода очень похожа на использование декораторов класса, но основное отличие состоит в том, что __init__() будет вызываться для каждого подкласса, а вот декораторы класса для подклассов не вызываются.
  • Метод __call__(cls, *arg, **kwargs) вызывается, когда вызывается экземпляр метакласса. Последний является объектом класса, он вызывается при создании новых экземпляров класса. Метод позволяет переопределить способ создания и инициализации экземпляров класса.

Виконання коду

  • exec(object, global, locals) — позволяет динамически выполнять код Python. Элемент object должен быть строкой или объектом кода (см. функцию compile()), представляющим один оператор или последовательность нескольких. Аргументы global и local — это глобальные и локальные пространства имен для исполняемого кода, которые не являются обязательными. Если они не указаны, то код выполняется в текущем пространстве. Если указаны, то global должен быть словарем, а local может быть любым объектом отображения, он всегда возвращает None.

  • eval(expression, global, locals) — используется для вычисления данного выражения и возвращает его значение. Похоже на exec(), но expression — это всего одно выражение Python, а не последовательность операторов. Возвращает значение вычисленного выражения.

  • compile(source, filename, mode) — компилирует источник в объект кода или AST. Исходный код предоставляется в качестве строкового значения в аргументе source. filename — это файл, из которого читается код. Если связанного файла нет (например, потому что он был создан динамически), обычно используется значение <string>.

Режим

  • exec (последовательность операторов),
  • eval (одно выражение) или single (один интерактивный оператор, например, в интерактивной сессии Python).

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Python 76.0%
  • HTML 18.8%
  • JavaScript 3.3%
  • CSS 1.1%
  • Mako 0.7%
  • Dockerfile 0.1%