Я хотел бы сделать что-то вроде этого:
class SillyWalk(object):
@staticmethod
def is_silly_enough(walk):
return (False, "It's never silly enough")
def walk(self, appraisal_method=is_silly_enough):
self.do_stuff()
(was_good_enough, reason) = appraisal_method(self)
if not was_good_enough:
self.execute_self_modifying_code(reason)
return appraisal_method
def do_stuff(self):
pass
def execute_self_modifying_code(self, problem):
from __future__ import deepjuju
deepjuju.kiss_booboo_better(self, problem)
с идеей, что кто-то может сделать
>>> silly_walk = SillyWalk()
>>> appraise = walk()
>>> is_good_walk = appraise(silly_walk)
, а также получить некоторое волшебное машинное обучение;этот последний бит не представляет особого интереса для меня, это было только первое, что пришло мне на ум в качестве примера использования статического метода как в функциональном контексте, так и с точки зрения вызывающего.
В любом случае, это не работает, потому что is_silly_enough
на самом деле не является функцией: это объект, чей метод __get__
вернет исходную функцию is_silly_enough
.Это означает, что он работает только «нормальным» образом, когда на него ссылаются как на атрибут объекта.Рассматриваемый объект создается функцией staticmethod()
, которую декоратор помещает между атрибутом SillyWalk
is_silly_enough
и функцией, которая изначально определена с этим именем.
Это означает, что для использованиязначение по умолчанию appraisal_method
из либо SillyWalk.walk
или вызывающего абонента, мы должны либо
- вызвать
appraisal_method.__get__(instance, owner)(...)
, чем просто вызватьappraisal_method(...)
- или назначьте его в качестве атрибута какого-либо объекта, затем обратитесь к этому свойству объекта как к методу, который мы вызываем, как мы бы назвали
appraisal_method
.
Учитывая, что ниЭти решения кажутся особенно Pythonic ™, мне интересно, возможно, есть лучший способ получить такую функциональность.По сути, я хочу, чтобы был способ указать, что метод должен по умолчанию использовать определенный класс или статический метод, определенный в области действия того же класса, для выполнения некоторой части его повседневной рутины.
Я бы предпочел не использовать None
, потому что я бы хотел, чтобы None
передавал сообщение о том, что эта конкретная функция не должна вызываться.Я думаю, что я мог бы использовать какое-то другое значение, например False
или NotImplemented
, но это выглядит так: а) хакерство б) раздражение от необходимости писать лишнюю пару строк кода, а также избыточную документацию для чего-то, чтоПохоже, это можно выразить довольно кратко в качестве параметра по умолчанию.
Какой лучший способ сделать это?