我正在编写一个小型应用程序,该应用程序需要用户输入才能为他们提供一组最佳参数以供使用。 (对这些集合中的每一个进行排名,用户可以选择他们想要使用的任何一个)
为此,我从一个选择数组中选择一个函数(取决于上下文),使用functools.partial
部分填充该函数,然后将部分对象返回到另一个模块,该模块依次调用C ++具有python接口的库(dlib
)。
直到今天,我还没有使用functools.partial
来填充函数,并且没有遇到任何问题。但是为了使代码少重复且更易于理解,我在其中添加了代码。添加该部分后,出现以下错误:
AttributeError:'functools.partial'对象没有属性'__code __'
我阅读了几篇文章,并意识到这是partial
对象的问题,因为它们通常缺少__name__
,__module__
等属性,但我不确定如何解决此问题。
PS:我正在使用python 3.7
编辑
我正在添加一个小代码来重现错误
from functools import partial
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
from sklearn.datasets import load_breast_cancer
from dlib import find_max_global
def objective_calculator(*args, X, y):
args = args[0]
model = LogisticRegression()
model.set_params(**{'class_weight': args[0], 'max_iter':args[1]})
model.fit(train['data'], train['target'])
predictions = model.predict(X)
return accuracy_score(y, predictions)
train = load_breast_cancer()
obj_calc = partial(objective_calculator, X=train['data'], y=train['target'])
lower_bounds = [0.1, 10] # class_weight, max_iter
upper_bounds = [0.5, 200] # class_weight, max_iter
is_integer_variable = [False, True]
find_max_global(f=obj_calc,
bound1=lower_bounds,
bound2=upper_bounds,
num_function_calls=2,
is_integer_variable=is_integer_variable,
solver_epsilon=1,)
运行上面的代码会导致以下错误
AttributeError:'functools.partial'对象没有属性'__code __'
建议手动将__code__
属性添加到部分对象吗?
答案 0 :(得分:1)
AttributeError: 'functools.partial' object has no attribute '__code__'
为解决此错误,我们可以使用
functools.WRAPPER_ASSIGNMENTS
更新属性,
默认为(“ 模块”,“ 名称”,“ 文档”)
在python 2.7.6中
或者,
我们只能更新当前属性...
import functools
import itertools
def wraps_safely(obj, attr_names=functools.WRAPPER_ASSIGNMENTS):
return wraps(obj, assigned=itertools.ifilter(functools.partial(hasattr, obj), attr_names))
`>>> def foo():
`... ` ` """ Ubiquitous foo function ...."""`
...
>>> functools.wraps(partial(foo))(foo)()
`Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File ```"/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/functools.py", ``line 33, in update_wrapper`
setattr(wrapper, attr, getattr(wrapped, attr))
AttributeError: 'functools.partial' object has no attribute '__module__'
>>> wraps_safely(partial(foo))(foo)()
>>> `
`
*仅严格处理部分对象。
使用singledispatch
进行折叠包装,并创建包装的部分对象,其属性将从函数“ fun”的属性中获取。
导入functools
def wraps_partial(wrapper, *args, **kwargs):
` """ Creates a callable object whose attributes will be set from the partials nested func attribute ..."""
` ` ` wrapper = wrapper.func``
while isinstance(wrapper, functools.partial):
wrapper = wrapper.func
return functools.wraps(wrapper, *args, **kwargs)
# after returning functools.wraps
def foo():
""" Foo function.
:return: None """
pass
>>> wraps_partial(partial(partial(foo)))(lambda : None).__doc__
' Foo Function, returns None '
>>> wraps_partial(partial(partial(foo)))(lambda : None).__name__
'foo'
>>> wraps_partial(partial(partial(foo)))(lambda : None)()
>>> pfoo = partial(partial(foo))
>>> @wraps_partial(pfoo)
... def not_foo():
...
""" Not Foo function ... """
...
>>> not_foo.__doc__
' Foo Function, returns None '
>>> not_foo.__name__
'foo'
>>>
从functools导入包装,部分包装,WRAPPER_ASSIGNMENTS
尝试:
wraps(partial(wraps))(wraps)
except AttributeError:
@wraps(wraps)
def wraps(obj, attr_names=WRAPPER_ASSIGNMENTS, wraps=wraps):
return wraps(obj, assigned=(name for name in attr_names if hasattr(obj, name)))
*仅当我们无法包装部分包装时,我们才定义新的包装功能* *使用原始包装纸复制文档*
还
在(Python 3.5)中,我们引用了原始函数,并且将其保留在局部函数中。您可以通过.func:
从functools
导入部分
def a(b):
print(b)
In[20]: c=partial(a,5)
In[21]: c.func.__module__
Out[21]: '__main__'
In[22]: c.func.__name__
Out[22]: 'a'
答案 1 :(得分:1)
我不敢向__code__
对象添加partial
属性。 __code__
属性允许对已编译 Python代码的低级别访问。通常,它通常不会在通用脚本中使用,并且可能在此处用于与基础C ++库进行接口。
防弹方式是定义一个新功能。在Python中,def
是一个可执行语句,可以迭代地重新定义一个函数:
def objective_calculator(*args, X, y):
...
for X, y in ...:
def obj_calc(*args):
return objective_calculator(*args, X, y)
...
find_max_global(f=obj_calc, ...)
obj_calc
现在是真正的Python函数,它将具有自己的__code__
属性。
如果dlib
库支持它,则可以使用lambda
:
find_max_global(f=lambda *args: objective_calculator(*args, X, y), ...)
lambda几乎是一个真正的函数,确实具有__code__
属性,但是在Python中它被定义为一个单独的对象类,因此取决于dlib库的要求(我找不到关于它的任何引用)它可能行不通。