Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python 2.x - creating static instance of class in same class

I am trying to write an "enum class" in python. A slight nuisance I am currently experiencing is the inability to define enum values inside the enum class. That is, I can do this:

class Fruit:
    def __init__(self, name):
        self.name = name

class Fruits(Enum):
    Apple = Fruit("apple")

But I would like to do this, or a similarly legible equivalent:

class Fruit(Enum):
    def __init__(self, name):
        self.name = name

    Apple = Fruit("apple")

Unfortunately, I am getting the following error: name 'Fruit' is not defined

What are the rules of visibility in such a case? Are there any little-known Python tricks that could help me? I would prefer something that is possible to write in the metaclass of Enum, since that would make usage less cumbersome for the user.

like image 576
Liosan Avatar asked Apr 30 '13 11:04

Liosan


1 Answers

You could make a metaclass that did something simple like this:

class MetaEnum(type):
    def __new__(cls, class_name, parents, attrs):
        def __init__(self, name=None):
            if name is not None: self.name = name
        attrs['__init__'] = __init__
        Klass = type.__new__(cls, class_name, parents, attrs)
        if 'instances' in attrs:
            for name in attrs['instances']:
                setattr(Klass, name.capitalize(), Klass(name))
            del Klass.instances # clean up
        return Klass

class Fruit(object):
    __metaclass__ = MetaEnum
    instances = ('apple', 'banana', 'cranberry')

for attr_name in dir(Fruit):
    if not attr_name.startswith('_'):
        attr = getattr(Fruit, attr_name)
        if type(attr) is Fruit:
            print('Fruit.{}, is a Fruit named {}'.format(attr_name, getattr(attr, 'name')))
        else:
            print('Fruit.{}, is a {}'.format(attr, type(attr)))

Output:

Fruit.Apple, is a Fruit named apple
Fruit.Banana, is a Fruit named banana
Fruit.Cranberry, is a Fruit named cranberry
like image 92
martineau Avatar answered Oct 21 '22 17:10

martineau