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

被折叠的 条评论
为什么被折叠?



