2016-04-22 3 views
3

В питона, staticmethod s являются «только функции», и я могу сослаться на них двумя различными способами:Python classmethods: какая разница между членом экземпляра и членом класса?

>>> class A: 
...  @staticmethod 
...  def f(): 
...   pass 
... 
>>> a=A() 
>>> A.f 
<function A.f at 0x7f20f8cd3f28> 
>>> a.f 
<function A.f at 0x7f20f8cd3f28> 
>>> a.f is A.f 
True 

Оба a.f и A.f имена, которые ссылаются на тот же объект, который бывает «просто функция". Отлично.

Теперь, скажем, у меня есть classmethod:

>>> class B: 
...  @classmethod 
...  def f(cls): 
...   pass 
... 
>>> b=B() 
>>> b.f is B.f 
False 

Я знаю, что b.f и B.f являются не функции: они связаны mothods. Это означает, что аргумент cls неявный и всегда равен B. Из-за этого я бы понял, что если B2 является подклассом B, B2().f is B().f будет ложным, поскольку они связаны методами с различными аргументами cls. Но я не понимаю, почему B().f is B.f дает False. Разве они не должны быть одним и тем же объектом, как и A().f и A.f?

EDIT: Этот вопрос не совпадает с «What is the difference between @staticmethod and @classmethod in Python?». Я знаю разницу между staticmethod и classmethod. Я хочу знать одну конкретную вещь, которая не рассматривается в связанном «зонтичном» вопросе.

+0

Класс как определение. «Экземпляр» является фактическим использованием этого определения. Таким образом, «класс» - это рецепт, а «экземпляр» - это торт. Поскольку рецепт - это не торт, а только инструкции о том, как сделать торт, они не совпадают. – DuckPuncher

+0

@ DuckPuncher ты прочитал тело моего вопроса? Я хочу знать, почему 'B(). F является B.f' является ложным и' A(). F является A.f' является истинным. – fonini

+1

См. Также «Пользовательские методы» здесь: https://docs.python.org/2/reference/datamodel.html#types –

ответ

4

B().f10 и B.f - это разные объекты, поскольку Python создает новый объект связанного метода каждый раз, когда вы ссылаетесь на нестатический метод через доступ к атрибуту.

Например, B.f is B.f также является False.

>>> B.f is B.f 
False 

Кроме того, вы получите новый объект метод, даже если экземпляр остается прежним:

>>> b = B() 
>>> b.f is b.f 
False 

@staticmethod создает новый статический объект метод, но

Когда статический метод объект извлекается из класса или класса экземпляра, фактически возвращенный объект является обернутым объектом, который равен , не подлежащий дальнейшему преобразованию на.

(от Data model)

В этом случае A.f всегда возвращает один и тот же объект f функцию.

+1

FWIW, 'b = B(); b.f также является b.f'. –