I am writing a small application that takes users' input to give them a set of optimal parameters to use. (Each of these sets are ranked and the user can select whichever one they want to use)
To be able to do this, I select one function from an array of choices(depending on the context), partially fill the function using functools.partial
then return the partial object to another module which in turn calls a C++ library (dlib
) which has a python interface.
Up until today, I wasn't using functools.partial
to fill the function and faced no issues. But to make the code less repetitive and easier to understand, I added that in. After adding that part, I get the following error :
AttributeError: 'functools.partial' object has no attribute '__code__'
I read a few posts and realized that this is an issue with partial
objects as they often lack attributes like __name__
, __module__
etc but I am not sure how to resolve this issue.
PS: I am using python 3.7
EDIT
I am adding a small code that reproduces the error
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,)
Running the above code results in the following error
AttributeError: 'functools.partial' object has no attribute '__code__'
Is it advisable to manually add the __code__
attribute to the partial object?
I would not dare adding a
__code__
attribute to apartial
object. The__code__
attribute allows a low level access to the compiled Python code. It is normally never used in common scripts and is probably used here to interface it with the underlying C++ library.The bullet proof way is to define a new function. In Python
def
is an executable statement, and it is possible to iterately redefine a function:obj_calc
is now a true Python function and it will have its own__code__
attribute.If the
dlib
library supports it, it could be possible to use alambda
:A lambda is almost a true function and has indeed a
__code__
attribute, but it is defined as a separate object class in Python, so depending on the dlib library requirements (I could not find any reference on it) it could work or not.for solving this error we can use
wraps
functools.WRAPPER_ASSIGNMENTS
to update attributes, which defaults to ('module', 'name', 'doc') in python 2.7.6 or,we can update only present attributes...
`
just filter out all those attribute which aren't present.
second approach would be:-
*strictly deal with partial objects only.
fold wraps with
singledispatch
and it creates wrapped partial object and its attribute would be taken from the function "fun" attribute.import functools
now we can get the original functions docs.
python(CPython) 3.
from functools import wraps, partial, WRAPPER_ASSIGNMENTS
try:
*we define a new wraps function only if we fail to wrap a partial,* *use the original wraps to copy the docs*
also,
In (Python 3.5) we have a reference to the original function, and it is maintained in the partial. You can access it as
.func:
from
functools
import partial