2009-03-28 3 views
26

Ex.Является ли плохая форма вызовом classmethod как метод из экземпляра?

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

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

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

c = C() 

c.f(2) 
4 

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

C.f() 

или

c.__class__.f() 

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

?

+1

OT, но предпочитают тип (с) с .__ class__ – Miles

ответ

25

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

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

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

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

c = C() 
c.f(2) 

и

C.f(2) 
+0

Да, но что, если вам действительно нужен метод класса? – frnhr

4

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

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

2

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

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

+4

Имя класса (в этом случае «C») может измениться, хотя ... –

3

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

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

+4

Для данного примера кода вам не нужен classmethod-on-instance, но если вы начали подкласс C, вы могли бы. – bobince

9

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