开发者

How do I dynamically create a function with the same signature as another function?

I'm busy creating a metaclass that replaces a stub function on a class with a new one with a proper implementation. The original function could use any signature. My problem is that I can't figure out how to create a new function with the same signature as the old one. How would I do this?

Update

This has nothing to do with the actual question which is "How do I dynamically create a function with the same signature as another function?" but I'm adding this to show why I can't use subclasses.

I'm trying to implement something like Scala Case Classes in Python. (Not the pattern matching 开发者_高级运维aspect just the automatically generated properties, eq, hash and str methods.)

I want something like this:

>>> 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')

As far as I can see, there is no way to that with subclasses.


I believe functools.wraps does not reproduce the original call signature. However, Michele Simionato's decorator module does:

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


use 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


It is possible to do this, using inspect.getargspecs. There's even a PEP in place to make it easier.

BUT -- this is not a good thing to do. Can you imagine how much of a debugging/maintenance nightmare it would be to have your functions dynamically created at runtime -- and not only that, but done so by a metaclass?! I don't understand why you have to replace the stub dynamically; can't you just change the code when you want to change the function? I mean, suppose you have a class

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

Since you don't know what it's meant to do, the metaclass can't actually implement any functionality. If you knew what ham were meant to do, you could do it in ham or one of its parent classes, instead of returning NotImplemented.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