一、枚举其实是一个类

现实世界中的“类型”,在计算机世界中如何描述?

常见的

1)用1、2、3..等数字表示类型

2)较好的做法是用字典表示

3)最好的是使用枚举

 # coding=utf-8
from enum import Enum class VIP(Enum): # 继承Enum类
YELLOW = 1 # 枚举类型建议使用大小
GREEN = 2
BLACK = 3
RED = 4 print(VIP.YELLOW)

1、python中,枚举的本质是类

2、使用时需要继承Enum类

3、类中定义一组常量,建议使用全大写字母表示

4、数字1、2、3其实没有意义,枚举的意义重在标识,不在取值。

二、枚举与普通类相比的优势

如果不使用枚举,如何表示类型

1)使用模块中的全局变量

yellow=1

green=2

2) 字典

{‘yellow’:1,'green':2}

3) 普通类

class TypeDiamond():

  yellow=1

  green=2

缺点:

1)可变,即可以在代码中轻易改变

2)没有防止相同标签的功能

现实中的‘类型’一旦定义不应该被轻易更改,但字典可以通过赋值改变类型,同样普通类也可以轻易改变类型。

字典和普通类允许变量(类型)相同

{‘yellow’:1,'yellow:2}

在python中没有真正的常量,在枚举中定义的类型不能被更改,且不能取相同的标记。

1)枚举的保护性

2)枚举的防重性

三、枚举类型、枚举名称与枚举值

1、获取某个枚举标签的值.value

2、获取某个枚举标签的名字.name

3、通过枚举标签的名称获取枚举的类型

4、枚举可遍历

 # 获取枚举标签的值
print(VIP.YELLOW.value)
# 获取枚举标签的名字
print(VIP.YELLOW.name)
# 获取枚举类型
print(VIP.YELLOW)
for v in VIP:
print(v)

1                           枚举值
YELLOW              枚举名称
VIP.YELLOW   枚举类型

四、枚举之间的比较

枚举支持的比较

1)等值比较

res=VIP.YELLOW==VIP.GREEN
print(res) 打印结果:False

2)身份比较

res=VIP.YELLOW is VIP.YELLOW
print(res)
打印结果:True

枚举不支持的比较

1)名称和值的比较

class VIP(Enum):
YELLOW = 1 # 枚举类型建议使用大小
GREEN = 2
BLACK = 3
RED = 4 res=VIP.YELLOW ==1
print(res)
打印结果:False

2)大小比较

res=VIP.YELLOW <VIP.GREEN
print(res)

报错:TypeError: '<' not supported between instances of 'VIP' and 'VIP'

3)枚举类之间的比较

class VIP(Enum):
YELLOW = 1 # 枚举类型建议使用大小
GREEN = 2
BLACK = 3
RED = 4 class VIP1(Enum):
YELLOW = 1 # 枚举类型建议使用大小
GREEN = 2
BLACK = 3
RED = 4 res=VIP.YELLOW ==VIP1.YELLOW
print(res)
打印结果:False

五、枚举注意事项
1、不能使用相同的标签
2、取值可以相同,但会作为别名,不能作为独立的枚举类型
3、枚举的遍历,取值相等时,不打印(无法访问)别名
 # coding=utf-8
from enum import Enum class VIP(Enum):
YELLOW = 1 # 枚举类型建议使用大小
YELLOW2 = 1
BLACK = 3
RED = 4 for v in VIP:
print(v)

4、如何遍历(访问)别名?VIP.__members__
 
 # coding=utf-8
from enum import Enum class VIP(Enum):
YELLOW = 1 # 枚举类型建议使用大小
YELLOW2 = 1
BLACK = 3
RED = 4 for v in VIP.__members__:
print(v)

六、枚举的转换

1、将枚举类型转化为数字

实际编码过程中,推荐:在代码中定义枚举类型,数据库中存储枚举值,通过枚举名称访问数据库中的枚举值

