文章目录

  • 枚举
  • 比较运算
  • 枚举转换
  • 小结
  • 一切皆对象
  • 什么是闭包
  • 闭包的经典误区
  • 用非闭包解决问题
  • 再用闭包解决问题
  • lambda表达式
  • 三元表达式
  • map
  • reduce
  • filter
  • 装饰器(类似C#中的特性)

枚举

python 枚举 通过值查找 python枚举有什么用_lambda表达式


Python2里面是没有枚举的,但在Python3里面枚举是新加的

枚举其实是一个类

首先需要导入enum下的Enum,需要类继承Enum

打印枚举的值,显示的是他的标签,而不是他具体的数值

python 枚举 通过值查找 python枚举有什么用_python_02


python 枚举 通过值查找 python枚举有什么用_环境变量_03


可以通过枚举点value来获取枚举的值

通过枚举点name来获取枚举的标签

python 枚举 通过值查找 python枚举有什么用_环境变量_04


枚举点name是返回一个字符串类型

枚举直接打印出来是一个枚举类型

比较运算

python 枚举 通过值查找 python枚举有什么用_python_05


枚举和具体的值比较,即使值是相等的,也会返回false

python 枚举 通过值查找 python枚举有什么用_python 枚举 通过值查找_06


枚举不能比较大小,会报错

python 枚举 通过值查找 python枚举有什么用_python_07


枚举可以使用is身份运算

枚举转换

python 枚举 通过值查找 python枚举有什么用_python_08


直接类名(参数是一个具体的值),VIP(a)就可以得到a这个值对应的枚举类型是什么

小结

python 枚举 通过值查找 python枚举有什么用_Python_09


类继承Enum,枚举的值可以是一个字符串,如果不想枚举的值只能是一个int值,就要继承IntEnum

python 枚举 通过值查找 python枚举有什么用_lambda表达式_10


给枚举加上装饰器@unique,可以限制枚举定义相同的值,这样定义会报错

一切皆对象

在其他语言中函数并不是一个对象,只是一段可执行的代码,在Python中函数却是一个对象,而且你可以认为在Python里面所有的东西都是对象。

什么是闭包

python 枚举 通过值查找 python枚举有什么用_python 枚举 通过值查找_11


这段代码执行不会报错,所以得出的结论是函数是可以作为返回值返回的

函数是可以赋值给一个变量的

直接变量后面跟一个括号就可以执行这个变量所赋值的函数了

python 枚举 通过值查找 python枚举有什么用_环境变量_12


闭包等于函数加上环境变量

上图的代码,执行f(2)的值还是100,而不是40,原因是因为,闭包只会去定义时候的值

python 枚举 通过值查找 python枚举有什么用_lambda表达式_13


__closure __返回一个闭包对象

__closure __【0】.cell_contents 返回环境变量

闭包的经典误区

python 枚举 通过值查找 python枚举有什么用_Python_14


上图的代码,在f2函数里面,只要有a=20,就不是一个闭包因为f2里面的a被Python认为是一个局部变量,而不是外面的环境变量a,而闭包必须是函数加环境变量共同组成的语句块

用非闭包解决问题

python 枚举 通过值查找 python枚举有什么用_Python_15


上面这段代码执行起来会报错

而把origin = new_pos去掉将不会报错

为什么?

因为只要origin在等号左边,Python就会认为origin是一个局部变量

所以当 new_pos = origin + step这句代码的时候,会报origin没有定义的错误

python 枚举 通过值查找 python枚举有什么用_python 枚举 通过值查找_16


而用global关键字声明origin是一个全局变量就可以解决上面的问题了

再用闭包解决问题

python 枚举 通过值查找 python枚举有什么用_lambda表达式_17


这边不用全局变量,而用 nonlocal 关键字表示这个pos变量不是局部变量

lambda表达式

python 枚举 通过值查找 python枚举有什么用_python 枚举 通过值查找_18


lambda表达式的定义如上图所示

lambda只能后面接上一个表达式,如果写一个完整的语句会报错

三元表达式

python 枚举 通过值查找 python枚举有什么用_环境变量_19


三元表达式的定义如上图所示

map

python 枚举 通过值查找 python枚举有什么用_lambda表达式_20


map是一个函数,第一个参数是一个方法,第二个参数是一个列表。

可以把map函数的作用看成,把列表的值做第一个参数方法的参数,结果是这个方法的返回结果,可以用list把结果map 对象转换成一个列表

python 枚举 通过值查找 python枚举有什么用_环境变量_21


如果你想传两个参数,可以传递两个列表

如果其中一个列表有缺失,结果也会少了缺失的部分,如上图的运行结果只有前六个有结果,由于7,8的缺失,结果也会缺失。

reduce

python 枚举 通过值查找 python枚举有什么用_环境变量_22


reduce是一个连续计算的结果,而上面这段代码执行结果是36,是这八位数相加的结果。

为什么是这个结果呢?

因为reduce是一个连续的计算结果,所以执行顺序是下面的顺序。
首先拿1,2作为lambda表达式的参数x,y,结果是3,然后结果3作为下次计算的x,y取列表中的3,所以结果相加是6,6也会继续作为下次计算结果的参数x,以此类推

python 枚举 通过值查找 python枚举有什么用_python_23


而第三个参数是作为初始值传入第一次调用lambda的调用中,如上图所示

filter

python 枚举 通过值查找 python枚举有什么用_python_24


filter适合一些需要过滤的场景中,上图的例子可以过滤掉不是1的数字

装饰器(类似C#中的特性)

import time

def decorator(func):
    def wrapper():
        print(time.time())
        func()
    return wrapper

@decorator
def f1():
    print('This is a function')

f1()

# 打印结果
#1585625939.49
#This is a function

这个我们自己定义的装饰器,在没有改变原f1函数的定义的代码,和f1调用逻辑的代码前提下,给f1添加了新的功能。不过是因为@加上装饰器。

f = decorator(f1)
f()

如果不用@符号 ,我们需要这样才可以使用装饰器修饰和调用原函数
那如果f1函数有参数怎么办,或者这个装饰器还可能给很多参数的别的函数用,那我们装饰器需要做那些改动?

import time

def decorator(func):
    def wrapper(*args):
        print(time.time())
        func(*args)
    return wrapper

@decorator
def f1(name):
    print('This is a function'+name)

@decorator
def f2(name1,name2):
    print('This is a function    '+name1+'   '+name2)

f1('test')
f2('name1','name2')

上图的装饰器只是用了可变参数来解决这个问题
然后如果现在有f3有一个可变的关键字参数,上面的这个装饰器就不能满足了,所以用到下面的这种写法

import time


def decorator(func):
    def wrapper(*args,**kw):
        print(time.time())
        func(*args,**kw)
    return wrapper

@decorator
def f1(name):
    print('This is a function'+name)

@decorator
def f2(name1,name2):
    print('This is a function    '+name1+'   '+name2)

@decorator
def f3(name1,name2,**kw):
    print('This is a function    '+name1+'   '+name2)
    print(kw)

f1('test')
f2('name1','name2')
d = {'a':1,'b':2,'c':3}
f3('name1','name2',a=1,b=2,c=3)
f3('name1','name2',**d)

我们也给装饰器加上一个可变的关键字参数就好了