Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the Pythonic way to initialize attributes or properties?

Python supports class attributes, instance attributes and properties.

from time import ctime, sleep

class MyClass(object):
    A = ctime()            # class attribute
    def __init__(self):
        self.B = ctime()   # instance attribute
        self._C = None

    @property
    def C(self):           # property
        if self._C is None:
            self._C = ctime()
        return self._C
    @C.setter
    def C(self, c):
        self._C

To a user who is not aware, how MyClass is implemented, A, B, and C show similar behaviour:

sleep(2)
myObject = MyClass()
sleep(2)
print myObject.A         # prints time module was initialized
print myObject.B         # prints time instance was created, 2 sec later
print myObject.C         # prints time this line was called, 2 sec later
myObject.A = 'foo'       # myObject.A is now an instance attribute
myObject.B = 'foo'       # myObject.B is still an instance attribute
myObject.C = 'foo'       # myObject.C is still an (instance) property
print myObject.A         # prints 'foo'
print myObject.B         # prints 'foo'
print myObject.C         # prints 'foo'

From the answer I got here, I understood the following: The first time myObject.A is printed, myObject.A is myObject.__Class__.A is MyClass.A. The second time myObject.A is not myObject.__Class__.A. Fine.

In the example above, ctime() was used only to illustrate, how A, B and C differ. Now assume, we are using an immutable constant instead:

class MyClass(object):
    A = 'bar'               # class attribute
    def __init__(self):
        self.B = 'meta'     # instance attribute
        self._C = None

    @property
    def C(self):            # property
        if self._C is None:
            self._C = 'foobar'
        return self._C
    @C.setter
    def C(self, c):
        self._C = c

myObject = MyClass()

myObject.A is still the class attribute MyClass.A, while myObject.B is an instance attribute and myObject.C is a property. All of them, do exactly what I want. They have a default value and I can assign some other value. Which style should I use, A, B or C?

like image 469
Jan Avatar asked Nov 14 '25 17:11

Jan


1 Answers

The preferred way to initialize a constant class attribute is in the class definition itself.

Looking at the code in the question, it seems that there is some confusion about how to access class attributes from an instance object.

Note that in an instance object you can access class attributes by name because when an attribute isn't found in the internal dictionary, the lookup continues in the class dictionary. That is, if instance.A doesn't exist, instance.__class__.A will be return instead if it's available.

However, when an attribute is created in an object instance, the the class attribute is shadowed. That is, instance.A = <value> creates a new instance attribute and the next time you access instance.A, <value> will be returned. However, the class attribute can still be retrieved using instance.__class__.A.

like image 99
jcollado Avatar answered Nov 17 '25 08:11

jcollado



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!