一、枚举其实是一个类

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

常见的

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. centos下更换默认的python版本

    1.在命令行输入python查看版本 2.到官网下载自己的python版本 wget https://www.python.org/ftp/python/3.5.1/Python-3.5.1.tgz ...

  2. Maven简介(六)——Dependency

    7      Dependency介绍 http://elim.iteye.com/category/269897 7.1     依赖的传递性 当项目A依赖于B,而B又依赖于C的时候,自然的A会依赖 ...

  3. 使用valgrind进行内存泄漏和非法内存操作检测

    valgrind是一个强大的工具,最常用的功能是用它来检测内存泄漏和非法内存的使用.要想让valgrind报告的更加细致,请使用-g进行编译. 基本命令如下: $ valgrind --tool=me ...

  4. poj 3268 Silver Cow Party (最短路算法的变换使用 【有向图的最短路应用】 )

    Silver Cow Party Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 13611   Accepted: 6138 ...

  5. Python成长之路第一篇(2)__初识列表和元组

    可以将列表和元组当成普通的“数组”,他能保存任意数量任意类型的Python对象,和数组一样都是通过数字0索引访问元素,列表和元组可以存储不同类型的对象,列表和元组有几处重要区别.列表元素用([])包括 ...

  6. cad定制快捷键

    1.工具-自定义-编辑程序参数,改好之后,关闭. 2.在命令行输入:reinit-选择PGP文件-确定.

  7. matlab之细胞数组

    学习matlab的一个博客:https://blog.csdn.net/smf0504/article/details/51814362 Matlab从5.0版开始引入了一种新的数据类型—细胞( ce ...

  8. legend2---开发日志15(功能需求明确,设计好类和结构的好处是)

    legend2---开发日志15(功能需求明确,设计好类和结构的好处是) 一.总结 一句话总结: 极快简化编程,节约大量时间 1.多个类型的物品,比如商店和寻宝的丹药,装备,特性书,英雄石等等 应该怎 ...

  9. P4311 士兵占领[最大流]

    题目地址 有一个$M * N$的棋盘,有的格子是障碍.现在你要选择一些格子来放置一些士兵,一个格子里最多可以放置一个士兵,障碍格里不能放置士兵.我们称这些士兵占领了整个棋盘当满足第i行至少放置了$L_ ...

  10. 【Lintcode】011.Search Range in Binary Search Tree

    题目: Given two values k1 and k2 (where k1 < k2) and a root pointer to a Binary Search Tree. Find a ...