Jan Musil
Jan Musil

Reputation: 508

self is not defined in class method argument

I have 4 classes with several methods in each of them. I need these methods to use some class variables as arguments, eg.

class Orange:
    def __init__(self,banana):
        self.banana = banana

    def apple(self,fruit=self.banana):
        return something

I already found out that this does not work as method arguments are defined when function is created, not when it is called, so i found a workaround here:

def apple(self,fruit=None):
    if fruit is None:
        fruit = self.banana

But the problem is, that i have about 50 arguments (no in each method, but summary from all methods of all classes) and using this method, i would get about one hundred new lines of code and that seems to me like very "dirty" workaround... isnt there any easier way how to reach that?

Upvotes: 3

Views: 1926

Answers (3)

Henry Woody
Henry Woody

Reputation: 15652

There are two ways to go with this problem.

Option 1

Use the method you have shown in your problem statement, but perhaps with a ternary operator to trim the number of lines:

def apple(self, fruit=None):
    fruit = fruit if fruit is not None else self.banana

Option 2

Consider revising the structure of your code. For example, it might not be necessary to allow the fruit used in each method to vary when called, and instead just using a preset option, like self.banana. (Basically just remove the keyword argument fruit altogether and just go ahead and use self.banana instead.) For those that do need to vary when the method is called, then resort to Option 1.

Upvotes: 2

Muhammad Hazrat
Muhammad Hazrat

Reputation: 1

The Best Option is to make separate Mutator for it

def setFruit(self, fruit):
    self.fruit = fruit

Upvotes: 0

Jan Musil
Jan Musil

Reputation: 508

Thanks guys, thanks to your comments and answers i found a complete solution.

>>> class Orange:
...     def __init__(self,banana="a"):
...         self.banana = banana
...     def apple(self,**kwargs):
...         self.__dict__.update(kwargs)
...         return self.banana
...
>>> test = Orange()
>>> test.apple()
'a'
>>> test.apple(banana="b")
'b'

So as you can see, passing different keyword variable will change the result, exactly as i wanted. However, only disadvantage (but it can be also advantage, depends on point of view) is, that this change is permanent so if we call the function again, its still changed like this:

>>> test.apple()
'b'

But this is not problem for me at all. If anyone wonders how to make this changes only temporary, save original init values to dict, and then when you want to use them, update the class dict, with variable where these values are saved, as following:

>>> class Orange:
...     def __init__(self,fruit={"banana":"a","cherry":"b"}):
...         self.fruit=fruit
...     def apple(self,**kwargs):
...         self.__dict__.update(self.fruit)
...         self.__dict__.update(kwargs)
...         return self.banana
...
>>> test = Orange()
>>> test.apple()
'a'
>>> test.apple(banana="b")
'b'
>>> test.apple()
'a'

Self.fruit stores original information, and it refreshs class variables in the beginning of function. If something is in kwargs, it just overrides it.

Upvotes: 1

Related Questions