2

Let us suppose the following situation: I have a class with some initial values. Furthermore, I want to provide the possibility to pass an user-defined method, when initializing a new object. The user knows about the attributes of the class in advance and may want to consider them in the function, for instance:

class some_class():
    def __init__(self, some_method):
        # some initial values
        self.a = 8
        self.b = 12
        # initializing a new object with a user-specific method
        self.some_method = some_method 

    def some_method(self):
        pass # this method shall be specified by the user

# user-specific function
def some_function(): 
    return self.a + self.b

some_object = some_class(some_method = some_function)
print(some_object.some_method())

Of course, the given example does not work, but I hope it shows what I want to do. I am searching for a way to define a function outside the class, which refers to the attribute of an object after it was passed during initialization.

What I try to avoid is to solve the problem with fixed name conventions, for instance:

class some_class():
    def __init__(self, some_method):
        self.a = 8
        self.b = 12
        self.some_method = some_method 

    def some_method(self):
        pass

def some_function(): 
    return some_object.a + some_object.b # -> fixed names to avoid the problem

some_object = some_class(some_method = some_function)
print(some_object.some_method())

I think what I need is a kind of placeholder or alternative to self. Does anybody has an idea?

Slango
  • 45
  • 6
  • If you want the user to supply additional code when using your class, they should be subclassing it rather than merely instantiating it. – jasonharper Apr 29 '19 at 15:01
  • 1
    What you want to do is binding a function to an object. See this question: https://stackoverflow.com/questions/1015307/python-bind-an-unbound-method – blues Apr 29 '19 at 15:03
  • Indeed but it is doable. I mean, this is python, all kinds of loopyland things are possible. – Josef Korbel Apr 29 '19 at 15:04
  • Thank you all for the many advices. However, blues is right. After following his link, I recognized that it was exactly, what I have searched. I just didn't know how it is called, what I've searched for – Slango Apr 30 '19 at 18:23

3 Answers3

6

This works, although not sure it is the most elegant way to achieve what you want:

class some_class():
    def __init__(self, some_method):
        self.a = 8
        self.b = 12
        self.some_method_func = some_method

    def some_method(self):
        return self.some_method_func(self)

def some_function(self):
    return self.a + self.b

some_object = some_class(some_method = some_function)
print(some_object.some_method())
vladmihaisima
  • 1,687
  • 13
  • 18
  • 1
    The proper way to do that is binding the function. https://stackoverflow.com/questions/1015307/python-bind-an-unbound-method – blues Apr 29 '19 at 15:04
0

If I'm reading this right, then the easy option is just to do the following:

class some_class():
    def __init__(self):
        self.a = 8
        self.b = 12

    def some_method(self):
        pass

def my_method(self):
    return self.a + self.b

# Redefine the class method
some_class.some_method = my_method

# Or, if you only want to do it for a specific instance:

instance = some_class()
instance.some_method = my_method

The usual way to do this 'properly' though is with sub-classing.

match
  • 5,496
  • 1
  • 15
  • 32
0

You need to get the class and the caller of the class to agree to a contract. The contract is that the class will pass in the instance of the class to the function, and the function must accept that as an argument.

class some_class():
    def some_method(self):
        return self.some_method_func(self)

def some_function(obj):
   return obj.a + obj.b
Bryan Oakley
  • 310,202
  • 36
  • 445
  • 584