如何使用与另一个函数相同的签名动态创建函数?

时间:2010-08-13 17:48:15

标签: python

我正忙于创建一个元类,用一个具有正确实现的新类替换类上的存根函数。原始功能可以使用任何签名。我的问题是我无法弄清楚如何使用与旧签名相同的签名创建新功能。我该怎么做?

更新

这与“我如何使用与另一个函数具有相同签名的动态创建函数?”的实际问题无关,但我添加此内容以说明为什么我可以'使用子类。

我正在尝试在Python中实现类似Scala Case Classes的内容。 (不是模式匹配方面只是自动生成的属性,eq,hash和str方法。)

我想要这样的事情:

>>> class MyCaseClass():
...     __metaclass__ = CaseMetaClass
...     def __init__(self, a, b):
...         pass

>>> instance = MyCaseClass(1, 'x')
>>> instance.a
1
>>> instance.b
'x'
>>> str(instance)
MyCaseClass(1, 'x')

据我所见,没有办法用子类。

3 个答案:

答案 0 :(得分:3)

我相信functools.wraps不会重现原始呼叫签名。但是,Michele Simionato的decorator module确实:

import decorator

class FooType(type):
    def __init__(cls,name,bases,clsdict):
        @decorator.decorator        
        def modify_stub(func, *args,**kw):
            return func(*args,**kw)+' + new'
        setattr(cls,'stub',modify_stub(clsdict['stub']))
class Foo(object):
    __metaclass__=FooType
    def stub(self,a,b,c):
        return 'original'


foo=Foo()
help(foo.stub)
# Help on method stub in module __main__:

# stub(self, a, b, c) method of __main__.Foo instance

print(foo.stub(1,2,3))
# original + new

答案 1 :(得分:0)

可能使用inspect.getargspecs执行此操作。甚至还有一个PEP in place可以让它变得更容易。

但是 - 这不是一件好事。你能想象一下,在运行时动态创建你的函数会有多少调试/维护噩梦 - 不仅仅是这样,而是由元类完成的?我不明白你为什么要动态替换存根;你想改变这个功能,你不能只改变代码吗?我的意思是,假设你有一个班级

class Spam( object ):
    def ham( self, a, b ):
        return NotImplemented

由于您不知道它的意图,因此元类实际上无法实现任何功能。如果您知道ham的意图,可以在ham或其中一个父类中执行此操作,而不是返回NotImplemented

答案 2 :(得分:0)

使用functools.wraps

>>> from functools import wraps
>>> def f(a,b):
    return a+b
>>> @wraps(f)
def f2(*args):
    print(args)
    return f(*args)
>>> f2(2,5)
(2, 5)
7