Рассмотрим этот пример шаблона стратегии в Python (адаптированный из примера здесь). В этом случае альтернативная стратегия является функцией.
class StrategyExample(object):
def __init__(self, strategy=None) :
if strategy:
self.execute = strategy
def execute(*args):
# I know that the first argument for a method
# must be 'self'. This is just for the sake of
# demonstration
print locals()
#alternate strategy is a function
def alt_strategy(*args):
print locals()
Ниже приведены результаты для стратегии по умолчанию.
>>> s0 = StrategyExample()
>>> print s0
<__main__.StrategyExample object at 0x100460d90>
>>> s0.execute()
{'args': (<__main__.StrategyExample object at 0x100460d90>,)}
В приведенном выше примере s0.execute
- это метод (не простая ванильная функция), и, следовательно, первый аргумент в args
, как и ожидалось, равен self
.
Ниже приведены результаты для альтернативной стратегии.
>>> s1 = StrategyExample(alt_strategy)
>>> s1.execute()
{'args': ()}
В этом случае s1.execute
является простой ванильной функцией и, как и ожидалось, не получает self
. Следовательно, args
пусто. Подожди минуту! Как это произошло?
И метод, и функция вызывались таким же образом. Как метод автоматически получает self
в качестве первого аргумента? И когда метод заменяется простой ванильной функцией, как он не получает self
в качестве первого аргумента?
Единственное различие, которое я смог найти, - это когда я изучил атрибуты стратегии по умолчанию и альтернативной стратегии.
>>> print dir(s0.execute)
['__cmp__', '__func__', '__self__', ...]
>>> print dir(s1.execute)
# does not have __self__ attribute
Есть ли атрибут __self__
в s0.execute
(метод), но его отсутствие на s1.execute
(функция) каким-то образом объясняет эту разницу в поведении? Как все это работает внутри?