Давайте поговорим о том, как на самом деле работают методы Python.
Вы могли заметить, что методы Python объявляются точно так же, как автономные функции, но внутри класса. Это потому, что методы Python на самом деле являются автономными функциями, которые находятся внутри класса. Аргумент self
/cls
не является особым. Это просто первый аргумент функции.
Прежде чем мы пойдем дальше, я хотел бы отметить, что вы, похоже, не наследуете явно от object
. Если вы работаете в Python 2.x, в корне графа нет object
, если только вы не наследуете его явно. Это плохо, и вы должны прямо или косвенно наследоваться от object
, когда это возможно в новом коде. Наследование от object
в Python 3 является законным и безвредным, но ненужным. Остальная часть этого обсуждения предполагает, что вы либо работаете в 3.x, либо исправили это.
Когда вы получаете доступ к переменной, функции, методу или объекту любого другого типа с помощью foo.bar
, вызываются определенные ловушки, известные как «протокол дескриптора». Вам не нужно знать подробности этого, чтобы понять, как работают функции. Все, что вам нужно знать, это:
- Во-первых, если есть переменная экземпляра
bar
, напрямую связанная с foo
(и foo
не является классом), мы просто возвращаем ее напрямую.(*)
- Если
foo
— это класс, а bar
— это @classmethod
функция (**), объявленная либо в foo
, либо в одном из его суперклассов, то перед возвратом первый аргумент устанавливается равным foo
. В противном случае он возвращается без изменений.(***) Если мы что-то вернули, мы останавливаемся здесь.
- Мы ищем «порядок разрешения метода»
foo
. Он состоит из класса foo
(известного как type(foo)
), суперкласса этого класса и так далее, пока мы не дойдем до object
. В случае множественного наследования это становится немного сложнее, но опять же, вам не нужно этого знать.
- Возьмите переменную
bar
из первого класса, в котором она есть (назовите ее Baz
).
- Если
Baz.bar
является обычной, недекорированной функцией, установите ее первый аргумент равным foo
и верните его.
- В противном случае, если
Baz.bar
является функцией @classmethod
, установите ее первый аргумент равным type(foo)
и верните его.
- В противном случае, если
Baz.bar
является функцией @staticmethod
или вообще не является функцией (**), верните ее без изменений.
Как видите, если метод объявлен @classmethod
, первым аргументом всегда является класс, а не экземпляр, независимо от того, как вызывается функция. Это означает, что у вас нет доступа к переменным экземпляра foo
, поскольку у вас нет доступа к самому foo
. Любые переменные, установленные в __init__()
, являются переменными экземпляра, поэтому здесь они не видны.
И вот все, о чем я солгал:
(*): Python фактически сначала выполняет остальную часть работы, а затем возвращается к этому шагу. Но это имеет значение только для таких вещей, как @property
, которые фактически могут переопределять локальные переменные экземпляра. Обычными методами нельзя.
(**): Это ложь. В этом случае Python также выполняет специальную обработку @property
функций и всего остального, что реализует определенные специальные методы.
(***): Я также игнорирую несвязанные методы в Python 2.x, потому что, за исключением некоторых действительно странных случаев (когда вы пытаетесь передать объект неправильного типа в качестве первого аргумента вручную), они не имеют никакого значения. . Их нет в Python 3.
person
Kevin
schedule
15.01.2016
classmethod
, если вам нужен метод экземпляра? - person user2357112 supports Monica   schedule 15.01.2016__init__
vars, является атрибутами экземпляра. Причина, по которой метод класса называется методом класса, заключается в том, что он имеет доступ только к классу, а не к экземпляру. Почему вы вообще используетеclassmethod
? - person BrenBarn   schedule 15.01.2016__init__
в качестве конструктора, в котором после установки значения могут использоваться где угодно в методах класса... - person NoobEditor   schedule 15.01.2016classmethod
? Как вы думаете, какова цельclassmethod
? Похоже, вам следует прочитать руководство по Python, чтобы понять, как использовать классы в Python. - person BrenBarn   schedule 15.01.2016classmethod
иinstance
? Доступ к методу черезobject
является экземпляром, а выполнениеA(). class_method()
является методом класса? - person NoobEditor   schedule 15.01.2016a=A()
a.method()
A().method()
больше или меньше того же, но, видимо, не в питоне... это то, что меня смутило.... имеет смысл? - person NoobEditor   schedule 15.01.2016classmethod
. Кажется, вы думаете, что метод класса — это просто любой метод, который вы определяете в классе, но это не так. Возможно, вы захотите просмотреть этот вопрос и этот вопрос. Если вам нужен доступ к переменным экземпляра, не используйтеclassmethod
. Вот и все. - person BrenBarn   schedule 15.01.2016