6

I am trying write a signal processing package, and I want to let user creates a custom function without needing to access the class file :

class myclass():
    def __init__(self):
        self.value = 6
    def custom(self, func, **kwargs):
        func(**kwargs)
        return self

c = myclass()
def add(**kwargs):
    self.value +=  kwargs['val']

kwargs = {'val': 4}
c.custom(add, **kwargs )
print (c.value)

I got name 'self' is not defined. Of course because func is not a method to the class. But I am not sure how to fix it. Please advice.

Thanks

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
J_yang
  • 2,672
  • 8
  • 32
  • 61
  • this may help: https://stackoverflow.com/questions/5626193/what-is-monkey-patching (may even be a duplicate?) – hiro protagonist Apr 04 '19 at 09:40
  • The problem has **nothing to do with** passing a function to a method (by the way, that is an **instance** method, not a class method) as an argument - you **already do this correctly. The problem is **in that method**, you do not correctly pass **the instance** to **the function** - and neither does that function *receive* the instance as a parameter, but it *needs* that instance, because it will use that. – Karl Knechtel Mar 29 '23 at 00:31

3 Answers3

9

You need to pass the class instance into the method too, do this :

class myclass():
    def __init__(self):
        self.value = 6
    def custom(self, func, **kwargs):
        func(self, **kwargs) ## added self here
        return self

c = myclass()
def add(self, **kwargs):  ## added self here
    self.value +=  kwargs['val']

kwargs = {'val': 4}
c.custom(add, **kwargs )
print (c.value)

output : 10

Mohamed Benkedadra
  • 1,964
  • 3
  • 21
  • 48
5

You can explicitly pass the self argument to add:

class myclass():
    def __init__(self):
        self.value = 6
    def custom(self, func, **kwargs):
        func(self, **kwargs)
        return self

c = myclass()
def add(self, **kwargs):
    self.value +=  kwargs['val']

kwargs = {'val': 4}
c.custom(add, **kwargs )
print (c.value)

Output:

10
Cloudomation
  • 1,597
  • 1
  • 6
  • 15
1

I would do one of the following:

1) Make the custom method a method of the class.

class myclass():
    def __init__(self):
        self.value = 6
    def custom(self, func, **kwargs):
        func(**kwargs)
        return self
    def add(self, **kwargs):
        self.value +=  kwargs['val']

kwargs = {'val': 4}
c = myclass()
c.custom( c.add, **kwargs )
print (c.value)    # Result == 10

2) Do not give the custom value itself access to class variables.

class myclass():
    def __init__(self):
        self.value = 6
    def custom(self, func, **kwargs):
        self.value += func(**kwargs)
        return self


def add(**kwargs):
    return kwargs['val']

kwargs = {'val': 4}
c = myclass()
c.custom(add, **kwargs )
print (c.value)    # Result == 10
  • I am afraid this is not the intention as the class will be in a package which I don't want user to access. But the answers above nicely solved the bug. – J_yang Apr 04 '19 at 10:02