if a==VIP.YELLOW:#不推荐使用a==1

  print(...)

if a==VIP.GREEN:#不推荐使用a==2

  print(...)

2、将数字转化为枚举类型

a=1

print(VIP(a))

 # coding=utf-8
from enum import Enum class VIP(Enum):
YELLOW = 1 # 枚举类型建议使用大小
YELLOW2 = 1
BLACK = 3
RED = 4 a=1
print(VIP(a))

七、枚举小结

1、IntEunm类

枚举值可以是int类型,也可以是str类型,如果明确了是int类型,可以使用IntEunm类,该类限制了枚举值只能是int

 #coding=utf-8
from enum import IntEnum class VIP(IntEnum):
YELLOW = 'a' # 枚举类型建议使用大小
YELLOW2 = 1
BLACK = 3
RED = 4

2、限制别名(不能取相同值)

 #coding=utf-8
from enum import IntEnum,unique @unique
class VIP(IntEnum):
YELLOW = 1 # 枚举类型建议使用大小
YELLOW2 = 1
BLACK = 3
RED = 4

3、枚举在python中是单例模式,不能实例化

这里引入了设计模式的概念,其中单例模式是23种设计模式中的一种。

八、函数式编程、闭包导论

1、python支持函数式编程,该用的时候用

2、概念不重要,重要的是思维

3、函数:其他语言中函数是指一段可执行的代码,并不是对象,但在python中,函数就是对象,可实例化

#coding=utf-8

def a():
pass print(type(a))


python:一切皆对象

那么

  • 函数可以赋值给变量
  • 函数可作为另一个函数的参数
  • 函数可作为另一个函数的返回结果

九、什么是闭包

闭包=函数+环境变量

环境变量:函数定义时用到的变量(在函数外)

 # coding=utf-8

 def curve_pre():  # 闭包
a = 25 # 环境变量 def curve(x): # 函数
return a * x * x #引用环境变量a return curve # 返回函数 f = curve_pre()
print(f(2))

结果:100

对a重新赋值,结果如何?

 # coding=utf-8

 def curve_pre():  # 闭包
a = 25 # 环境变量 def curve(x): # 函数
return a * x * x #引用环境变量a return curve # 返回函数 a=10
f=curve_pre()
print(f(2))

结果仍然是:100

如何获取环境变量的值25

 # coding=utf-8

 def curve_pre():  # 闭包
a = 25 # 环境变量 def curve(x): # 函数
return a * x * x #引用环境变量a return curve # 返回函数 f = curve_pre()
#获取环境变量的值
print(f.__closure__[0].cell_contents)

十、一个事例看闭包

闭包的意义:保存环境,现场

局部变量不影响外部的环境变量

 # coding=utf-8

 def f1():
a = 10 def f2():
a = 20
print(a) print(a)
f2()
print(a) f1()

打印结果:

10
20
10

十一、闭包的经典误区

代码1

 #coding=utf-8

 def f1():
a=10
def f2():
a=20 #a出现在表达式的作为,会被当做局部变量 f=f1()
print(f.__closure__)

打印结果:

Traceback (most recent call last):
  File "E:/pyClass/eleven/c11.py", line 9, in <module>
    print(f.__closure__)
AttributeError: 'NoneType' object has no attribute '__closure__'

原因:

f1()不是闭包,因为没有返回?

代码2:加入返回

 # coding=utf-8

 def f1():
a = 10 def f2():
a = 20 # a出现在表达式的作为,会被当做局部变量 return f2 f = f1()
print(f.__closure__)

打印结果:None

原因:函数f2没有返回?

代码3:在f2中增加返回

 # coding=utf-8

 def f1():
a = 10 def f2():
a = 20 # a出现在表达式的作为,会被当做局部变量
return a
return f2 f = f1()
print(f.__closure__)

打印结果:None

原因:f2中没有引用环境变量

代码4

 # coding=utf-8

 def f1():
