Reputation: 63
I am new in python. I want to write an add_function method for this class to add any function to my class dynamically. This function can manipulate some attributes of my class but it is written outside the class. Assume this class and its method.
import numpy as np
import feature_function as ffun
class Features:
def __init__(self,x,fs=None):
self.x = x
self.fs = fs
self.label = []
self.features = []
def __mean(self, nan_omit = False, min_samples = 1):
out = ffun.mean(self.x, nan_omit = nan_omit, min_samples = min_samples)
self.label.extend(['mean'])
self.features = np.append(self.features,out)
now I want to write this function outside of the scope of class:
def __max(self, nan_omit = False, min_samples = 1):
out = ffun.max(self.x, nan_omit = nan_omit, min_samples = min_samples)
self.label.extend(['max'])
self.features = np.append(self.features,out)
and add it to class. In order to add function to class I have an add_function method inside my class that its arguments are the function that is passed outside the class and also the name of the function.
# Add function dynamically by user
def add_function(self, name, methodToRun, type ):
name2 = '__' + name
# setattr(self, name2, methodToRun)
setattr(self, mangle_attr(self, name2), methodToRun)
mangle_attr
is a function in order to set private function to a class.
def mangle_attr(source, attr):
# if source is an object, get the class
if not hasattr(source, "__bases__"):
source = source.__class__
# mangle attr
tmp = {}
code = _mangle_template.format(cls=source.__name__, attr=attr)
eval(compile(code, '', 'exec'), {}, tmp);
return tmp['cls'].mangle.__code__.co_varnames[0]
using setattr
doesn't bound __max
function to my class, for example __mean
is bounded in my class, if I call the function I can see:
<bound method Features.__mean of <__main__.Features object at 0x7fd4c91aac10>>
however for __max
I still see this:
<function skewness at 0x7fd2b9dbfb90>
do I have a solution for this problem?
Upvotes: 6
Views: 3766
Reputation: 50106
Your addfunction
binds its argument to the instance self
, not to the class. Bind the argument to the class, e.g. via type(self)
or a classmethod
:
class Features:
...
# Add function dynamically by user
@classmethod
def add_function(cls, name, methodToRun, type ):
name2 = '__' + name
setattr(cls, mangle_attr(self, name2), methodToRun)
A bound method is a function on the class, looked up through the instance. Adding a function to an instance merely makes it an attribute, which happens to be callable.
Upvotes: 5
Reputation: 9197
A simpler example to show the general idea:
# Create the class without a method
class Features():
def __init__(self):
self.x = 100
# Create a function outside of the class
def multiply(self):
return self.x*2
# initialize class object, then add function as a method to the class
obj = Features()
setattr(Features, "multiply", multiply)
obj.multiply()
Upvotes: 4