【问题标题】:How to intercept a method call which doesn't exist?如何拦截不存在的方法调用?
【发布时间】:2012-06-08 10:30:18
【问题描述】:

我想创建一个在调用任何可能存在或不存在的方法时不提供Attribute Error 的类:

我的班级:

class magic_class:
    ...
    # How to over-ride method calls
    ...

预期输出:

ob = magic_class()
ob.unknown_method()
# Prints 'unknown_method' was called

ob.unknown_method2()
# Prints 'unknown_method2' was called

现在,unknown_methodunknown_method2 在类中实际上并不存在,但是我们如何在 python 中拦截方法调用呢?

【问题讨论】:

  • 旁注仅供参考:PEP8 说它应该命名为 class MagicClass: 并且新样式至少应该继承对象:class MagicClass(object):

标签: python


【解决方案1】:

覆盖__getattr__()魔术方法:

class MagicClass(object):
    def __getattr__(self, name):
        def wrapper(*args, **kwargs):
            print "'%s' was called" % name
        return wrapper

ob = MagicClass()
ob.unknown_method()
ob.unknown_method2()

打印

'unknown_method' was called
'unknown_method2' was called

【讨论】:

  • 如何处理这样的方法调用:ob.calc(1000, 2000)。意味着您如何保留调用的参数?
  • @YugalJindle:添加了*args, **kwargs 以接受包装器中的任意参数。
【解决方案2】:

以防万一有人试图将未知方法委托给对象,代码如下:

class MagicClass():
    def __init__(self, obj):
        self.an_obj = obj

    def __getattr__(self, method_name):
        def method(*args, **kwargs):
            print("Handling unknown method: '{}'".format(method_name))
            if kwargs:
                print("It had the following key word arguments: " + str(kwargs))
            if args:
                print("It had the following positional arguments: " + str(args))
            return getattr(self.an_obj, method_name)(*args, **kwargs)
        return method

这在您需要应用Proxy pattern 时非常有用。

此外,考虑到 args 和 kwargs,您可以生成一个完全用户友好的界面,因为使用 MagicClass 的人将其视为真实对象。

【讨论】:

  • 这里的self.optimizer 是什么?
  • 抱歉,打错了。应该是self.an_obj - “优化器”是我在自己的程序中包装的对象的名称。我编辑了代码:)
【解决方案3】:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-16
    • 2014-10-11
    • 1970-01-01
    • 2011-06-11
    • 2010-11-11
    相关资源
    最近更新 更多