我正在尝试定义一个标记某些方法的装饰器,然后提供通过方法调用所有标记方法的功能。
以下内容应该让我知道我喜欢一切行为,但由于显而易见的原因而无法正常运作
def mark(method):
# mark_methods should belong to the class wherein methods are being marked
mark_methods.append(method)
return method
class BaseClass():
# This should belong to each subclasses independently
marked_methods = []
def bundle(self):
data = {}
for marked_method in Person.marked_methods:
data[marked_method.__name___] = marked_method()
return data
class Person(BaseClass):
@mark
def name(self):
return 'Fred'
def say_hi(self):
return 'Hi'
class Dog(BaseClass):
@mark
def name(self):
return 'Fido'
@mark
def fur_color(self):
return 'Black'
def bark(self):
return 'Woof'
Person.marked_methods # => [name]
Person().bundle() # => {'name': 'Fred'}
Dog.marked_methods # => [name, fur_color]
Dog().bundle() # => {'name': 'Fido', 'fur_color': 'Black'}
理想情况下,此行为将包含在可由其他类继承的类中。
这是我正在寻找的一个版本,它表现出类似的行为而不使用装饰器。相反,它依赖于操纵以特定前缀mark_whatever
开头的函数:
MARK_PREFIX = 'mark_'
class TrackingWithoutDecoratorClass():
@classmethod
def __init_subclass__(cls, **kwargs):
"""Tracks all methods added on init
"""
# Mapping of transformer names to transformer functions
cls.marked = {}
for name, func in vars(cls).items():
# Add all functions starting with the `MARK_PREFIX` to the
# marked registry
if name.startswith(MARK_PREFIX):
registry_name = name.replace(MARK_PREFIX, '')
cls.marked[registry_name] = func
class Example(TrackingWithoutDecoratorClass):
def mark_one(self):
return 1
def mark_two(self):
return 2
def not_marked_three(self):
return 3
print(Example.marked.keys())
答案 0 :(得分:1)
我建议自己标记方法:
import inspect
def mark(func):
func.marked = True
return func
class Base():
@classmethod
def marked_methods(cls):
return [n for n, f in inspect.getmembers(cls) if hasattr(f, 'marked')]
def bundle(self):
return {m: getattr(self, m)() for m in self.marked_methods()}
class Person(Base):
@mark
def name(self):
return 'Fred'
def say(self):
return 'Hi'
class Dog(Base):
@mark
def name(self):
return 'Fido'
def bark(self):
return 'Woof'
@mark
def color(self):
return 'Black'
print(Person.marked_methods()) #=> ['name']
print(Person().bundle()) #=> {'name': 'Fred'}
print(Dog.marked_methods()) #=> ['color', 'name']
print(Dog().bundle()) #=> {'color': 'Black', 'name': 'Fido'}
答案 1 :(得分:0)
诀窍是,一旦目标类从基类继承,就使用元类来存储修饰的方法:
def mark(method):
method.marked = True
return method
class MarkTracking(type):
def __new__(cls, name, bases, attr):
marked = []
for obj in attr.values():
if hasattr(obj, 'marked'):
marked.append(obj)
attr['marked_methods'] = marked
return type.__new__(cls, name, bases, attr)
class BaseClass(metaclass=MarkTracking):
def bundle(self):
data = {}
for marked_method in self.__class__.marked_methods:
data[marked_method.__name__] = marked_method(self)
return data
class Person(BaseClass):
@mark
def name(self):
return 'Fred'
def say_hi(self):
return 'Hi'
class Dog(BaseClass):
@mark
def name(self):
return 'Fido'
@mark
def fur_color(self):
return 'Black'
def bark(self):
return 'Woof'
print(Person.marked_methods) # => [name]
print(Person().bundle()) # => {'name': 'Fred'}
print(Dog.marked_methods) # => [name, fur_color]
print(Dog().bundle()) # => {'name': 'Fido', 'fur_color': 'Black'}