Какова цель методов класса? - PullRequest
238 голосов
/ 01 сентября 2008

Я учу себя Python, и мой последний урок состоял в том, что Python - это не Java , и поэтому я просто потратил некоторое время, превращая все свои методы Class в функции.

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

У кого-нибудь есть хороший пример использования метода Class в Python или, по крайней мере, кто-нибудь может сказать мне, когда методы Class могут быть разумно использованы?

Ответы [ 15 ]

4 голосов
/ 17 августа 2010

Методы класса обеспечивают «семантический сахар» (не знаю, широко ли используется этот термин) или «семантическое удобство».

Пример: вы получили набор классов, представляющих объекты. Возможно, вы захотите иметь метод класса all() или find() для записи User.all() или User.find(firstname='Guido'). Конечно, это можно сделать с помощью функций уровня модуля ...

3 голосов
/ 24 марта 2017

Что меня поразило, так это то, что так называемый метод class и так называемый метод instance - это просто функция с семантическим значением, примененным к ее параметр, который передается без вывода сообщений, когда функция вызывается как метод объекта (т.е. obj.meth()).

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

Поскольку это просто функция , ее можно объявить только один раз в любой заданной области (т. Е. class определение). Следовательно, если в качестве сюрприза для Rubyist следует, что вы не можете иметь метод класса и метод экземпляра с одинаковым именем .

Учтите это:

class Foo():
  def foo(x):
    print(x)

Вы можете позвонить foo в случае

Foo().foo()
<__main__.Foo instance at 0x7f4dd3e3bc20>

но не по классу:

Foo.foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unbound method foo() must be called with Foo instance as first argument (got nothing instead)

Теперь добавьте @classmethod:

class Foo():
  @classmethod
  def foo(x):
    print(x)

Вызов экземпляра теперь передает его класс:

Foo().foo()
__main__.Foo

как и при вызове в класс:

Foo.foo()
__main__.Foo

Это единственное соглашение, согласно которому мы используем self для этого первого аргумента в методе экземпляра и cls в методе класса. Я не использовал ни того, ни другого, чтобы проиллюстрировать, что это просто аргумент. В Ruby self - это ключевое слово .

Контрастность с Ruby:

class Foo
  def foo()
    puts "instance method #{self}"
  end
  def self.foo()
    puts "class method #{self}"
  end
end

Foo.foo()
class method Foo

Foo.new.foo()
instance method #<Foo:0x000000020fe018>

Метод класса Python - это просто оформленная функция , и вы можете использовать те же приемы для создания собственных декораторов . Декорированный метод оборачивает реальный метод (в случае @classmethod он передает дополнительный аргумент класса). Базовый метод все еще там, скрытый , но все еще доступный .


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

2 голосов
/ 14 октября 2014

Я задавал себе один и тот же вопрос несколько раз. И хотя ребята изо всех сил пытались это объяснить, ИМХО лучший (и самый простой) ответ, который я нашел, это описание метода Class в документации Python.

Существует также ссылка на статический метод. И в случае, если кто-то уже знает методы экземпляра (что я предполагаю), этот ответ может быть последней частью, чтобы собрать все вместе ...

Более подробную информацию по этой теме можно найти также в документации: Стандартная иерархия типов (прокрутите вниз до Методы экземпляров раздел)

2 голосов
/ 07 сентября 2012

Это интересная тема. Я предполагаю, что метод класса Python работает как синглтон, а не как фабрика (которая возвращает произведенный экземпляр класса). Причина, по которой это единственный элемент, заключается в том, что существует общий объект, который создается (словарь), но только один раз для класса, но используется всеми экземплярами.

Для иллюстрации приведу пример. Обратите внимание, что все экземпляры имеют ссылку на один словарь. Это не Фабричный образец, как я понимаю. Это, вероятно, очень уникально для Python.

class M():
 @classmethod
 def m(cls, arg):
     print "arg was",  getattr(cls, "arg" , None),
     cls.arg = arg
     print "arg is" , cls.arg

 M.m(1)   # prints arg was None arg is 1
 M.m(2)   # prints arg was 1 arg is 2
 m1 = M()
 m2 = M() 
 m1.m(3)  # prints arg was 2 arg is 3  
 m2.m(4)  # prints arg was 3 arg is 4 << this breaks the factory pattern theory.
 M.m(5)   # prints arg was 4 arg is 5
0 голосов
/ 08 сентября 2016

Класс, конечно, определяет набор экземпляров. И методы класса работают на отдельных экземплярах. Методы класса (и переменные) - это место, где можно повесить другую информацию, связанную с множеством экземпляров, над всеми.

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

Вы также можете использовать методы класса, чтобы определить инструменты для работы со всем набором. Например, Student.all_of_em () может вернуть всех известных студентов. Очевидно, что если ваш набор экземпляров имеет больше структуры, чем просто набор, вы можете предоставить методы класса, чтобы узнать об этой структуре. Students.all_of_em (класс = 'юниоры')

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

...