Skip to content Skip to sidebar Skip to footer

Python Class Constructor (static)

Does Python have a mechanism for class constructors, i.e. a function that is called whenever the class is first referenced (as opposed to when an instance of that object is created

Solution 1:

You can use a class decorator:

defadd_arg(cls):
    ifnothasattr(cls, "arg"):
        cls.arg = 'foo'return cls

@add_argclassT(object):
    pass

Or a custom metaclass:

classWithArg(type):
    def__new__(meta, name, bases, attrs):
        cls = type.__new__(meta, name, bases, attrs)
        ifnothasattr(cls, "arg"):
            cls.arg = "foo"return cls

# python 2classT(object):
    __metaclass__ = WithArg

# python 3classT(metaclass=WithArg):
    pass

But as others already mention this won't give you much more than plainly setting the class attribute in the class statement.

NB : if you want a computed attribute on the class itself, you'll have to either set it as a property on a custom metaclass

classWithProp(type):@propertydefarg(cls):
         return"foo"classT(object):
     __metaclass__ = WithProp

 T.arg
 => 'foo'

But arg will only be available on the class object itself, not on it's instances:

T().arg
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'T' object has no attribute 'arg'

or write your own custom descriptor:

classArgDescriptor(object):def__get__(self, obj, cls=None):
        return42classT(object):
    arg = ArgDescriptor()

T.arg
=> 42
T().arg
=> 42

Solution 2:

You simply have to initialise the class variable when declaring it within the class

classT:
    arg = 'foo'#this initialises the class instancedef__init__(self):
        self.arg = 'bar'#this initialises the object instanceprint(T.arg)  # class instance returns 'foo'
obj = T()
print(T.arg)  # class instance still returns 'foo'print(obj.arg)  # object instance returns 'bar'

Solution 3:

I create a static_init decorator which calls a static_init class method if it exists. This static_init class method will run when the class decorator is evaluated which is when the class is defined - so not quite when the class is first referenced - but it is analogous to static initialization in other languages like Java.

Here is the decorator and example of how to use it to initialize a class variable on an enum class:

# pylint: disable=missing-docstring,no-memberimport enum

defstatic_init(cls):
    ifgetattr(cls, "static_init", None):
        cls.static_init()
    return cls

@static_initclassSomeEnum(enum.Enum):
    VAL_A = enum.auto()
    VAL_B = enum.auto()
    VAL_C = enum.auto()
    VAL_D = enum.auto()

    @classmethoddefstatic_init(cls):
        text_dict = {}
        setattr(cls, 'text_dict', text_dict)
        for value in cls:
            text_dict[value.name.lower().replace("_", " ").title()] = value

deftest_static_init():
    assert SomeEnum.text_dict["Val A"] == SomeEnum.VAL_A
    assert SomeEnum.text_dict["Val B"] == SomeEnum.VAL_B
    assert SomeEnum.text_dict["Val C"] == SomeEnum.VAL_C
    assert SomeEnum.text_dict["Val D"] == SomeEnum.VAL_D

Post a Comment for "Python Class Constructor (static)"