一、枚举其实是一个类

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

常见的

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. oracle 数据库常用数据表操作

    在oracle中创建sequence CREATE SEQUENCE sequence名称 MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCRE ...

  2. Android Weekly Notes Issue #255

    Android Weekly Issue #255 April 30th, 2017 Android Weekly Issue #255 本期内容包括: 一种在RxJava中显示loading/con ...

  3. Mac OS访问Windows共享文件夹

    原文地址:http://blog.csdn.net/jinhill/article/details/7246922 最近开始研究Mac OS,遇到的第一个问题就是如何在Mac OS中访问Windows ...

  4. Spring Boot2.0之性能优化

    1.JVM参数调优   针对运行效果  吞吐量    初始堆内存与最大堆尽量相同   减少垃圾回收次数  2.扫包优化: 启动优化 默认Tomcat容器改为Undertow Tomcat的吞吐量500 ...

  5. Spark- Spark Yarn模式下跑yarn-client无法初始化SparkConext,Over usage of virtual memory

    在spark yarn模式下跑yarn-client时出现无法初始化SparkContext错误. // :: INFO mapreduce.Job: Task Id : attempt_142829 ...

  6. matlab字符串链接的三种方式

    1.fprintf()函数: a='I love you,'; b='China'; c=123; fprintf('%s%s\n',a,b); fprintf('%s%s*****%d\n',a,b ...

  7. 使用C语言解析URL

    1. [代码]容易写成自己输入URL,这里测试一个例子     #include <stdio.h>#include <stdlib.h>#include <string ...

  8. POJ 2409 Let it Bead:置换群 Polya定理

    题目链接:http://poj.org/problem?id=2409 题意: 有一串n个珠子穿起来的项链,你有k种颜色来给每一个珠子染色. 问你染色后有多少种不同的项链. 注:“不同”的概念是指无论 ...

  9. struts2 自定义类型转化 第三弹

    1.Struts2的类型转化,对于8种原生数据类型以及Date,String等常见类型,Struts2可以使用内建的类型转化器实现自动转化:但对于自定义的对象类型来说,就需要我们自己指定类型转化的的方 ...

  10. html5--1.16 内联框架

    html5--1.16 内联框架 学习要点: 1.iframe内联框架2.综合实例1 1.iframe内联框架 1.iframe元素用来在文档中添加一个内联框架. 2.iframe为body元素的子元 ...