Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python class syntax - is this a good idea?

Tags:

python

syntax

I'm tempted to define my Python classes like this:

class MyClass(object):
    """my docstring"""

    msg = None
    a_variable = None
    some_dict = {}

    def __init__(self, msg):
        self.msg = msg

Is declaring the object variables (msg, a_variable, etc) at the top, like Java good or bad or indifferent? I know it's unnecessary, but still tempting to do.

like image 222
Lucy Avatar asked Dec 02 '22 06:12

Lucy


2 Answers

Defining variables in the class defintion like that makes the variable accessible between every instance of that class. In Java terms it is a bit like making the variable static. However, there are major differences as show below.

class MyClass(object):
    msg = "ABC"

print MyClass.msg     #prints ABC
a = MyClass()
print a.msg           #prints ABC
a.msg = "abc"
print a.msg           #prints abc
print MyClass.msg     #prints ABC
print a.__class__.msg #prints ABC

As seen from the above code, it is not quite the same thing, as while the variable can be access via self.msg, when it is assigned a value it is not assigned to the variable defined at class scope.

One of the disadvantage of doing it via the method you do is that it can lead to errors as it adds hidden state the the class. Say someone left out self.msg = "ABC" from the constructor (Or more realistically code was refactored and only one of the definitions was altered)

a = MyClass()
print a.msg   #prints ABC

#somewhere else in the program
MyClass.msg = "XYZ"

#now the same bit of code leads to a different result, despite the expectation that it
#leads to the same result.
a = MyClass()
print a.msg   #prints XYZ

Far better to avoid defining msg at the class level and then you avoid the issues:

class MyClass(object):
    pass

print MyClass.msg #AttributeError: type object 'MyClass' has no attribute 'msg'
like image 168
Yacoby Avatar answered Dec 04 '22 01:12

Yacoby


Declaring variables directly inside the class definition makes them class variables instead of instance variables. Class variables are somewhat similar to static variables in Java and should be used like MyClass.a_variable. But they can also be used like self.a_variable, which is a problem because naive programmers can treat them as instance variables. Your "some_dict" variable, for example, would be shared by each instance of MyClass, so if you add a key "k" to it, that will be visible to any instance.

If you always remember to re-assign class variables, there's almost no difference to instance variables. Only the initial definition in MyClass will remain. But anyway, that's not good practice as you might run into trouble when not re-assigning those variables!

Better write the class like so:

class MyClass(object):
    """
    Some class
    """

    def __init__(self, msg):
        self.__msg = msg
        self.__a_variable = None
        self.__some_dict = {}

Using two underscores for "private" variables (pseudo-private!) is optional. If the variables should be public, just keep their names without the __ prefix.

like image 41
AndiDog Avatar answered Dec 04 '22 03:12

AndiDog