wewa
wewa

Reputation: 1678

Using the self-parameter in python objects

I've got a question about defining functions and the self-parameter in python.

There is following code.

class Dictionaries(object):
    __CSVDescription = ["ID", "States", "FilterTime", "Reaction", "DTC", "ActiveDischarge"]

    def __makeDict(Lst):
        return dict(zip(Lst, range(len(Lst))))

    def getDict(self):
        return self.__makeDict(self.__CSVDescription)

    CSVDescription = __makeDict(__CSVDescription)

x = Dictionaries()
print x.CSVDescription
print x.getDict()

x.CSVDescription works fine. But print x.getDict() returns an error.

TypeError: __makeDict() takes exactly 1 argument (2 given)

I can add the self-parameter to the __makeDict() method, but then print x.CSVDescription wouldn't work.

How do I use the self-parameter correctly?

Upvotes: 1

Views: 268

Answers (2)

lvc
lvc

Reputation: 35089

A solution using @staticmethod won't work here because calling the method from the class body itself doesn't invoke the descriptor protocol (this would also be a problem for normal methods if they were descriptors - but that isn't the case until after the class definition has been compiled). There are four major options here - but most of them could be seen as some level of code obfuscation, and would really need a comment to answer the question "why not just use a staticmethod?".

The first is, as @Marcus suggests, to always call the method from the class, not from an instance. That is, every time you would do self.__makeDict, do self.__class__.__makeDict instead. This will look strange, because it is a strange thing to do - in Python, you almost never need to call a method as Class.method, and the only time you do (in code written before super became available), using self.__class__ would be wrong.

In similar vein, but the other way around, you could make it a staticmethod and invoke the descriptor protocol manually in the class body - do: __makeDict.__get__(None, Dictionaries)(__lst).

Or, you could detect yourself what context its being called from by getting fancy with optional arguments:

def __makeDict(self, Lst=None):
    if Lst is None:
       Lst = self
    ...

But, by far the best way is to realise you're working in Python and not Java - put it outside the class.

def _makeDict(Lst):
    ...

class Dictionaries(object):
   def getDict(self):
      return _makeDict(self.__CSVDescription)

   CSVDescription = _makeDict(__CSVDescription)

Upvotes: 3

Ilmo Euro
Ilmo Euro

Reputation: 5135

In python, the self parameter is implicitly passed to instance methods, unless the method is decorated with @staticmethod.

In this case, __makeDict doesn't need a reference to the object itself, so it can be made a static method so you can omit the self:

@staticmethod
def __makeDict(Lst): # ...

def getDict(self):
    return self.__makeDict(self.__CSVDescription)

Upvotes: 6

Related Questions