[关闭]
@yanglt7 2018-12-03T07:55:10.000000Z 字数 2495 阅读 594

Python21_使用枚举类和元类

Python


使用枚举类

为这样的枚举类型定义一个 class 类型,然后,每个常量都是 class 的一个唯一实例。Python 提供了 Enum 类来实现这个功能:

  1. >>> from enum import Enum
  2. >>> Month=Enum('Month',('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'))
  3. >>> for name,member in Month.__members__.items():
  4. ... print(name,'=>',member,',',member.value)
  5. ...
  6. Jan => Month.Jan , 1
  7. Feb => Month.Feb , 2
  8. Mar => Month.Mar , 3
  9. Apr => Month.Apr , 4
  10. May => Month.May , 5
  11. Jun => Month.Jun , 6
  12. Jul => Month.Jul , 7
  13. Aug => Month.Aug , 8
  14. Sep => Month.Sep , 9
  15. Oct => Month.Oct , 10
  16. Nov => Month.Nov , 11
  17. Dec => Month.Dec , 12

如果需要更精确地控制枚举类型,可以从 Enum 派生出自定义类:

  1. from enum import Enum, unique
  2. @unique
  3. class Weekday(Enum):
  4. Sun = 0 # Sun 的 value 被设定为 0
  5. Mon = 1
  6. Tue = 2
  7. Wed = 3
  8. Thu = 4
  9. Fri = 5
  10. Sat = 6

访问这些枚举类型可以有若干种方法:

  1. >>> day1 = Weekday.Mon
  2. >>> print(day1)
  3. Weekday.Mon
  4. >>> print(Weekday.Tue)
  5. Weekday.Tue
  6. >>> print(Weekday['Tue'])
  7. Weekday.Tue
  8. >>> print(Weekday.Tue.value)
  9. 2
  10. >>> print(day1 == Weekday.Mon)
  11. True
  12. >>> print(day1 == Weekday.Tue)
  13. False
  14. >>> print(Weekday(1))
  15. Weekday.Mon
  16. >>> print(day1 == Weekday(1))
  17. True
  18. >>> Weekday(7)
  19. Traceback (most recent call last):
  20. ...
  21. ValueError: 7 is not a valid Weekday
  22. >>> for name, member in Weekday.__members__.items():
  23. ... print(name, '=>', member)
  24. ...
  25. Sun => Weekday.Sun
  26. Mon => Weekday.Mon
  27. Tue => Weekday.Tue
  28. Wed => Weekday.Wed
  29. Thu => Weekday.Thu
  30. Fri => Weekday.Fri
  31. Sat => Weekday.Sat

使用元类

type()

要定义一个 Hello 的 class,就写一个 hello.py 模块:执行结果就是动态创建出一个 Hello 的 class 对象,测试如下:

  1. >>> class Hello(object):
  2. ... def hello(self,name='world'):
  3. ... print('Hello,%s.' % name)
  4. ...
  5. >>> from hello import Hello
  6. >>> h=Hello()
  7. >>> h.hello()
  8. Hello,world.
  9. >>> print(type(Hello))
  10. <class 'type'>
  11. >>> print(type(h))
  12. <class '__main__.Hello'>

type() 函数可以查看一个类型或变量的类型,Hello 是一个 class,它的类型就是 type,而 h 是一个实例,它的类型就是 class Hello。

type() 函数既可以返回一个对象的类型,又可以创建出新的类型,比如,我们可以通过 type() 函数创建出 Hello 类,而无需通过 class Hello(object)... 的定义:

  1. >>> def fn(self,name='world'):
  2. ... print('Hello,%s.' % name)
  3. ...
  4. >>> Hello=type('Hello',(object,),dict(hello=fn))
  5. >>> h=Hello()
  6. >>> h.hello()
  7. Hello,world.
  8. >>> print(type(Hello))
  9. <class 'type'>
  10. >>> print(type(h))
  11. <class '__main__.Hello'>

要创建一个 class 对象,type() 函数依次传入3个参数:

class的名称;

继承的父类集合,注意 Python 支持多重继承,如果只有一个父类,别忘了 tuple 的单元素写法;

class 的方法名称与函数绑定,这里我们把函数 fn 绑定到方法名 hello 上。

metaclass

先定义 metaclass,就可以创建类,最后创建实例。

定义 ListMetaclass,按照默认习惯,metaclass 的类名总是以 Metaclass 结尾,以便清楚地表示这是一个 metaclass:

  1. >>> class ListMetaclass(type):
  2. ... def __new__(cls,name,bases,attrs):
  3. ... attrs['add']=lambda self,value:self.append(value)
  4. ... return type.__new__(cls,name,bases,attrs)
  5. ...

有了 ListMetaclass,我们在定义类的时候还要指示使用 ListMetaclass 来定制类,传入关键字参数 metaclass:

  1. >>> class MyList(list,metaclass=ListMetaclass):
  2. ... pass

__new__() 方法接收到的参数依次是:

当前准备创建的类的对象;

类的名字;

类继承的父类集合;

类的方法集合。

测试一下 MyList 是否可以调用 add() 方法:

  1. >>> L=MyList()
  2. >>> L.add(1)
  3. >>> L
  4. [1]
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注