a = 10 def f2():
# a = 20 # a出现在表达式的作为,会被当做局部变量
return a
return f2 f = f1()
print(f.__closure__)

打印结果:(<cell at 0x00000000006CA5E8: int object at 0x000000001DCEB560>,)

总结

1)环境变量不能作为局部变量被赋值

2)需要返回函数

3)函数需要引用环境变量

十二、几个问题,用闭包解决

问题:计算旅行者当前位置,假设起点x=0,每走一步,x+1

问题关键:保存上次结果

起点:x=0

每走一步:x+1

3步:result=3

5步:result=8

6步:result=14

方法一:非闭包

 #coding=utf-8

 origin=0

 def go(step):
new_pos=origin+step
origin=new_pos
return origin print(go(2))
print(go(3))
print(go(5))

报错信息:

Traceback (most recent call last):
  File "E:/pyClass/eleven/c12.py", line 10, in <module>
    print(go(2))
  File "E:/pyClass/eleven/c12.py", line 6, in go
    new_pos=origin+step
UnboundLocalError: local variable 'origin' referenced before assignment

原因:第7行中,origin出现在表达式左边,会被认为是局部变量,局部变量在6行中没有定义就使用,系统认为是错误的

尝试解决:

注释掉第7行,不再报错,但是打印结果

0

0

0

与预期不符

最终解决:使用global关键字,声明origin为全局变量

 #coding=utf-8

 origin=0
def go(step):
global origin
new_pos=origin+step
origin=new_pos
return origin print(go(2))
print(go(3))
print(go(5))

打印结果

2
5
10
方法二:使用闭包

 # coding=utf-8

 origin = 0

 def factory(pos):
def go(step):
nonlocal pos # 声明pos非局部变量
new_pos = pos + step
pos = new_pos
return pos return go tourist = factory(origin)
print("旅行者当前位置:%s" % (tourist(2)))
print("origin变量的值:%s" % (origin))
print("环境变量的值:%s" % (tourist.__closure__[0].cell_contents))
print("旅行者当前位置:%s" % (tourist(3)))
print("origin变量的值:%s" % (origin))
print("环境变量的值:%s" % (tourist.__closure__[0].cell_contents))
print("旅行者当前位置:%s" % (tourist(5)))
print("origin变量的值:%s" % (origin))
print("环境变量的值:%s" % (tourist.__closure__[0].cell_contents))

打印结果:

旅行者当前位置:2
origin变量的值:0
环境变量的值:2
旅行者当前位置:5
origin变量的值:0
环境变量的值:5
旅行者当前位置:10
origin变量的值:0
环境变量的值:10
总结

1)origin并没有被改变

2)pos环境变量被记住

												

