Как - методы класса назначенный по умолчанию Пайтон?

Копаясь с python, я дал себе bruces с ошибкой тип takes 2 positional arguments but 3 were given. Мой метод, который внутри класса, имел форму

def add(x, y) :
    return x +y

Он только что прочитал основную документацию по классам и знал существование модификаторов @classmethod и @staticmethod, что документация говорит, что это главным образом "синтаксический сахар". Также я знаю, что self или cls это не размещенные слова, так что не важно, если мой первый параметр называется self, cls или x.

Полученная ошибка дает мне из-за того, что думает, что по умолчанию, методы класса считались методами класса (и первый аргумент считается ссылкой на класс / инстанцию), и хочу ли я их статические у меня есть тогда, что помещать модификатор, но я не нашел ничего, что бы это показывало ясно в документации.

Смоги казаться очевидным, но для меня он был достаточно контраинтуитивным, что, если я заявляю

def saludar() :
   print("hola")

внутри класса, вызов даст ошибку, потому что у функции есть 0 параметров, но мы попробуем перемещать (подразумеваемый) один с вызовом. Кто-то может подтверждать, что методы назначены по умолчанию класса, как будто они были записанными с @classmethod?

27
задан 12.12.2015, 02:42
3 ответа

Методы класса, по умолчанию, функционируют следующей формы:


Я женю 1: Методы Инстанции

Класс без @classmethod или @staticmethod. Поскольку ты упоминаешь, self или cls это не размещенные слова, но - предложенные, чтобы поддерживать стандарт в Программировании, Ориентируемом на Объекты на Пайтона:

class Clase:
    def __init__(cualquiercosa, nombre):
        cualquiercosa.nombre = nombre

    def hola(cualquiercosa):
        print('¡Hola, %s!' % cualquiercosa.nombre)

Действительно, все методы класса нуждаются в том, чтобы иметь ссылку на инстанцию. Поскольку ты можешь оценивать, даже я не использую self.

>>> c1 = Clase('Diego')
>>> c1.hola()
¡Hola, Diego!

Это эквивалентное, хотя немного глупый, но покажи форму, в которой методом он назван используя инстанцию класса:

>>> c1 = Clase('Diego')
>>> Clase.hola(c1)
¡Hola, Diego!

Не возможно называть метод без инстанции из-за способа если только ты не используешь @classmethod поскольку мы увидим в Случае 2:

>>> Clase.hola()
Traceback (most recent call last):
  File "clases.py", line 11, in <module>
    Clase.hola()
TypeError: unbound method hola() must be called with Clase instance as first argument (got nothing instead)

Я женю 2: Методы Класса

Класс с @classmethod. Украсив метод с @classmethod то, что ты говоришь Пайтону: "Пайтон, на всякий случай я хочу использовать этот метод, не имея инстанции, так что ты не мстишь мне с глупостями self". И Пайтон ответит тебе: "Ok, но тогда дай мне ссылку на класс". Снова, не необходимо использовать cls:

class Clase:
    @classmethod
    def hola(cualquiertonteria, nombre):
        print('¡Hola, %s!' % nombre)

>>> Clase.hola('Diego')
¡Hola, Diego!

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

class Clase:
    def __init__(cualquiercosa, nombre, rango='Cadete'):
        cualquiercosa.nombre = nombre
        cualquiercosa.rango = rango

    def hola(cualquiercosa):
        print('¡Hola, %s! Eres un %s' % (cualquiercosa.nombre, cualquiercosa.rango))

    @classmethod
    def desde_nombre(cualquiertonteria, nombre):
        return cualquiertonteria(nombre)

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

>>> c1 = Clase.desde_nombre('Diego')
>>> c1.hola()
¡Hola, Diego! Eres un Cadete

Я женю 3: Статические методы

Класс с @staticmethod. Вкратце то, что ты говоришь Пайтону, "Пайтон, я буду создавать метод без инстанции и без класса, так что ты не мстишь мне с глупостями self или cls". И Пайтон ответит тебе: "Ты знаешь, что ты можешь делать это без необходимости класса, нет?". Метод с @staticmethod это не практически ни элегантный способ называть функцию с класса, так как он не получает даже инстанции, ни сам класс.

Лично я это использовал редко, но ко мне приходят случаи, в которых этот метод мог бы быть затруднительно связанным с данными, которыми ты манипулируешь в классе и хочешь поддержать все в том же сайте. А именно, вместо того, чтобы создавать функцию "helper" в другом модуле, так как ты это создаешь в том же классе как какой-то тип утверждения:

class Clase:
    def __init__(cualquiercosa, nombre):
        cualquiercosa.nombre = nombre

    def hola(cualquiercosa):
        print('¡Hola, %s!' % cualquiercosa.nombre)

    @staticmethod
    def mis_padres_estan_locos(nombre):
        estan_locos = False
        if nombre in ('Hitler', 'Kakaroto'):
            estan_locos = True
        return estan_locos

>>> Clase.mis_padres_estan_locos('Hitler')
True
>>> Clase.mis_padres_estan_locos('Diego')
False
>>> Clase.mis_padres_estan_locos('Kakaroto')
True

Это, вкратце, более или менее, как функционируют классы в Пайтоне.

