Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overriding class variables in python

I'm trying to understand a bit how Python (2.6) deals with class, instances and so on, and at a certain point, I tried this code:

#/usr/bin/python2.6

class Base(object):
    default = "default value in base"

    def __init__(self):
        super(Base, self).__init__()

    @classmethod
    def showDefaultValue(cls, defl = default):
        print "defl == %s" % (defl)


class Descend(Base):
    default = "default value in descend"

    def __init__(self):
        super(Descend, self).__init__()

if __name__ == "__main__":
    Descend.showDefaultValue()

The output is: "default value in base"

I was wondering why the "default" field is not overwirtten by the Descend class... Is there any way to overwrite it? Why isn't it being overwritten?

Any hint (or link to an explanatory page will be appreciated). Thank you!

like image 958
BorrajaX Avatar asked Jan 21 '11 20:01

BorrajaX


People also ask

Can you override a variable in Python?

Method overriding is an ability of any object-oriented programming language that allows a subclass or child class to provide a specific implementation of a method that is already provided by one of its super-classes or parent classes.

How do you override a class in Python?

In Python method overriding occurs by simply defining in the child class a method with the same name of a method in the parent class. When you define a method in the object you make this latter able to satisfy that method call, so the implementations of its ancestors do not come in play.

Can class variables be changed?

Any object can change the value of a class variable, but class variables can also be manipulated without creating an instance of the class.

Can you change class attributes Python?

But be careful, if you want to change a class attribute, you have to do it with the notation ClassName. AttributeName. Otherwise, you will create a new instance variable.


2 Answers

The class variable is being overwritten. Try

@classmethod
def showDefaultValue(cls):
    print "defl == %s" % (cls.default,)

The reason your way doesn't work has more to do with the way Python treats default arguments to functions than with class attributes. The default value for defl is evaluated at the time Python defines the binding for showDefaultValue and this is done exactly once. When you call your method the default value used is what was evaluated at the time of definition.

In your case, defl was bound to the value of the default variable as it was during the execution of the class body form of Base. Regardless of how you call showDefaultValue later on (i.e., whether via Base or via Descend) that value remains fixed in all subsequent invocations of showDefaultValue.

like image 80
Dirk Avatar answered Oct 10 '22 01:10

Dirk


def showDefaultValue(cls, defl=default):

means that default gets evaluated when the function is defined, as usual in Python. So the definition looks like this then:

def showDefaultValue(cls, defl="default value in base"):

This value of defl is stored as a default argument on the function object and used when you call the method without arguments. You can look at the defaults of a function like print Descend.showDefaultValue.im_self.default to validate this.

If you want to get the default from the current class then you have get it from there:

@classmethod
def showDefaultValue(cls, defl=None):
    if defl is None:
        defl = cls.default
    print "defl == %s" % (defl)
like image 41
Jochen Ritzel Avatar answered Oct 10 '22 01:10

Jochen Ritzel