0

I have the following code:

class Car: def __init__(self, id_): self.id = id_ class Train: def __init__(self, id_): self.id = id_ class TransportKind(Enum): One = Car Two = Train class Transport: def __init__(self, transport_kind: TransportKind, other_value: int): self.transport_kind = transport_kind self.other_value = other_value 

Now I want to construct a Transport:

ts = Transport(transport_kind=TransportKind.One(id=5), other_value=2) 

However this is not valid, since an Enum value cannot be constructed (TypeError: 'TransportKind' object is not callable)

How can I construct a TransportKind value?

3
  • car : Car does nothing, it doesn't create a class attribute. Creating class attributes is done with car = ... - but I'm not really sure of what you are really trying to achieve here... Commented Dec 7, 2020 at 11:55
  • @ThierryLathuille Typo mb, I updated my post. Commented Dec 7, 2020 at 12:02
  • you might be after an abstract factory pattern that returns a car/train factory based on the enum which in turn will create a car or train or such - but its qutie unclear to me what you aim at Commented Dec 7, 2020 at 12:29

2 Answers 2

3

Enum types (in other languages as well as Python) generally aren't meant to be made such that the type itself has data. I'm also confused, because traditionally, you don't want the enum type's name to be obscured. An enum is for classification amongst a discrete set of types/attributes. Traditionally, you would have a solution like the following:

from enum import Enum class TransportKind(Enum): Car = 1 Train = 2 class Transport(object): def __init__(self, transport_kind: TransportKind, other_value: int, **extra_data): self.transport_kind = transport_kind self.other_value = other_value for k, v in extra_data.items(): setattr(self, k, v) ... ts = Transport(transport_kind=TransportKind.Car, other_value=2, id=5) 

And somewhere, whereever relevant, you'd dispatch depending on ts.transport_kind to have different behavior and different expected attributes.

That said, an even more traditional-such approach is simply object-oriented programming:

class Transport(object): def __init__(self, id: int, other_value: int): self.id = id self.other_value = other_value class Car(Transport): pass class Train(Transport): pass ... ts = Car(other_value=2, id=5) 

Then later on use dispatching (dynamic, double using the visitor pattern, or even just a simple instanceof check) based on the class itself.

If you are so dead-set on doing things the way you propose, it would involve subclassing Enum or even subclassing the internal EnumMeta and altering its behavior, which gets very messy very quickly.

E: Fixed an assumption I made in the second example

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

Comments

0

You want to access the value of your enumeration member (see this part of the documentation):

ts = Transport(transport_kind=TransportKind.One.value(id_=5), other_value=2) print(ts) # <__main__.Transport object at 0x7f247f0e88b0> 

But this looks like a strange use of enums anyway...

1 Comment

Accessing the value in this manner loses the behavior of the enum (classification to discrete type) because the transport_kind member is no longer of that enum, but an instance of that enum's value.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.