十一、python的高级语法与用法的更多相关文章

  1. Python(九) Python的高级语法与用法

    本章节我们揭开Python进阶部分的高级特性,详细讲解枚举.闭包,并对函数式编程做出介绍 一. 枚举其实是一个类 from enum import Enum #枚举类 class VIP(Enum): ...

  2. 12.Python的高级语法和用法

    # from enum import Enum # 枚举 # class VIP(Enum): # YELLOW = # YELLOW_ALIAS = # 别名 # GREEN = # BLACK = ...

  3. python 类高级语法 静态方法

    通过@staticmethod装饰器即可把其装饰的方法变为一个静态方法,什么是静态方法呢?其实不难理解,普通的方法,可以在实例化后直接调用,并且在方法里可以通过self.调用实例变量或类变量,但静态方 ...

  4. Python自动化 【第七篇】:Python基础-面向对象高级语法、异常处理、Scoket开发基础

    本节内容: 1.     面向对象高级语法部分 1.1   静态方法.类方法.属性方法 1.2   类的特殊方法 1.3   反射 2.     异常处理 3.     Socket开发基础 1.   ...

  5. Python高级语法之:一篇文章了解yield与Generator生成器

    Python高级语法中,由一个yield关键词生成的generator生成器,是精髓中的精髓.它虽然比装饰器.魔法方法更难懂,但是它强大到我们难以想象的地步:小到简单的for loop循环,大到代替多 ...

  6. python 循环高级用法 [expression for x in X [if condition] for y in Y [if condition] ... for n in N [if condition] ]按照从左至右的顺序,分别是外层循环到内层循环

    高级语法 除了像上面介绍的 [x ** 2 for x in L] 这种基本语法之外,列表推导式还有一些高级的扩展. 4.1. 带有if语句 我们可以在 for 语句后面跟上一个 if 判断语句,用于 ...

  7. 从一知半解到揭晓Java高级语法—泛型

    目录 前言 探讨 泛型解决了什么问题? 扩展 引入泛型 什么是泛型? 泛型类 泛型接口 泛型方法 类型擦除 擦除的问题 边界 通配符 上界通配符 下界通配符 通配符和向上转型 泛型约束 实践总结 泛型 ...

  8. 进击的Python【第七章】:Python的高级应用(四)面向对象编程进阶

    Python的高级应用(三)面向对象编程进阶 本章学习要点: 面向对象高级语法部分 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 一.面向对象高级语法部分 静态方法 ...

  9. 进击的Python【第六章】:Python的高级应用(三)面向对象编程

    Python的高级应用(三)面向对象编程 本章学习要点: 面向对象编程介绍 面向对象与面向过程编程的区别 为什么要用面向对象编程思想 面向对象的相关概念 一.面向对象编程介绍 面向对象程序设计(英语: ...

随机推荐

  1. 窥探 Swift 之别具一格的 Struct 和 Class

    说到结构体和类,还是那句话,只要是接触过编程的小伙伴们对这两者并不陌生.但在Swift中的Struct和Class也有着令人眼前一亮的特性.Struct的功能变得更为强大,Class变的更为灵活.St ...

  2. openstack多region介绍与实践

    版权声明:本文为原创文章,转载请注明出处. 概念介绍 所谓openstack多region,就是多套openstack共享一个keystone和horizon.每个区域一套openstack环境,可以 ...

  3. win10安装tomcat7

    下载Tomcat 安装tomcat tomcat7是绿色软件,解压后即可使用,请大家先将tomcat解压到合适的位置(建议整个路径都是英文路径),下载 apache-tomcat-7.0.79-win ...

  4. python操作cad

    from pyautocad import Autocad # 自動連接上cad,只要cad是開着的,就創建了一個<pyautocad.api.Autocad> 對象.這個對象連接最近打開 ...

  5. UVA 111 简单DP 但是有坑

    题目传送门:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=18201 其实是一道不算难的DP,但是搞了好久,才发现原来是题目没 ...

  6. linux启动全过程

    参考: http://www.staroceans.org/e-book/linux-bootstrap-1.html 1. MBR里的内容属于grub grub-2.02\grub-core\boo ...

  7. DDP入门

    DDP,即动态动态规划,可以用于解决一类带修改的DP问题. 我们从一个比较简单的东西入手,最大子段和. 带修改的最大子段和其实是常规问题了,经典的解决方法是用线段树维护从左,右开始的最大子段和和区间最 ...

  8. 数据结构与算法(5)----->二叉树

    1.  概念 二叉树节点的结构: class Node{ int value; // value表示二叉树的节点值 Node left; Node right; // left和right表示二叉树的 ...

  9. Ubuntu 16.04 LTS 一键安装VNC

    Ubuntu 16.04 LTS 安装VNC,在百度和谷歌找了很多教程,不是太老,就是说的驴唇不对马嘴,所以忍不住写一些以正视听. Ubuntu 16.04 LTS是最近出的LTS版本系统,估计未来也 ...

  10. saltstack syndic安装配置使用

    salt-syndic是做神马的呢?如果大家知道zabbix proxy的话那就可以很容易理解了,syndic的意思为理事,其实如果叫salt-proxy的话那就更好理解了,它就是一层代理,如同zab ...