В Python 3 ваш код будет работать, но в Python 2 есть некоторая упаковка, которая имеет место при поиске методов.
Класс против экземпляра
уровень класса: сохранение counter
с функцией (либо напрямую, либо с использованием изменяемого значения по умолчанию) эффективно делает его атрибутом уровня класса какесть только одна функция, независимо от того, сколько у вас экземпляров (все они используют один и тот же объект функции).
уровень экземпляра: сделать counter
атрибут уровня экземпляраВы должны создать функцию в __init__
, затем обернуть ее functools.partial
(чтобы она работала как обычный метод), а затем сохранить ее в экземпляре - теперь у вас есть один объект функции для каждого экземпляра.
Уровень класса
Общепринятой практикой для статоподобной переменной является использование изменяемого аргумента по умолчанию:
class foo(object):
...
def bar(self, _counter=[0]):
_counter[0] += 1
return _counter[0]
Если вы хотите, чтобы он был красивееВы можете определить свой собственный изменяемый контейнер:
class MutableDefault(object):
def __init__(self, start=0):
self.value = start
def __iadd__(self, other):
self.value += other
return self
def value(self):
return self.value
и изменить свой код следующим образом:
class foo(object):
def bar(self, _counter=MutableDefault()):
_counter += 1
return _counter.value
Уровень экземпляра
from functools import partial
class foo(object):
def __init__(self):
def bar(self, _counter=MutableDefault(1)): # create new 'bar' each time
value = _counter.value
_counter += 1
return value
self.bar = partial(bar, self)
Сводка
Как видите, удобочитаемость серьезно пострадала, когдапереход на уровень экземпляра для counter
.Я настоятельно рекомендую вам переоценить важность подчеркивания того, что counter
является частью bar
, и, если это действительно важно, возможно, сделайте bar
своим собственным классом, экземпляры которого станут частью экземпляров foo
.Если это не очень важно, сделайте это обычным способом:
class foo(object):
def __init__(self):
self.bar_counter = 0
def bar(self):
self.bar_counter += 1
return self.bar_counter