简体   繁体   中英

Python: dynamically create methods based on other classes'

I've looked for quite a while but couldn't find a proper answer to my question: I have a class containing methods which operate on arrays and I want dynamically create methods with a similar name in another class with a modified output.

I've got something like this so far, can anyone guide me ?

Thanks

Class A():

    def__init__(self,array):
        self.data = array

    def method1(self,*args):
        newarray = whatever(self.data,*args)
        return newarray

    def method2(self,*args):
        newarray = whatever2(self.data,*args)
        return newarray

I want to be able to use those methods to generate new ones in a more complex class, say:

class B(C):    #inherits from C

    def __init__(self,[arg1,array]):
        #initialize from parent class
        C.__init__(self,[arg1,array])

        #create new methods for this class using same name
        methodnames = [element for element in dir(A) if element[0] != '_']

        for methodname in methodnames:
            ##following works but this is not the output I want here
            #self.__dict__[methodname] = getattr(A(array),methodname)

            #following doesn't work... at least not as I expect it to
            #case1
            #self.__dict__[methodname] = [arg1,getattr(A(array),methodname)]
            #case2
            self.__dict__[methodname] = list([arg1,getattr(A(array),methodname)])

a = array
#following returns a list of [arg1, method] but what I really want is [arg1,newarray]
C([arg1,array]).method1(*args)

OK, so let's try to be clearer:

Class A contains filters, takes an array and applies filter as method, returns filtered data.

Class filters()

def__init__(self,array):
    self.data = array

def filter1(self,*args):
    newarray = median(self.data,*args)
    return newarray

def filter2(self,*args):
    newarray = gaussian(self.data,*args)
    return newarray

...

In another module, I have class SpecialData, which operates on a list of x,y data (where x and y are iterables, ie lists, arrays...). So something like

Class SpecialData():

def __init__(self,[x,y]):
    self.data = [x,y]

def power(self,power):
    ypow = self.data[1]**power
    return [x,pow]

def porod(self):
    return [x**4,x**4*y]

....

Now, what I want is to add the filter methods contained in class filters to class SpecialData. I could, of course do this by re-coding all filters with proper format for SpecialClass. but what I really want, is that each time a new filter is added to class filters, to make it available at runtime in class SpecialData without having to re-hard code the new filter.

So, not being very clever, I tried to read the list of available filters in class filters by:

import filters

filternames = [element for element in dir(filters) if element[0] != '_']

for fitlername in filternames: generate_filters_in_class_SpecialClass

How do I do this properly ?

I found a number of posts related to this, some using super(), others using SpecialData. dict or even setattr. Since the 2nd seemed more understandable to me, I focused on this one and came up with:

import filters

Class SpecialData():

def __init__(self,[x,y]):
    self.data = [x,y]

    filternames = [element for element in dir(filters) if element[0] != '_']

    for fitlername in filternames:

        self.__dict__[fitlername ] = [self.data[0],getattr(filters(self.data[1]),fitlername)]

Of course, this doesn't work, because the list is not callable. If I change the last line to : self. dict [fitlername ] = list([self.data[0],getattr(filters(self.data[1]),fitlername)]) it returns the method as the 2nd element, rather than the result.

Note that the following works, but this is not what I want... self. dict [fitlername ] = getattr(filters(self.data[1]),fitlername)

Hope this is clearer now...

I think you are trying to make an advanced use of Python without using/knowing its advanced features, like you are borrowing techniques from another language.

This is not a criticism, but you should have a look on Python tutorial , Python introspection or metaclasses .

I think that if you just complete your knowledge on Python functions you will be easily able to solve your problem in a much simpler way.

Rather than generating a proposed solution, you should make it clearer what you are trying to achieve. Class A is a clear example of the starting point; please post an example of your desired ending point, eg

Class B(): 

    def__init__(self,array): 
        self.data = array 

    def method1(self,*args): 
        newarray = ComplexWhatever(self.data,*args) 
        return newarray 

    def method2(self,*args): 
        newarray = EvenBiggerWhatever2(self.data,*args) 
        return newarray 

a = A(input_array)
b = B(input_array)
print(a.method1(args))
print(b.method1(args))

What isn't clear is how you want to "dynamically generate" the new function "ComplexWhatever()" instead of writing the function by hand.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM