为了娱乐,我想知道如何实现以下目标:
functionA = make_fun(['paramA', 'paramB'])
functionB = make_fun(['arg1', 'arg2', 'arg3'])
相当于
^{pr2}$这意味着需要以下行为:
functionA(3, paramB=1) # Works
functionA(3, 2, 1) # Fails
functionB(0) # Fails
问题的焦点是变量argspec-I是否可以轻松地使用常用的装饰器技术创建函数体。在
对于那些感兴趣的人,我试着用编程方式创建如下类。同样,困难在于生成带有编程参数的__init__
方法——类的其余部分使用修饰符或元类看起来很简单。在
class MyClass:
def __init__(self, paramA=None, paramB=None):
self._attr = ['paramA', 'paramB']
for a in self._attr:
self.__setattr__(a, None)
def __str__(self):
return str({k:v for (k,v) in self.__dict__.items() if k in self._attributes})
可以使用^{} 从包含Python代码的字符串构造函数对象:
示例:
^{pr2}$如果您想要更多的功能(例如,默认的参数值),那就需要调整包含代码的字符串并让它表示所需的函数签名。在
免责声明:正如下面所指出的,重要的是要验证
parameters
的内容,并且生成的Python代码字符串可以安全地传递给exec
。您应该自己构造parameters
,或者设置适当的限制,以防止用户为parameters
构造恶意值。在下面是另一种方法,使用
functools.wrap
,它保留了签名和docstring,至少在Python3中是这样。诀窍是在从未被调用的伪函数中创建签名和文档。这里有几个例子。在基本示例
结果是:
^{pr2}$调用
inspect.signature(exposed_func_1).parameters
返回所需的签名。但是,使用inspect.getfullargspec(exposed_func_1)
仍然返回template
的签名。至少,如果您在template
的定义中放置所有要生成的函数的公共参数,这些参数将出现。在如果因为某种原因这是个坏主意,请告诉我!在
更复杂的例子
通过在内部函数中分层并定义更多不同的行为,可以得到比这更复杂的结果:
这有点冗长,但关键是,在使用它创建函数时,来自您(程序员)的动态输入有很大的灵活性,在使用公开的输入(来自函数的用户)时也有很大的灵活性。在
使用类的一种可能的解决方案:
相关问题 更多 >
编程相关推荐