一、枚举其实是一个类

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

常见的

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. 在datax之前版本中添加filewriter并创建job时出现问题

    问题描述:

  2. BZOJ 1626 [Usaco2007 Dec]Building Roads 修建道路:kruskal(最小生成树)

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1626 题意: 有n个农场,坐标为(x[i],y[i]). 有m条原先就修好的路,连接农场( ...

  3. nodejs && apidoc

    1. 安装nodejs      http://www.nodejs.org      源码编译      configure —prefix=/usr/local/nodejs      make ...

  4. suse enterprise Linux 11上配置 oracle11g和tomcat开机自启动

    一.oracle 11g r2自启动 1.修改/etc/sysconfig/oracle文件: ORACLE_BASE=/oracle  //此处改为你安装的oracle目录 START_ORACLE ...

  5. UOJ_21_【UR #1】缩进优化_数学

    UOJ_21_[UR #1]缩进优化_数学 题面:http://uoj.ac/problem/21 最小化$\sum\limits{i=1}^{n}a[i]/x+a[i]\;mod\;x$ =$\su ...

  6. 【Lintcode】094.Binary Tree Maximum Path Sum

    题目: Given a binary tree, find the maximum path sum. The path may start and end at any node in the tr ...

  7. 【LintCode】060.Search Insert Position

    题目: Given a sorted array and a target value, return the index if the target is found. If not, return ...

  8. 系列文章-- SSIS学习

    SSIS是SQL Server Integraion Services的简称.是生成高性能数据集成解决方案(包括数据仓库的提取.转换和加载 (ETL) 包)的平台.   SSIS组件转换_模糊查找转换 ...

  9. BZOJ3295:[CQOI2011]动态逆序对

    浅谈树状数组与线段树:https://www.cnblogs.com/AKMer/p/9946944.html 题目传送门:https://www.lydsy.com/JudgeOnline/prob ...

  10. AtCoder Regular Contest 068E:Snuke Line

    题目传送门:https://arc068.contest.atcoder.jp/tasks/arc068_c 题目翻译 直线上有\(0-m\)这\(m+1\)个点,一共有\(m\)辆火车.第\(i\) ...