26
ответ дан 24.11.2019, 15:06
  • 1
    Спасибо, очень полный. Он обрабатывал информацию в понимании различия копаясь с int и # 233; rprete и я habr и # 237; в принесенный лента понимать различие между тремя часами, когда синтаксис, от случая к случаю, пойдите и # 233; ntica. – Diego 11.12.2015, 22:01
  • 2
    #161; Забота, class s и # 237; это размещенное слово! – Darkhogg 14.12.2015, 10:53
  • 3
    @Darkhogg просвет, class это, но я убедил ее и # 243; n использованная в м и # 233; все класса cls он это не. – César 14.12.2015, 14:01
  • 4
    @C и # 233; sarBust и # 237; вы Уже, но в твоем ответе он говорит буквально: и #171; self или class не размещенные слова и # 187; что неправильное. – Darkhogg 14.12.2015, 14:04
  • 5
    @Darkhogg верный! Это был typo, я это исправляю. Спасибо! – César 14.12.2015, 14:05

В Пайтоне, методы назначены по умолчанию методы инстанции.

В Пайтоне есть три типа методов:

  • инстанции: они получают инстанцию объекта как первого параметра.
  • класса: они получают класс как первый параметр, эквивалентный явным методам как static в других языках.
  • статические: они ничего не получают добавочный как первый параметр, эквивалентный свободным функциям, которые могли бы быть в той же единице перевода в других языках.
5
ответ дан 24.11.2019, 15:06

Методы класса в Пайтоне назначены по умолчанию методы инстанции, нуждаются в ссылке на объект в вопросе.

Если ты смотришь в Википедиа Методо _ (информатику), отличи между методами инстанции и методов класса или статические, в Пайтоне (в противоположность другим языкам) методы класса и статические - две различные вещи. Это проистекает того, что классы в себе также - объекты.

Метод инстанции, в Пайтоне, нуждается в ясной ссылке на инстанцию, отсюда ошибка takes 2 positional arguments but 3 were given. Синтаксический сахар, - в котором переводчик берется за то, чтобы перемещать ссылку на инстанцию как первый параметр метода, поэтому необходим self в заявлении метода, но он не снабжает ссылками ее в инстанцию во время делания призыва к методу формы: instancia.metodo().

Метод класса - метод инстанции объекта класса, в Пайтоне классы - также объекты. Чтобы показывать переводчику, что вышеупомянутый метод не идет в pertener в инстанции класса а в объект класс в себе, необходим декоратор @classmethod. Как каждый метод инстанции нуждается в ссылке на объект, на котором он работает, в этом случае он используется cls. Так self как cls это произвольные слова, но соглашение состоит в том, чтобы использовать вышеупомянутые слова, в соответствии с философией Дзен Пайтона, который говорит, что единственный дебет, - единственный очевидный способ делать что-то. Они используются обычно как альтернативные "стартапы" в __init__.

В конце концов, статический метод - функция (он не нуждается ни ни в каком объекте ни ссылке на класс, чтобы функционировать), но нуждается декоратор @staticmethod для того, чтобы переводчик это не взял как метод инстанции.


Он оказывается лучше с кодом. Если мы определяем класс Clase и инстанция:

class Clase:
    def __init__(self, arg1, arg2):
        self.arg1 = arg1
        self.arg2 = arg2

    @staticmethod
    def metodo_estatico(arg1, arg2):
        return arg1 + arg2

    def metodo_instancia(self, arg3):
        return self.arg1 + self.arg2 + arg3

    @classmethod
    def metodo_clase(cls, arg1):
        arg2 = 2
        return cls(arg1, arg2)

>>> instancia = Clase(4, 2)

Clase это объект типа type, instancia это объект типа Clase:

>>> Clase
<class '__main__.Clase'>
>>> type(Clase)
<class 'type'>
>>> instancia
<__main__.Clase object at 0x7f1354c17278>
>>> type(instancia)
<class '__main__.Clase'>

metodo_instancia до тех пор, пока он не принадлежит инстанции класса это функция, 'function' (В Пайтоне 2 его было бы одним 'unbound method', не соединенный метод):

>>> Clase.metodo_instancia
<function Clase.metodo_instancia at 0x7f1354bf89d8>

Но однажды принадлежи isntancia тебя перейдите к тому, чтобы быть одним 'bound method', метод, соединенный в вышеупомянутую инстанцию:

>>> instancia.metodo_instancia
<bound method Clase.metodo_instancia of <__main__.Clase object at 0x7f1354c17278>>

Метод класса metodo_clase это метод, соединенный (bound method) в класс:

>>> Clase.metodo_clase
<bound method type.metodo_clase of <class '__main__.Clase'>>
>>> instancia.metodo_clase
<bound method type.metodo_clase of <class '__main__.Clase'>>

В обоих случаях служи как фактория (в нашем осуществлении класса Clase) чтобы создавать новые объекты типа Clase:

>>> Clase.metodo_clase(3)
<__main__.Clase object at 0x7f1354c2bf60>
>>> instancia.metodo_clase(3)
<__main__.Clase object at 0x7f1352bfd828>

В конце концов, metodo_estatico это та же функция, как в классе, так и в инстанции:

>>> Clase.metodo_estatico
<function Clase.metodo_estatico at 0x7f1354bf8950>
>>> instancia.metodo_estatico
<function Clase.metodo_estatico at 0x7f1354bf8950>
6
ответ дан 24.11.2019, 15:06