Use of Python metaclass II - Python Enumeration

本文介绍两种使用Python元类实现枚举的方法。第一种方法通过定义元类和枚举函数来创建枚举类;第二种方法则定义了一个带有特殊元类的Animal类,该元类重写了__getattr__方法以返回枚举成员的索引。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

In my previous post, I disussesed with the reader the concept of metaclass and its internals. and in following post one usage of the python metaclass is discussed. Today another use of the metaclass will be discussed.

 

As a note, this article is inspired from this original post from stackoverflow.

 

Problem with Python and Enumeration

python does not have internal keyword for enumeration, however, with the help of metaclass and dictionary, you can create your own enuemration.

 

 

let's see two impl, one is with a enum method by which you can further create any enumeration class.

 

 

First impl: enum meta method to create enumeration classes

 

 

 

The impl 

 

# define the __metaclass__ function
def M_add_class_attr(attribs):
    def foo(name, bases, dict_):
        for v, k in attribs:
            dict_[k] = v
        return type(name, bases, dict_)
    return foo

def enum(names):
    class Foo(object):
        __metaclass__ = M_add_class_attr(enumerate(names))
    def __setattr__(self, name, value): # this make it readonly
        raise NotImplementedError
    return Foo()
 

 

 

the test code 

 

 

import unittest

from MetaClass.EnumImpl1 import M_add_class_attr, enum
class Test(unittest.TestCase):


    def test_enumImpl1_usage_example(self):
        Animal = enum(['DOG', 'CAT'])
        self.assertEqual(0, Animal.DOG)
        self.assertEqual(1, Animal.CAT)
        


if __name__ == "__main__":
    #import sys;sys.argv = ['', 'Test.test_enumImpl1_usage_example']
    unittest.main()
 

 

Second impl:  Enumeration Class with Symbol name

In this example, we are still going to create a animal enumeration class, and we want Animal to be a symbol rather than a variable where the client is able to reassign to.

 

 

the impl

 

class Animal(object):
    
    values = ["Horse", "Dog", "Cat"]
    
    # this is a very neat implementation
    # where you define a __metaclass__ method that 
    # has the __getattr__ override to return the index of the constants
    # that you have defined in class instance 'values'  

    class __metaclass__(type):
        def __getattr__(self, name):
            return self.values.index(name)
    
    # the above is equivalent as writting as follow.
#    class Animal_Metaclass(type):
#        def __getattr__(self, name):
#            return self.values.index(name)
#    __metaclass__ = Animal_Metaclass
 

 

the test code 

 

import unittest
from MetaClass.EnumImpl2 import Animal

class Test(unittest.TestCase):

    # though the syntax is not well recognized by the Eclispe IDE, the function works 
    # perfectly well.
    def test_enumImpl2_usage(self):
#        print Animal.Horse
        self.assertEqual(0, Animal.Horse)
        self.assertEqual(1, Animal.Dog)
        self.assertEqual(2, Animal.Cat)


if __name__ == "__main__":
    #import sys;sys.argv = ['', 'Test.test_enumImpl2_usage']
    unittest.main()
 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值