Я нахожу, что это полезный для создания "фабрики метода функционирует", которые переносят параметрический атрибут объекта в некоторую логику.
Например:
"""Fishing for answers.
>>> one().number_fisher()
'one fish'
>>> one().colour_fisher()
'red fish'
>>> two().number_fisher()
'two fish'
>>> two().colour_fisher()
'blue fish'
"""
class one(object):
def number(self):
return 'one'
def colour(self):
return 'red'
def _make_fisher(sea):
def fisher(self):
return '{0} fish'.format(getattr(self, sea)())
return fisher
number_fisher = _make_fisher('number')
colour_fisher = _make_fisher('colour')
class two(one):
def number(self):
return 'two'
def colour(self):
return 'blue'
Действительно ли необходимо передать атрибут make_fisher
как строка, или существует ли лучший способ сделать это?
Если я буду передавать и использовать фактический атрибут, то это повредит полиморфизм, начиная с экземпляров two
будет все еще использовать ту же самую ссылку на объект атрибута.
Т.Е.
diff --git a/fishery.py b/fishery.py
index 840e85d..b98cf72 100644
--- a/fishery.py
+++ b/fishery.py
@@ -4,10 +4,12 @@
'one fish'
>>> one().colour_fisher()
'red fish'
+
+This version does not implement polymorphism, and so this happens:
>>> two().number_fisher()
-'two fish'
+'one fish'
>>> two().colour_fisher()
-'blue fish'
+'red fish'
"""
@@ -18,10 +20,10 @@ class one(object):
return 'red'
def _make_fisher(sea):
def fisher(self):
- return '{0} fish'.format(getattr(self, sea)())
+ return '{0} fish'.format(sea(self))
return fisher
- number_fisher = _make_fisher('number')
- colour_fisher = _make_fisher('colour')
+ number_fisher = _make_fisher(number)
+ colour_fisher = _make_fisher(colour)
class two(one):
def number(self):
Это кажется немного слабым для использования строки для ссылки на атрибут, но я не вижу другой способ сделать это. Есть ли?
«Еще один уровень косвенности» (иногда предлагается как волшебная панацея программирования ;-) - как и для типичных декораторов, таких как свойство
. Например: [
def makefisher(fun):
def fisher(self):
return '{0} fish'.format(fun(self))
return fisher
class one(object):
def number(self): return self._number()
def _number(self): return 'one'
number_fisher = makefisher(number)
class two(one):
def _number(self): return 'two'
] По сути, функция, которую вы оборачиваете, является «организующей функцией» в необычно простом варианте шаблонного метода DP, а та, которую вы переопределяете, является «функцией перехвата» в том же DP. Или, по крайней мере, это один способ взглянуть на это, а другой - «дополнительный уровень косвенности», с которого я начал ;-).