“Метакласс”, “__ новый __”, “cls” и “супер” - каков механизм точно?

Строгие стандарты: нестатический метод [& lt; class> :: & lt; method>] не следует называть статически

Происходит при попытке вызова не- статический метод для класса, поскольку он был статичным, и вы также имеете флаг E_STRICT в настройках error_reporting().

Пример:

class HTML {
   public function br() {
      echo '
'; } }

HTML::br() или $html::br()

Вы действительно можете избежать этой ошибки, не добавляя E_STRICT к error_reporting(), например

error_reporting(E_ALL & ~E_STRICT);

, поскольку, как и для PHP 5.4.0 и выше, E_STRICT включен в E_ALL [ ref ]. Но это не рекомендуется. Решение состоит в том, чтобы определить вашу предполагаемую статическую функцию как фактическую static:

public static function br() {
  echo '
'; }

или вызвать функцию условно:

$html = new HTML();
$html->br();

Похожие вопросы:

28
задан Community 23 May 2017 в 12:34
поделиться

2 ответа

Хорошо, Вы бросили довольно много понятий в соединение здесь! Я собираюсь вытащить несколько конкретных вопросов, которые Вы имеете.

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

собственная документация Python является очень хорошей ссылкой, и абсолютно актуальный. Существует статья IBM developerWorks, которая прекрасна как введение и проявляет более основанный на учебном руководстве подход, но обратите внимание, что этому пять лет и проводит много времени, говоря о подходах более старого стиля к метаклассам.

super то, как Вы получаете доступ к суперклассам объекта. Это более сложно, чем (например), Java super ключевое слово, главным образом из-за множественного наследования в Python. Как [1 115] Супер Продуманный Вредный объясняет, использование super() может привести к Вам неявно использование цепочки суперклассов, порядок которых определяется Порядок Разрешения Метода (MRO).

Вы видите MRO для класса легко путем вызова mro() на класс (не на экземпляре). Обратите внимание, что метаклассы не находятся в иерархии суперкласса объекта.

Thomas' описание метаклассов здесь превосходен:

метакласс А является классом класса. Как класс определяет, как экземпляр класса ведет себя, метакласс определяет, как класс ведет себя. Класс является экземпляром метакласса.

В примерах Вы даете, вот то, что продолжается:

  1. вызов к __new__ пузырится до следующей вещи в MRO. В этом случае, super(MyType, cls) решил бы к type; вызов type.__new__ позволяет Python завершиться, это - нормальные шаги создания экземпляра.

  2. Этот пример использует метаклассы для осуществления одиночного элемента. Он переопределяет __call__ в метаклассе так, чтобы каждый раз, когда экземпляр класса создается, он прервал это и мог обойти создание экземпляра, если уже существует один (сохранен в [1 110]). Обратите внимание, что переопределение __new__ в метаклассе не будет достаточно хорошо, потому что это только называют при создании класс . Переопределение __new__ на классе работало бы, как бы то ни было.

  3. Это показывает способ динамично создать класс. Вот, он добавляет имя предоставленного класса к созданному имени класса и добавляет его к иерархии классов также.

я не абсолютно уверен, какой пример кода Вы ищете, но вот краткий, показывающий метаклассы, наследование и разрешение метода:

class MyMeta(type):
    def __new__(cls, name, bases, dct):
        print "meta: creating %s %s" % (name, bases)
        return type.__new__(cls, name, bases, dct)

    def meta_meth(cls):
        print "MyMeta.meta_meth"

    __repr__ = lambda c: c.__name__

class A(object):
    __metaclass__ = MyMeta
    def __init__(self):
        super(A, self).__init__()
        print "A init"

    def meth(self):
        print "A.meth"

class B(object):
    __metaclass__ = MyMeta
    def __init__(self):
        super(B, self).__init__()
        print "B init"

    def meth(self):
        print "B.meth"

class C(A, B):
    __metaclass__ = MyMeta
    def __init__(self):
        super(C, self).__init__()
        print "C init"

>>> c_obj = C()
meta: creating A (<type 'object'>,)
meta: creating B (<type 'object'>,)
meta: creating C (A, B)
B init
A init
C init
>>> c_obj.meth()
A.meth
>>> C.meta_meth()
MyMeta.meta_meth
>>> c_obj.meta_meth()
Traceback (most recent call last):
  File "mro.py", line 38, in <module>
    c_obj.meta_meth()
AttributeError: 'C' object has no attribute 'meta_meth'
21
ответ дан Community 28 November 2019 в 03:45
поделиться

Вот более прагматический ответ.

редко имеет значение

  1. " , Что такое метакласс в Python ". Нижняя строка, type является метаклассом всех классов. У Вас нет почти практического применения для этого.

    class X(object):
        pass
    type(X) == type
    
  2. " , Каковы Ваши (конкретные) варианты использования для метаклассов в Python? ". Нижняя строка. Ни один.

  3. " Супер Python является остротой, но Вы не можете использовать его ". Интересное примечание, но мало практического значения. У Вас никогда не будет потребности в разрешении сложных сетей множественного наследования. Легко препятствовать этой проблеме возникнуть при помощи дизайна стратегии explicity вместо множественного наследования.

Вот мой опыт за прошлые 7 лет программирования Python.

  1. класс А имеет 1 или более суперклассов, формирующих простую цепочку от моего класса до object.

  2. понятие "класса" определяется метаклассом, названным type. Я мог бы хотеть расширить понятие "класса", но до сих пор, это никогда не подходило на практике. Не однажды. type всегда делает правильную вещь.

  3. Используя super удается действительно хорошо на практике. Это позволяет подклассу подчиняться, это - суперкласс. Это, оказывается, обнаруживается в этих примерах метакласса, потому что они расширяют встроенный метакласс, type.

    Однако во всех ситуациях с подклассом, Вы используете super для расширения суперкласса.

Метаклассы

проблема метакласса - это:

  • Каждый объект имеет ссылку на, он - определение типа или "класс".

  • А class является, сам, также объектом.

  • Поэтому объект типа class имеет ссылку на, он - тип или "класс". "Класс" "класса" является метаклассом.

, Так как "класс" не является объектом периода выполнения C++, этого не происходит в C++. Это действительно происходит в Java, Smalltalk и Python.

метакласс А определяет поведение объекта класса.

  • 90% Вашего взаимодействия с классом должны попросить, чтобы класс создал новый объект.

  • 10% времени, Вы будете использовать методы класса или переменные класса ("статичный" в C++ или языке Java.)

я нашел несколько вариантов использования для методов уровня класса. У меня есть почти бывшие бесполезные случаи для переменных класса. У меня никогда не было ситуации для изменения пути объектные строительные работы.

9
ответ дан Community 28 November 2019 в 03:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: