枚举其实是一个类
from enum import Enum
class VIP(Enum):
YELLOW = 1
GREEN = 2
BLACK = 3
RED = 4
print(VIP.YELLOW) # -> VIP.YELLOW
枚举的意义是其名字 而不是其数值
枚举类和普通类相比有什么优势
表示一连串类型的方法:
1.普通的类和字典第一个缺陷是,没有防止改变的机制。
2.没有防止相同标签的功能
枚举类型、枚举名称与枚举值:
通过type函数查看
print(type(VIP.GREEN.name)) # 枚举的名字
print(type(VIP.GREEN)) # 枚举的类
print(type(VIP["GREEN"])) # 枚举的类
枚举类可以遍历
廖雪峰--枚举类
枚举的比较运算
result = VIP.GREEN
assert result != VIP.BLACK, "false"
assert result is VIP.GREEN, "false"
枚举可以进行相等与不等比较,不能进行大小比较。
可以 is 比较。身份比较
对于不同的枚举类,即使名字和值一样,也不相等。属于不同类
枚举注意事项
1.枚举下不能有相同的标签
2.枚举下可以有相同的值,那么第一个类型之后的相同值的名字是第一个类型的别名!!!枚举类有装饰器@unique检查保证不重复(相同值)
from enum import Enum # unique
# @unique
class VIP(Enum):
YELLOW = 1
GREEN = 2
BLACK = 2
RED = 4
print(VIP.YELLOW)
print(type(VIP.GREEN.name))
print(type(VIP.GREEN))
print(type(VIP["GREEN"]))
result = VIP.GREEN
assert result == VIP.BLACK, "false" # 由于重复的赋值,导致两个成员值相等,并且调用BLACK返回的名字会是GREEN
assert result is VIP.GREEN, "false"
for v in VIP: # 没有BLACK
print(v)
for v in VIP.__members__: # 有BLACK
print(v)
很有意思,感觉有一定的实用价值。
枚举转换
推荐存储类型的方法:存储数字,采用枚举类来解析所存储的数字。能增加代码的可读性。
通过数字读取枚举类的方法 -> print(VIP(1))
枚举小结:
Enum值可以是字符串,如果需要强制是整数,需要用到IntEnum
枚举类用装饰器@unique检查保证不重复(相同值?)
采用的是单例模式,所以无法实例化 -> 猜到了
23种设计模式
进阶内容开场白
高阶知识用在编程哪些方面:
包、类库的开发者。
一切皆对象
函数式编程
如果用类写代码写的很繁琐,别扭,就可以考虑函数式编程
闭包的概念
廖雪峰--闭包--封装
可以把一个函数作为另一个函数的参数传递进去
也可以把一个函数作为另一个函数的返回结果。
个人认识:主要看一个函数的运行结果是关于函数的引用还是关于函数的调用。
什么是闭包
个人认识:就是初次运行函数并不返回运行值,而是返回一个可调用的对象,在此调用就会返回运行值。
# 最简单的闭包
# 返回闭包时牢记一点:返回函数不要引用任何循环变量,或者后续会发生变化的变量。
def curve_pre():
a = 25
def curve(x):
y = a * x ^ 2 + x
return y
return curve
re = curve_pre()
print(re) # .curve at 0x7f73b9e27158>
print(re.__closure__) # 闭包的参数对象
print(re.__closure__[0].cell_contents) # 返回闭包的参数
print(re(2))
闭包需要调用到函数的局部变量,否则闭包意义不大。
返回闭包时牢记一点:返回函数不要引用任何循环变量,或者后续会发生变化的变量。
一个事例看闭包
闭包 = 函数 + 环境的变量(局部变量)
闭包的意义:保存的是一个环境 -> 不可调用后续发生变化的值。(最好是调用局部变量)
需要注意的地方:
def f1():
a = 10
def f2():
a = 20
print(a)
print(a)
f2()
print(a)
f1() # 返回 10 20 10
闭包的经典误区
def f1():
a = 10
def f2():
a = 20 # 闭包内部不能定义局部变量 可以采用 a = a + 10 的方式引用外部变量
return a
return f2
f = f1()
print(f)
print(f.__closure__) # 返回None,一旦函数的内部定义赋值了局部变量,将不再形成闭包,必须引用外部变量!!!
出个题,用闭包解决
我先用非闭包解决一下
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))
再用闭包解决一下
origin = 0
def factory(pos):
def move(step):
nonlocal pos
new_pos = pos + step
pos = new_pos
return new_pos
return move
f = factory(origin)
print(f(2))
print(f(3))
print(f(8))
自封闭性,没有取改变全局变量的值。而是自己保存上次执行完成之后的环境的变量,将变量的改变局限在函数内部。
闭包
如果用类,类变量就能解决此问题。
小谈函数式编程
factory : 工厂模式
python的闭包强调的是保存环境变量
javascript的闭包强调的是函数外部访问函数内部的变量
由于闭包产生的函数以及变量是常驻内存,容易导致内存泄漏。