Это плохая форма вызова метода класса в качестве метода из экземпляра? - PullRequest
35 голосов
/ 28 марта 2009

Ex.

Если у меня есть что-то вроде этого:

class C(object):
    @classmethod
    def f(cls, x):
       return x + x

Это будет работать:

c = C()

c.f(2)
4

Но разве это плохо? Должен ли я звонить только

C.f()

или

c.__class__.f()

Очевидно, что это имеет смысл только в тех случаях, когда f не взаимодействует с self / cls, ожидая, что он будет классом.

Ответы [ 6 ]

31 голосов
/ 28 марта 2009

Если вы испытываете желание вызвать метод класса из экземпляра, вам, вероятно, не нужен метод класса.

В приведенном вами примере статический метод будет более уместным именно из-за вашего последнего замечания (без взаимодействия self / cls).

class C(object):
    @staticmethod
    def f(x):
       return x + x

таким образом, это "хорошая форма", чтобы сделать оба

c = C()
c.f(2)

и

C.f(2)
10 голосов
/ 28 марта 2009

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

5 голосов
/ 28 марта 2009

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

Есть ли причина, по которой это не просто статический метод?

3 голосов
/ 28 марта 2009

Если у вас уже есть экземпляр C, зачем вам f (), чтобы быть методом класса? Мало того, что это плохая форма, это обычно не нужно. Кто-то в сети говорит: «Это плохо, потому что создается впечатление, что в объекте используются переменные экземпляра, но это не так».

Хотя, на странице 484 learning python отмечается, что вы можете вызывать метод в любом случае, и он будет точно таким же, пока вы передаете тот же экземпляр в.

3 голосов
/ 28 марта 2009

C.f() яснее, чем c_instance.f(), а c_instance.__class__.f() просто безобразно. Поскольку ясность и красота - любимые черты сообщества питонов, я бы сказал, что C.f () - лучший маршрут.

Есть ли какая-то особая причина, по которой вы хотите назвать это каким-либо другим способом?

0 голосов
/ 11 октября 2018

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

class A:
  def a(self, number):
    print("a", self, number)
    self.b(number)

  @classmethod
  def b(cls, number):
    print("b", cls, number + 1)
    cls.c(number)

  @classmethod
  def c(cls, number):
    print("c", cls, number * 2)



b = A()
b.a(3) 

Приведенный выше код дает следующий результат:

a <__main__.A object at 0x000001FAC09FE358> 3
b <class '__main__.A'> 4
c <class '__main__.A'> 6

Я не говорю, что это лучшее соглашение, но оно ничего не нарушает в Python 3.6

...