How to call a function stored in a Python class instance variable

2.4k views Asked by At

I'm passing a function as a parameter to a class constructor. The constructor stores it in an instance variable, and other class methods want to call it.

class ComboList(list) :
    def __init__(self,a,b,kg) :
        list.__init__(self)
        self.__kg = kg
        # More stuff follows

When I try to call the function in another method, for example:

x = self.__kg('a')

I get "{AttributeError}'' object has no attribute '__kg'."

When I evaluate the function call in my IDE's Evaluate Expression window, I get the same thing. But when I evaluate the instance variable itself ("self.__kg"), I get:

result = {function} <function <lambda> at 0x0000000002ED5C18>

...so it appears that the attribute __kg is defined.

What is going wrong?

I can call the function by referencing the parameter -- no problem.

kg(a')

I can also assign the parameter's value to a method variable and call the variable -- no problem.

_kag = kg
_kag('a')

It's only the reference to the instance variable that doesn't work.

2

There are 2 answers

0
CodingPenguins On

Whenever a variable has a double underscore in a class, Python will invoke name mangling (see the Python documentation on classes). Using double underscores is pretty much only to avoid name clashes with subclasses or to make a variable 'really private'. (See PEP8 for more style suggestions).

If you want other inherited subclasses to use your private variable, you can either use one single underscore (_kg) or use the @property decorator.

Check out this really dumb example:

class ComboList(list) :
    def __init__(self,a,b,kg) :
        list.__init__(self)
        self.__kg = kg
        # More stuff follows

    @property
    def kg(self):
        return(self.__kg)

my_list = ComboList(1,2,'This will be printed')
print(my_list.kg)
0
hspandher On

Don't use double underscore, which makes python do some magic and append classname to variable names (called name mangling). Just use single underscore instead of double.