【问题标题】:Capture unknown magic method calls?捕获未知的魔法方法调用?
【发布时间】:2018-01-27 13:08:53
【问题描述】:

我有一个类,我想为其重写各种方法,例如__str____iter__len。但是,所有这些方法的实现都是相同的。例如,我可能有这样的事情:

def __len__(self):
    return list.__len__(self.do_something())

def __str__(self):
    return str(self.do_something())

def __iter__(self):
    return list.__iter__(self.do_something())

def items(self):
    return (self.do_something()).items()

我的想法是捕获方法或魔术方法,并在执行do_something(在一种包装函数中)后调用它们。有没有办法做到这一点?或者也许有替代解决方案?

【问题讨论】:

  • 看起来你应该继承list,但如果没有更多上下文我无法判断。
  • @Stephen S,我正在制作一个充当远程过程调用存根的对象。它可以是列表、字典或其他对象引用(在服务器端)。 do_something 方法将返回列表,如果它是一个列表。但是,如果它是一个字典,它将返回一个字典。 (原谅我的 __iter__ 示例,它只返回一个 list 方法)
  • @StephenS 如果我要继承 list,我该如何包装所有 list 特定方法?
  • 如果你继承list,它会给你所有的list方法。您在子类中实现的每个方法都将覆盖父方法。无论如何都要调用父方法,use super.
  • @StephenS,我想这在没有子类列表的情况下也可以工作,但我主要关心的是确保覆盖列表和字典中的所有方法。

标签: python


【解决方案1】:

如果你真的想封装所有“神奇”的方法,你可以使用装饰器和元类。

import functools


def magic_decorator(func):
    @functools.wraps(func)
    def func_wrapper(*args, **kwargs):
        ...
        return func(*args, **kwargs)
    return func_wrapper


class WrappedMagicMeta(type):

    def __new__(cls, name, bases, attrs):
        for k, v in attrs.items():
            if k.startswith('__') and k.endswith('__') and callable(v):
                attrs[k] = magic_decorator(v)

        return type.__new__(cls, name, bases, attrs)


class MyCustomObject(metaclass = WrappedMagicMeta):
    pass

您可以在func_wrapper 中实现您需要对MyCustomObject 的魔法方法施加的任何功能。


【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-23
    • 2014-08-07
    • 1970-01-01
    • 2012-08-27
    • 2014-02-04
    相关资源
    最近更新 更多