【问题标题】:Is it possible to extend from function type? (Python 2.7)是否可以从函数类型扩展? (Python 2.7)
【发布时间】:2015-09-18 16:18:29
【问题描述】:

作为我自己的练习,我正在尝试用 Python 编写一个与 C# 中的事件类似的类。

下面是类中的两个主要函数(__subs 是一个列表):

class Event (object):
    def __iadd__ (self, other):
        if not callable(other):
            raise ValueError("%s must be callable" % other)
        self.__subs.append(other)
        return self

    def __add__ (self, other):
        if not callable(other):
            raise ValueError("%s must be callable" % other)
        new = Event()
        new.__subs = [f for f in self.__subs]
        new.__subs.append(other)
        return new

    def __call__ (self, *args, **kwargs):
        for func in self.__subs:
            func(*args, **kwargs)

这允许以下语法:

e1 = Event()
e1 += afunction
e2 += another
e1 (arg1, arg = val) # afunction and another will be called with arg1 and val

e2 = Event() + afunction + another
e2 (arg1, arg = val)

(Event() + afunction + another) (arg1, arg = val)

但是,我想将最后两个简化成这样

e = afunction + another
e (arg1, arg = val)

(afunction + another) (arg1, arg = val)

我尝试这样做,但我收到错误“TypeError: 'function' is not an accepted base type”

class function (FunctionType):
    def __add__ (self, other):
        return Event() + self + other

我正在尝试做的事情可能吗?

【问题讨论】:

    标签: python function python-2.7 operator-overloading


    【解决方案1】:

    你不能直接子类化函数,不。最多可以创建一个包装类,将所有属性访问传递给底层函数。

    为了支持调用,给包装类一个object.__call__ method

    class FunctionWrapper(object):
        def __init__(self, func):
            self._func = func
    
        def __getattr__(self, attr):
            return getattr(self._func, attr)
    
        def __call__(self, *args, **kwargs):
            return self._func(*args, **kwargs)
    
        # additional methods
    

    您甚至可以使用装饰器语法将其“绘制”到函数声明上:

    @FunctionWrapper
    def foo(): pass
    

    演示:

    >>> @FunctionWrapper
    ... def foo():
    ...     return 'bar'
    ... 
    >>> foo
    <__main__.FunctionWrapper object at 0x102544850>
    >>> foo()
    'bar'
    >>> foo.__name__
    'foo'
    >>> foo.__code__
    <code object foo at 0x1026cb730, file "<stdin>", line 1>
    

    【讨论】:

    • 那么@FunctionWrapper在定义之后基本上是foo = FunctionWrapper(foo)
    • @TangibleLight:没错,合二为一。请参阅original proposal
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-11
    • 2022-06-10
    • 1970-01-01
    • 2020-03-02
    • 1970-01-01
    • 2013-05-21
    • 1970-01-01
    相关资源
    最近更新 更多