MyPython-->进阶篇-->使用枚举类 元类

当我们需要定义常量时,一个办法是用大写变量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的情况所以下内容看不到也没关系,因为基本你不会用到

 

posted @ 2016-09-15 23:28  notJoke  阅读(562)  评论(0编辑  收藏  举报