Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Assigning functions as attributes of an object, then calling without the implied 'self' arguement?

Tags:

python

Python allows you to assign a pre-defined function to a class as an attribute, such as

def fish_slap(fish):
    # do something

class dance(object):
    dance_move=fish_slap

However, if we try do say

d=dance()
d.dance_move("Halibut")

we get the get the following error

TypeError: fish_slap() takes exactly 1 arguement (2 given)

Python seems to be viewing this as a object method and providing the implied 'self' argument. Fair enough, it seems I've just learned that assigning a function as an attribute in this way is equivalent to defining the function directly within the class. I can see that this is a useful feature.

However, in this case this is not what I want. In my application I have statistical models encoded as different classes which also have their own 'train' methods for training the model parameters against supplied data. In order to do this, an objective function that you wish to minimize (or maximize) the value of needs to be supplied. An example simple objective function is say

def RMSE(predicted,observed):
    "Root mean squared error"
    return sp.sqrt(sp.mean((predicted-observed)**2))

where SciPy has been imported as sp. These objective functions are defined in a single .py file and used throughout my code and naturally exists as standalone functions, rather than as class methods with the implied 'self' argument.

I want to be able to set the desired objective function as an attribute so that any subsequent work a model object does uses that function, for instance

some_model=SomeModel(initial_parameter_values_guess) 
some_model.objective_function = RMSE
some_model.train(training_data)
predictions_RMSE = some_model.predict()
some_mode.objective_function = MAE
predictions_MAE = some_model.predict()

In this example is seems I could just pass the objective function as an argument to train, however in my application there is a lot more one would want to do and it seems to make more sense to be able to set/get the objective function rather than repeatedly providing it as an argument.

There are any number of workarounds to achieve this basic behavior, but what is the most pthonic approach?

Note that my current code is python2 and python3 compliant. If there are version specific solutions please point that out. I am running with python2 in order to be able to use matplotlib however I am trying to ensure the code is python3 compatible apart from that module.

like image 641
Bogdanovist Avatar asked Feb 24 '13 21:02

Bogdanovist


People also ask

Can you call a function without arguments in Python?

7.1. In the case of no arguments and no return value, the definition is very simple. Calling the function is performed by using the call operator () after the name of the function.

What would be the consequence of not requiring the self argument in methods?

If there was no self argument, the same class couldn't hold the information for both these objects. However, since the class is just a blueprint, self allows access to the attributes and methods of each object in python. This allows each object to have its own attributes and methods.

What is self argument in function?

self represents the instance of the class. By using the “self” we can access the attributes and methods of the class in python. It binds the attributes with the given arguments. The reason you need to use self. is because Python does not use the @ syntax to refer to instance attributes.

Can a class attribute can be used without an instance of that class?

while you can access class attributes using an instance it's not safe to do so. In python, the instance of a class is referred to by the keyword self. Using this keyword you can access not only all instance attributes but also the class attributes.


1 Answers

You can use a staticmethod

class dance(object):
    dance_move=staticmethod(fish_slap)

Note that you don't need to use staticmethod if you're assigning to an attribute of an instance:

>>> def move():
...     print "disco party!"
... 
>>> class dance(object):
...     dance_move = staticmethod(move)
... 
>>> d = dance()
>>> d.dance_move()
disco party!
>>> d.break_it_down = move
>>> d.break_it_down()
disco party!
like image 123
mgilson Avatar answered Oct 03 '22 17:10

mgilson