当我们需要定义常量时,一个办法是用大写变量2通过整数来定义,例如月份
JAN = 1 FEB = 2 MAR = 3
好处是简单,缺点是类型是int,并且仍然是变量
更好的方法是为这样的枚举类型定义一个class类,然后每个常量都是class的一个唯一实例,python提供了Eum类来实现这个功能
from enum import Enum Month = Enum(‘Month‘,(‘Jan‘,‘Feb‘,‘Mar‘,‘Apr‘,‘May‘)) print(Month.May) for name,member in Month.__members__.items(): print(name,‘->‘,member,‘,‘,member.value)
我们可以直接使用Month.May 来引用一个常量,或者枚举它的所有成员
value属性则是自动赋给成员的int常量,默认从1 开始
如果需要更精确的控制枚举类型,可以从Enum派生出自定义类
from enum import Enum,unique @unique class Weekday(Enum): Sun = 0#Sun的value被指定为0 Mon = 1 Tue = 2 Wed = 3 Thu = 4 Fri = 5 Sat = 6
@unique装饰器 可以帮助我们检查保证没有重复的值
访问这些枚举类型有若干种方法
day1 = Weekday.Mon print(day1) print(Weekday.Tue) print(Weekday[‘Thu‘]) print(Weekday.Mon.value) print(day1 == Weekday.Mon) print(day1 == Weekday.Fri) print(Weekday(1)) print(day1 == Weekday.Tue) print(Weekday(1))
使用元类
type()
动态语言和静态语言最大的不同,就是函数和类的定义,不是编译时的定义,而是运行时动态创建的
比如我们要定义一个hello的class ,就写一个hello.py的模块
class Hello(object): def hello(self,name = ‘world‘): print(‘Hello %s ‘%name)
当python解释器载入hello模块时,就会依次执行该模块的所有语句,执行结构就是动态的创建出一个Hello的class对象
from hello import Hello h1 = Hello() h1.hello()print(type(Hello)) print(type(h1))
<class ‘type‘> <class ‘hello.Hello‘>
type()函数可以查看一个类型或变量的类型,Hello是一个class,他的类型就是type,而h1是一个实例,他的类型就是clas Hello
我们说class的定义是运行时动态创建的,而创建class的方法就是type()函数
type()函数既可以返回一个对象的类型,又可以创建出新的类型,比如,我们可以通过type()函数创建出Hellp类,而无需通过class Hello(object)....的定义
def fn(self,name=‘world‘): print(‘hello, %s.‘ % name) Hello = type(‘Hello‘, (object,), dict(hello = fn)) h = Hello() h.hello()#hello, world. print(type(Hello))#<class ‘type‘> print(type(h))#<class ‘__main__.Hello‘>
要创建一个class对象,type()函数一次传入3个参数
1.class的名称
2.继承的父类集合,注意python支持多重继承,如果只有一个弗雷,别忘了tuple的单元素写法 ,
3.class的方法名称与函数绑定,这里我们直接把函数fn绑定到方法名hello上
通过type()函数创建的类和直接写class是完全一样的,因为python解释器遇到class定义时,仅仅是扫描一下class定义的语法,然后调用type()函数创建出一个class
正常情况下,我们都用class Xxx...
来定义类,但是,type()
函数也允许我们动态创建出类来,也就是说,动态语言本身支持运行期动态创建类,这和静态语言有非常大的不同,要在静态语言运行期创建类,必须构造源代码字符串再调用编译器,或者借助一些工具生成字节码实现,本质上都是动态编译,会非常复杂。
metaclass
除了使用type()动态创建类以外,要控制类的创建行为,还而已使用metaclass,质疑为元类
当我们定义了类以后,就可以根据这个类创建实例,所以先定义类,然后创建实例
但是如果我们想创建出类呢?那就必须根据metaclass,就可以创建类,最后创建实例
所以,metaclass运行你创建类和修改类。换句话说你可以把类看城市metaclass创建出来的实例
metaclass是python 面向对象最难理解,也是最难是用的魔术代码。正常情况下,你不会碰到需要使用metaclass的情况所以下内容看不到也没关系,因为基本你不会用到