В Python 3 ваш код будет работать, но в Python 2 есть некоторая упаковка, что происходит, когда методы ищутся.
Класс против Instance
уровня Класса: хранение 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
уровень Instance
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
Если 'counter' быть уровень класса (все экземпляры разделяют текущее значение счетчика) или уровня экземпляра (каждый экземпляр будет начинаться с 1)? –
'counter' должен быть экземпляром уровня – sbell
Этот связанный с этим вопрос может (или может быть) быть полезным: http://stackoverflow.com/questions/7034063/adding-attributes-the-instancemethods-in-python –