2015-09-18 2 views
3

Рассмотрим следующий пример:Как Python знает переменную экземпляра без определения __init__?

class X: 
    def run(self): 
     print("An example.") 

X().run() 

Выход есть:

> An example. 

Но когда мы опускаем ссылку на экземпляр:

class X: 
    def run(): 
     print("An example.") 

X().run() 

The output is: 

TypeError: run() takes 0 positional arguments but 1 was given

Когда мы создаем класс, __ new __ вызывается и экземпляр создается, нормально. Но как это требует экземпляра без определения __ init __? (Я удивлен, потому что я всегда написал __ init __, думая, что он отвечал за определение соглашения/само имя для ссылки на переменную). Я смущен.

+0

хорошо, 'X(). Запуска()' 'вызывает запуск (object_ref)', где 'object_ref' ваш старый' self' – Pynchia

+0

в случае 'self' не нужен, вы можете украсить метод с' @ staticmethod'. Посмотрите, как [this SO QA] (http://stackoverflow.com/questions/136097/what-is-the-difference-between-staticmethod-and-classmethod-in-python) помогает пролить свет на предмет статичности и class – Pynchia

+0

Я бы рекомендовал начать использовать классы нового стиля. Пожалуйста, прочитайте [this SO QA] (http://stackoverflow.com/questions/54867/what-is-the-difference-between-old-style-and-new-style-classes-in-python) по теме – Pynchia

ответ

2

При вызове instance.run() если неявно вызывает run(instance) поэтому вы получаете сообщение об ошибке:

TypeError: run() takes 0 positional arguments but 1 was given

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

Во-вторых, вы используете старый способ объявления класса - class X:
Новый способ является class X(object): но независимо от того, если вы используете новый/старый аннотацию, вызов X() возвращает экземпляр класс, даже если вы не определили __init__.

И третье, если вы хотите, чтобы сделать его метод класса, вы можете сделать то, что Pynchia предложил в комментарии выше (аннотирования метод с @staticmethod) или объявить метод как метод класса, указав, что первый аргумент cls и аннотирования его как класс-метода:

class X: 

    @classmethod 
    def run(cls): 
     print "a" 


X.run() # prints a 

1. в соответствии с комментарием Марка ниже, в Python 3 мы возвращаемся к «старому» из объявления класса. Полезно знать - спасибо Марк!

+1

Чтобы объявить метод как метод класса, используйте декоратор '@ classmethod', используя только имя' cls', ничего не меняет. – bereal

+0

@bereal мой плохой - спасибо за исправление. – alfasin

+2

'class X (object):' является * старым * новым способом объявления класса! Для Python 3 класс X: 'отлично. –

Смежные вопросы