假设我编写了一个装饰器来做一些非常通用的东西.例如,它可能会将所有参数转换为特定类型,执行日志记录,实现memoization等.
这是一个例子:
def args_as_ints(f):
def g(*args, **kwargs):
args = [int(x) for x in args]
kwargs = dict((k, int(v)) for k, v in kwargs.items())
return f(*args, **kwargs)
return g
@args_as_ints
def funny_function(x, y, z=3):
"""Computes x*y + 2*z"""
return x*y + 2*z
>>> funny_function("3", 4.0, z="5")
22
Run Code Online (Sandbox Code Playgroud)
到目前为止一切都很顺利.然而,有一个问题.装饰函数不保留原始函数的文档:
>>> help(funny_function)
Help on function g in module __main__:
g(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)
幸运的是,有一个解决方法:
def args_as_ints(f):
def g(*args, **kwargs):
args = [int(x) for x in args]
kwargs = dict((k, int(v)) for k, v in kwargs.items()) …Run Code Online (Sandbox Code Playgroud) 以下作品:
def spam():
print "spam"
exec(spam.__code__)
Run Code Online (Sandbox Code Playgroud)
垃圾邮件
但如果spam需要参数呢?
def spam(eggs):
print "spam and", eggs
exec(spam.__code__)
Run Code Online (Sandbox Code Playgroud)
TypeError:spam()只需1个参数(给定0)
鉴于,我无法访问函数本身,只能访问代码对象,如何在执行代码对象时将参数传递给代码对象?是否可以使用eval?
编辑:由于大多数读者往往不相信这有用,请参阅以下用例:
我想将小Python函数保存到文件中,以便可以从另一台计算机中调用它们.(这里不用说这个用例严格限制了可能的功能.)pickle函数对象本身不起作用,因为这只保存了定义函数的名称和模块.相反,我可以腌制__code__功能.当我再次取消它时,当然对函数的引用消失了,这就是我无法调用该函数的原因.我只是在运行时没有它.
另一个用例:
我在一个文件中处理几个函数,计算一些数据并将其存储在硬盘上.计算会耗费大量时间,所以我不想每次都执行这些函数,但只有在函数的实现发生变化时才会执行.
我有一个版本的运行整个模块而不是一个功能.它通过查看实现模块的文件的修改时间来工作.但是如果我有许多我不想在单个文件中分离的函数,那么这不是一个选项.
如果我有一个函数(在Python 2.5.2中),如:
def sample_func():
a = 78
b = range(5)
#c = a + b[2] - x
Run Code Online (Sandbox Code Playgroud)
我的问题是:
提前致谢.
编辑:
每个人都在要求用例.但这是一个奇怪的情况.(别怪我,我没有创造它).这是场景:
我有我的简单装饰器my_decorator装饰my_func.
def my_decorator(func):
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
wrapper._decorator_name_ = 'my_decorator'
return wrapper
@my_decorator
def my_func(x):
print('hello %s'%x)
my_func._decorator_name_
'my_decorator'
Run Code Online (Sandbox Code Playgroud)
直到这里工作,但我看不到功能的实际签名.
my_func?
Signature: my_func(*args, **kwargs)
Docstring: <no docstring>
File: ~/<ipython-input-2-e4c91999ef66>
Type: function
Run Code Online (Sandbox Code Playgroud)
如果我用python's装饰我的装饰器decorator.decorator,我可以看到我的函数的签名但我不能拥有我定义的新属性.
import decorator
@decorator.decorator
def my_decorator(func):
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
wrapper._decorator_name_ = 'my_decorator'
return wrapper
@my_decorator
def my_func(x):
print('hello %s'%x)
my_func?
Signature: my_func(x)
Docstring: <no docstring>
File: ~/<ipython-input-8-934f46134434>
Type: function
my_func._decorator_name_
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-10-7e3ef4ebfc8b> …Run Code Online (Sandbox Code Playgroud) 我希望在下面的代码中,当我键入时 instance_of_A = A(,假定参数的名称是init_argumentA而不是*meta_args, **meta_kwargs。__call__但不幸的是,显示了元类方法的参数。
class Meta(type):
def __call__(cls,*meta_args,**meta_kwargs):
# Something here
return super().__call__(*meta_args, **meta_kwargs)
class A(metaclass = Meta):
def __init__(self,init_argumentA):
# something here
class B(metaclass = Meta):
def __init__(self,init_argumentB):
# something here
Run Code Online (Sandbox Code Playgroud)
我已经搜索了一个解决方案,并发现了问题如何动态更改子类中方法的签名? 和签名更改装饰器:正确记录附加参数。但没有一个,似乎完全是我想要的。第一个链接使用检查来更改赋予函数的变量数量,但我似乎无法让它适用于我的情况,我认为必须有一个更明显的解决方案。第二个并不完全是我想要的,但这种方式可能是一个不错的选择。
编辑:我在 Spyder 工作。我想要这个是因为我有数千个元类型的类,每个类都有不同的参数,这是不可能记住的,所以我们的想法是用户在看到正确的参数出现时可以记住它。
我正在使用 Python,我从这里的参数的 REST 端点获得了一个定义:
我想要做的是以下内容:
OnlineMethod(above_url).CreateDriveTimePolygons(Input_Location=(25,-34), Drive_Times="5,12,31")
Run Code Online (Sandbox Code Playgroud)
我可以setattr在 obj 上使用来定义预制函数,但我的问题如下:
谢谢
目标是不使用 kwargs 或 args