Python的高级语法与用法
一、枚举其实是一个类
from enum import Enum
class VIP(Enum):
YELLOW = 1
GREEN = 2
BLACK = 3
RED = 4
print(VIP.BLACK)
运行结果:
VIP.BLACK
二、枚举和普通类相比有什么优势
1、普通类值可变,枚举值不可变;
2、普通类变量名可相同,且值为最近的一个变量值,枚举变量名不可重复。
from enum import Enum
class Common():
YELLOW = 1
YELLOW = 2
print(Common.YELLOW)
运行结果:
2
class VIP(Enum):
YELLOW = 1
YELLOW = 5
GREEN = 2
BLACK = 3
RED = 4
print(VIP.YELLOW.value)
运行结果:
Traceback (most recent call last):
File "/home/caoxuejin/Project/sample/chapter11/c1.py", line 17, in <module>
class VIP(Enum):
File "/home/caoxuejin/Project/sample/chapter11/c1.py", line 19, in VIP
YELLOW = 5
File "/home/caoxuejin/myEnvs/python37/lib/python3.7/enum.py", line 100, in __setitem__
raise TypeError('Attempted to reuse key: %r' % key)
TypeError: Attempted to reuse key: 'YELLOW'
三、枚举类型、枚举名称和枚举值
1、枚举名称:
from enum import Enum
class VIP(Enum):
YELLOW = 1
GREEN = 2
BLACK = 3
RED = 4
# 枚举名称
print(VIP.YELLOW.name)
运行结果:
YELLOW
2、枚举值:
from enum import Enum
class VIP(Enum):
YELLOW = 1
GREEN = 2
BLACK = 3
RED = 4
# 枚举值
print(VIP.YELLOW.value)
运行结果:
1
3、枚举类型:
from enum import Enum
class VIP(Enum):
YELLOW = 1
GREEN = 2
BLACK = 3
RED = 4
# 枚举类型
print(VIP.YELLOW)
运行结果:
VIP.YELLOW
print(VIP["YELLOW"])
运行结果:
VIP.YELLOW
print(type(VIP.YELLOW))
运行结果:
<enum 'VIP'>
4、枚举遍历:
from enum import Enum
class VIP(Enum):
YELLOW = 1
GREEN = 2
BLACK = 3
RED = 4
# 枚举遍历
for v in VIP:
print(v)
运行结果:
VIP.YELLOW
VIP.GREEN
VIP.BLACK
VIP.RED
四、枚举的比较运算
1、==:
from enum import Enum
class VIP(Enum):
YELLOW = 1
GREEN = 2
BLACK = 3
RED = 4
class VIPS(Enum):
YELLOW = 1
GREEN = 2
BLACK = 3
RED = 4
result = (VIP.YELLOW==VIP.YELLOW)
print(result)
运行结果:
True
result = (VIP.YELLOW==1)
print(result)
运行结果:
False
result = (VIP.YELLOW==VIPS.YELLOW)
print(result)
运行结果:
False
2、is:
from enum import Enum
class VIP(Enum):
YELLOW = 1
GREEN = 2
BLACK = 3
RED = 4
class VIPS(Enum):
YELLOW = 1
GREEN = 2
BLACK = 3
RED = 4
result = (VIP.YELLOW is VIP.YELLOW)
print(result)
运行结果:
True
result = (VIP.YELLOW is 1)
print(result)
运行结果:
False
result = (VIP.YELLOW is VIPS.YELLOW)
print(result)
运行结果:
False
五、枚举注意事项
1、别名:当两个枚举的枚举值相同时,后一个枚举为前一个枚举的别名。
from enum import Enum
class VIP(Enum):
YELLOW = 1
YELLOW_ALIAS = 1 # 别名
GREEN = 2
BLACK = 3
RED = 4
print(VIP.YELLOW)
运行结果:
VIP.YELLOW
print(VIP.YELLOW_ALIAS)
运行结果:
VIP.YELLOW
for v in VIP:
print(v)
运行结果:
VIP.YELLOW
VIP.GREEN
VIP.BLACK
VIP.RED
2、如若需要在遍历的时候把别名遍历出来,有如下两种方式:
(1) 方式一:获取标签名及枚举类型
from enum import Enum
class VIP(Enum):
YELLOW = 1
YELLOW_ALIAS = 1
GREEN = 2
BLACK = 3
RED = 4
for v in VIP.__members__.items():
print(v)
运行结果:
('YELLOW', <VIP.YELLOW: 1>)
('YELLOW_ALIAS', <VIP.YELLOW: 1>)
('GREEN', <VIP.GREEN: 2>)
('BLACK', <VIP.BLACK: 3>)
('RED', <VIP.RED: 4>)
(2) 方式二: 获取标签名
from enum import Enum
class VIP(Enum):
YELLOW = 1
YELLOW_ALIAS = 1
GREEN = 2
BLACK = 3
RED = 4
for v in VIP.__members__:
print(v)
运行结果:
YELLOW
YELLOW_ALIAS
GREEN
BLACK
RED
六、枚举转换
from enum import Enum
class VIP(Enum):
YELLOW = 1
YELLOW_ALIAS = 1
GREEN = 2
BLACK = 3
RED = 4
a = 1
print(VIP(a))
运行结果:
VIP.YELLOW
七、枚举小结
1、当引入父类的枚举类型为IntEnum时,枚举值必须为int类型
from enum import Enum, IntEnum
class VIP(IntEnum):
YELLOW = 1
GREEN = 2
BLACK = 3
RED = "four"
print(VIP.RED)
运行结果:
Traceback (most recent call last):
File "/home/caoxuejin/Project/sample/chapter11/c5.py", line 9, in <module>
class VIP(IntEnum):
File "/home/caoxuejin/myEnvs/python37/lib/python3.7/enum.py", line 217, in __new__
enum_member = __new__(enum_class, *args)
ValueError: invalid literal for int() with base 10: 'four'
class VIP(IntEnum):
YELLOW = 1
GREEN = 2
BLACK = 3
RED = 4
print(VIP.RED)
运行结果:
VIP.RED
2、如若加了@unique装饰器的话,枚举值是不允许相同的
from enum import Enum, IntEnum, unique
@unique
class VIP(IntEnum):
YELLOW = 1
GREEN = 1
BLACK = 3
RED = 4
print(VIP.RED)
运行结果:
Traceback (most recent call last):
File "/home/caoxuejin/Project/sample/chapter11/c5.py", line 10, in <module>
class VIP(IntEnum):
File "/home/caoxuejin/myEnvs/python37/lib/python3.7/enum.py", line 848, in unique
(enumeration, alias_details))
ValueError: duplicate values found in <enum 'VIP'>: GREEN -> YELLOW
九、什么是闭包
1、闭包:在函数嵌套的程序结构中,如果内层函数包含对外层函数局部变量的引用,同时外层函数的返回结果又是对内层函数的引用,这就构成了一个闭包。
2、示例:
(1) 示例一:闭包
def cure_pre():
a = 25
def cure(x):
return a*x*x
return cure
a = 10
f = cure_pre()
print(f.__closure__)
print(f.__closure__[0].cell_contents)
print(f(2))
运行结果:
(<cell at 0x7f6ad5cc4b58: int object at 0x557de53bba60>,)
25
100
(2) 示例二:非闭包
a = 25
def cure_pre():
def cure(x):
return a*x*x
return cure
a = 10
f = cure_pre()
print(f(2))
运行结果:
40
十一、一个示例看看闭包
def f1():
a = 10
def f2():
a = 20
print(a)
print(a)
f2()
print(a)
f1()
运行结果:
10
20
10
十二、闭包的经典误区
1、正确:
def f1():
a = 10
def f2():
# a被python认为是一个局部变量
# a = 25
c = 20 * a
return c
return f2
f = f1()
print(f)
print(f.__closure__)
print(f.__closure__[0].cell_contents)
运行结果:
<function f1.<locals>.f2 at 0x7fe9ca018d90>
(<cell at 0x7fe9ca026b58: int object at 0x55d704956880>,)
10
2、错误:
def f1():
a = 10
def f2():
# a被python认为是一个局部变量
a = 25
c = 20 * a
return c
return f2
f = f1()
print(f)
print(f.__closure__)
print(f.__closure__[0].cell_contents)
运行结果:
<function f1.<locals>.f2 at 0x7f6f56b85d90>
None
File "/home/caoxuejin/Project/sample/chapter11/c9.py", line 21, in <module>
print(f.__closure__[0].cell_contents)
十三、闭包示例
1、非闭包方式:
origin = 0
def go(step):
global origin
new_pos = origin + step
origin = new_pos
return origin
print(go(2))
print(go(3))
print(go(6))
运行结果:
2
5
11
2、闭包方式:
origin = 0
def factory(pos):
def go(step):
nonlocal pos
new_pos = pos + step
pos = new_pos
return pos
return go
tourist = factory(origin)
print(tourist(2))
print(tourist.__closure__[0].cell_contents)
print(tourist(3))
print(tourist.__closure__[0].cell_contents)
print(tourist(6))
print(tourist.__closure__[0].cell_contents)
运行结果:
2
2
5
5
11
11