前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python的高级语法与用法(二)

Python的高级语法与用法(二)

作者头像
stormwen
发布2019-08-05 11:14:54
4850
发布2019-08-05 11:14:54
举报
文章被收录于专栏:公众号:googpy

(一)枚举转换

例1

给定一个变量a=1,将它转换成枚举类型。根据要求,代码如下:

代码语言:javascript
复制
from enum import Enum

class VIP(Enum):          
    YELLOW = 1
    YELLOW_ALIAS = 2
    BLACK  = 3
    RED    = 4

class Common():
    YELLOW = 1

a =1
print(VIP(a))
代码语言:javascript
复制
VIP.YELLOW

这种将数字转换成枚举类型的方法和字符串整形转换是不一样的,前者是数值访问具体枚举类型的方案,后者则是数据结构的内部转换。

还需要注意的是,如果给定的变量值不在枚举类,则会报错。

(二)Enum和IntEnum

枚举中不仅有Enum模块,还有IntEnum,那两者在用法上有什么区别呢?

Enum不会对类下面的变量整形限制

代码语言:javascript
复制
from enum import Enum
class VIP(Enum):
    YELLOW = 1
    GREEN  = 'str'
    BLACK  = 3
    RED    = 4

运行不会出错。

IntEnum对于这种情况,则会报错

代码语言:javascript
复制
from enum import IntEnum
class VIP(IntEnum):
    YELLOW = 1
    GREEN  = 'str'
    BLACK  = 3
    RED    = 4
代码语言:javascript
复制
ValueError: invalid literal for int() with base 10: 'str'

上一节的学习可以知道,枚举对于值相等的标签,不会报错,而是把其中一个称为另一个的别名,但是如果需要Python报错,或者限制这种情况,可以按下面这种方法实现之:

代码语言:javascript
复制
from enum import IntEnum,unique

@unique
class VIP(IntEnum):
    YELLOW = 1
    GREEN  = 1
    BLACK  = 3

在引入语法中加入unique,同时在类前面加入@unique这个装饰器,故而运行结果为:

代码语言:javascript
复制
ValueError: duplicate values found in <enum 'VIP'>: GREEN -> YELLOW

(三)闭包

例2

代码语言:javascript
复制
def curve_pre():
    a = 25
    def curve(x):
        return a*x*x
    return curve

f = curve_pre()
print(f(2))
代码语言:javascript
复制
100

说一下我的浅显认识,要形成闭包,首先得有一个嵌套函数,即函数中定义了另一个函数,闭包则是一个集合,它包括了外部函数的局部变量,这些局部变量在外部函数返回后继续存在,并能被内部函数引用。

当对上面代码进行改动时,即加入a=10,打印的结果却不会发生变化,其实这里很好理解,在嵌套函数中,变量a是一个全局变量,通过前面的学习,Python内部的寻找机制,会先寻找本层的局部变量,如果没有则会向上寻找全部变量。

总结,通过一个简单的例子,可以知道闭包由函数和定义时外部环境构成的整体。

(四)__closure__属性和cell对象

代码语言:javascript
复制
def curve_pre():
    a = 25
    def curve(x):
        return a*x*x
    return curve

f = curve_pre()
print(f.__closure__)                    #函数的属性
print(f.__closure__[0].cell_contents)   #定义时的环境变量
print(f(2))                             #函数返回值
代码语言:javascript
复制
(<cell at 0x000000000265F768: int object at 0x000007FEDDD9E650>,)
25
100

Python中函数也是对象,所以函数也有很多属性,和闭包相关的就是__closure__属性,如果函数是一个闭包,则它返回的是一个由cell对象组成的元组对象。Cell对象的cell_contents属性就是闭包的自由变量(全局变量)

(五)一个关于闭包的例子

(1)先看一下三个打印值分别会返回多少?

代码语言:javascript
复制
def f1():
    a =10
    def f2():
        a =20
        print(a)    #第二次
    print(a)        #第一次
    f2()
    print(a)        #第三次

f1()
代码语言:javascript
复制
10
20
10

分析代码运行的过程,由外及里。在代码中我把每个打印值出现的次数也标了出来,方便大家理解。

(2)再看下面这段代码是闭包吗?

代码语言:javascript
复制
def f1():
    a =10
    def f2():
        a =20
        return a
    f2()
    return f2

f = f1()
print(f)
print(f.__closure__)
代码语言:javascript
复制
<function f1.<locals>.f2 at 0x00000000021E89D8>
None

我们删去上面代码中的打印语句,再加入return,看看代码运行结果。检验函数是否为闭包,需要用到.__closure__属性。

(3)再将上述代码进行修改,删掉f2中的变量a,结果为

代码语言:javascript
复制
<function f1.<locals>.f2 at 0x00000000021D89D8>
(<cell at 0x000000000216F768: int object at 0x000007FEDE16E470>,)

可以看到此时是闭包

(4)如果在f2函数中加入一个c=20*a,那么结果又如如何呢?

代码语言:javascript
复制
def f1():
    a =10
    def f2():
        c = 20 * a
    f2()
    return f2

f = f1()
print(f)
print(f.__closure__)
代码语言:javascript
复制
<function f1.<locals>.f2 at 0x00000000021D89D8>
(<cell at 0x000000000216F768: int object at 0x000007FEDDD9E470>,)

总结

(1)闭包避免了使用全局变量,此外,闭包允许将函数与其操作的某些数据(环境)关联起来。

(2)局部变量最好不要与环境变量同名,否则就不是一个闭包;

(3)闭包的意义是,保存环境变量,即将函数调用时的“现场”保存下来。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-05-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 googpy 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档