【问题标题】:Partial function object has no attribute "__code__"部分函数对象没有属性“__code__”
【发布时间】:2019-07-04 06:17:22
【问题描述】:

我正在编写一个小型应用程序,它接受用户的输入,为他们提供一组最佳参数以供使用。 (这些集合中的每一个都被排名,用户可以选择他们想要使用的任何一个)

为了能够做到这一点,我从一组选项中选择一个函数(取决于上下文),使用functools.partial 部分填充函数,然后将部分对象返回到另一个模块,该模块又调用 C++ 库( dlib),它有一个 python 接口。

直到今天,我还没有使用 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__ 属性添加到部分对象?

【问题讨论】:

  • 显示出现此错误的代码。
  • @furas,代码是更大代码库的一部分。我需要一些时间来生成一个 mvc 代码。
  • @furas,我在编辑部分添加了一个小代码。请看一下
  • @furas,也许你可以帮忙解决这个问题stackoverflow.com/questions/56882865/…

标签: python python-3.x partial functools


【解决方案1】:
AttributeError: 'functools.partial' object has no attribute '__code__'

为了解决这个错误,我们可以使用

包装

functools.WRAPPER_ASSIGNMENTS 更新属性, 默认为 ('module', 'name', 'doc') 在 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”属性。

导入功能工具

  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'



 >>>

现在我们可以获取原始函数文档了。

python(CPython) 3.

from functools import wraps, partial, 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)))

*我们定义一个新的 wraps 函数,只有当我们不能包装一个部分时,* *使用原始包装复制文档*

还有,

在(Python 3.5)中,我们有一个对原始函数的引用,它在部分中被维护。您可以通过.func:访问它

来自functoolsimport 部分

 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'

【讨论】:

  • 你的缩进到处都是,你要纠正它吗?
【解决方案2】:

我不敢将__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 库的要求(我找不到任何关于它的参考)它可以工作与否。

【讨论】:

    猜你喜欢
    • 2018-06-03
    • 1970-01-01
    • 2013-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-01
    • 1970-01-01
    • 2022-01-14
    相关资源
    最近更新 更多