210

In Python, I want a class to have some "constants" (practically, variables) which will be common in all subclasses.

Is there a way to do it with friendly syntax? Right now I use:

class Animal:
    SIZES=["Huge","Big","Medium","Small"]

class Horse(Animal):
    def printSize(self):
        print(Animal.SIZES[1])

and I'm wondering if there is a better way to do it?
or a way to do it without then having to write "Animal." before the sizes.

Horse inherits from Animal.

4
  • 35
    Not a full answer but If SIZES never changes, definitely use a tuple instead of a list. Like so ("Huge","Big","Medium","Small") Commented May 20, 2012 at 9:53
  • 3
    Looks like you're really after an enum here Commented May 20, 2012 at 11:39
  • @jamylak your comment seems to be popular, many people seem to consider it valueable. Could you explain the logic behind it? Commented Apr 29, 2021 at 13:11
  • 3
    @dmigo Just that the question was asking about constants and a list can be mutated, so it's better to use a tuple which is immutable. A constant should not change Commented Apr 29, 2021 at 13:46

5 Answers 5

206

Since Horse is a subclass of Animal, you can just change

print(Animal.SIZES[1])

with

print(self.SIZES[1])

Still, you need to remember that SIZES[1] means "big", so probably you could improve your code by doing something like:

class Animal:
    SIZE_HUGE="Huge"
    SIZE_BIG="Big"
    SIZE_MEDIUM="Medium"
    SIZE_SMALL="Small"

class Horse(Animal):
    def printSize(self):
        print(self.SIZE_BIG)

Alternatively, you could create intermediate classes: HugeAnimal, BigAnimal, and so on. That would be especially helpful if each animal class will contain different logic.

Sign up to request clarification or add additional context in comments.

1 Comment

SIZE_BIG=["BigOne","BigTwo"] shall i use this type of constant.
28

You can get to SIZES by means of self.SIZES (in an instance method) or cls.SIZES (in a class method).

In any case, you will have to be explicit about where to find SIZES. An alternative is to put SIZES in the module containing the classes, but then you need to define all classes in a single module.

2 Comments

Horse is indeed a subclass of Animal. Actually, it is perfectly possible to use self.SIZES[1] instead of Animal.SIZES[1].
@betabandido: the OP corrected the question. Will update the answer accordingly.
22
class Animal:
    HUGE = "Huge"
    BIG = "Big"

class Horse:
    def printSize(self):
        print(Animal.HUGE)

1 Comment

Also you can access via self, ex. "self.HUGE" or "self.BIG". This would only work internally within the class.
6

Expanding on betabandido's answer, you could write a function to inject the attributes as constants into the module:

def module_register_class_constants(klass, attr_prefix):
    globals().update(
        (name, getattr(klass, name)) for name in dir(klass) if name.startswith(attr_prefix)
    )

class Animal(object):
    SIZE_HUGE = "Huge"
    SIZE_BIG = "Big"

module_register_class_constants(Animal, "SIZE_")

class Horse(Animal):
    def printSize(self):
        print SIZE_BIG

1 Comment

print SIZE_BIG out of class will be the same? Will it be editable Animal.SIZE_HUGE = 'Small'?
1

You can also use an Enum to achieve constants:

from enum import Enum, IntEnum

class MyEnumA(Enum):
    A = "A"
    B = "B"
    C = "C"
    D = "D"
    E = "E"

class MyEnumB(IntEnum):
    A = 0
    B = 1
    C = 2
    D = 3
    E = 4

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.