2014-01-22 2 views
2

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

This question показывает, как объявить такие «статические переменные» (терминология C++) внутри функций. Я попытался сделать то же самое в методе экземпляра и потерпел неудачу.

Вот рабочий минимальный пример, который воспроизводит проблему. Вы можете скопировать его в интерпретатор.

class SomeClass(object): 
    def some_method(self): 
     if not hasattr(SomeClass.some_method, 'some_static_var'): 
      SomeClass.some_method.some_static_var = 1 # breaks here 

     for i in range(3): 
      print SomeClass.some_method.some_static_var 
      SomeClass.some_method.some_static_var += 1 

if __name__ == '__main__': 
    some_instance = SomeClass() 
    some_instance.some_method() 

На линии с надписью "# перерывами здесь", я получаю:

AttributeError: 'instancemethod' object has no attribute 'some_static_var'

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

+0

насчет 'SomeClass. some_method.im_func.some_static_var = 1' (Предполагая python2) –

ответ

1

В python 2 вам нужно иметь дело с связанными и несвязанными методами. Они не имеют атрибут __dict__, как функции делают:

#python 2 
'__dict__' in dir(SomeClass.some_method) 
Out[9]: False 

def stuff(): 
    pass 

'__dict__' in dir(stuff) 
Out[11]: True 

В Python 3, ваш код работает отлично! Понятие связанных/несвязанных методов исчезло, все - функция.

#python 3 
'__dict__' in dir(SomeClass.some_method) 
Out[2]: True 

Назад, чтобы сделать ваш код работать, вам нужно поставить атрибут на вещь, которая имеет __dict__: фактическую функцию:

if not hasattr(SomeClass.some_method.__func__, 'some_static_var'): 
    #etc 

Read more on im_func and __func__ here

Это до вас решите, делает ли это ваш код более или менее читабельным - для меня, чтобы эти типы атрибутов класса предметов были почти всегда в пути; не имеет значения, что к указанному атрибуту обращается только один метод, именно там я ищу «статические» типы vars. Я оцениваю читаемый код поверх чистых пространств имен.

Этот последний пункт был, конечно, редакционный, каждый имеет право на свое мнение :-)

1

Вы не можете установить атрибут объектов метода.

Создание классов вместо этого (то есть SomeClass.some_var = 1) является стандартным способом Python. Однако мы можем предложить более подходящие исправления, если вы дадите нам обзор на высоком уровне вашей фактической проблемы (для чего вы пишете этот код?).

+0

Он мог бы поместить атрибут на фактическую функцию, а не на обернутый объект метода. –

-1

Используйте global ключевое слово, чтобы получить доступ к переменным файловом уровне

my_static = None 

class MyClass(object): 
    def some_method(self): 
     global my_static 
     if my_static is None: 
      my_static = 0 
     else: 
      my_static = my_static + 1 
     print my_static 

if __name__ == '__main__': 
    instance = MyClass() 
    instance.some_method() 
    instance.some_method() 

Выходы:

0 
1 

Хотя, как уже упоминалось в другом месте, переменная класса была бы предпочтительнее

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