【python】Function(9.1)

在这里插入图片描述

承接【python】Function(9)

更多连载请查看【python】

Don’t say so much!



1 闭包

如果在一个函数的内部定义了另一个函数,外部的我们叫他外函数,内部的我们叫他内函数。

在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了一个闭包。

def a(x):
    def b(y):
        print (x*y)
    return b

i = a(5)
print (i)
print (type(i))
a(5)(6)

结果为

<function a.<locals>.b at 0x7f7e6429a9d8>
<class 'function'>
30

闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数。

这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。

所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。

闭包在运行时可以有多个实例,不同的引用环境和相同的函数组合可以产生不同的实例。

简单来说,闭包就是根据不同的配置信息得到不同的结果~

来自:Python进阶系列连载(8)——闭包(上)

看个例子就懂

def func(str1):
    print("你的电脑基本配置是:")
    def func_in(str2):
        print(str1 + str2)
    return func_in

a = func("16G内存")
a("2T硬盘(小明要求的)")
print("-"*30)

b = func("1080Ti显卡")
b("2T硬盘(小刚要求的)")
print("-"*30)

a("2T硬盘+粉红色外观(小红要求的)")

output

你的电脑基本配置是:
16G内存2T硬盘(小明要求的)
------------------------------
你的电脑基本配置是:
1080Ti显卡2T硬盘(小刚要求的)
------------------------------
16G内存2T硬盘+粉红色外观(小红要求的)

常见错误

def a(x):
    x = 5
    def b(y):
        x = x*x+y
        return x
    return b
a(5)(6)

结果为

UnboundLocalError: local variable 'x' referenced before assignment

修改 python2,放在容器中

def a(x):
    x = [5]
    def b(y):
        x[0] = x[0]**2+6
        return x[0]
    return b
a(5)(6)

结果为31


修改 python3,nonlocal 关键字
nonlocal关键字用来在函数或其他作用域中使用外层(非全局)变量。

def a(x):
    x = 5
    def b(y):
        nonlocal x 
        x = x*x+y
        return x
    return b
a(3)(6)
a(4)(6)
a(5)(6)

结果都为31


注意下面两种情况的区别

def funOut():
    def funIn():
        print('宾果!你成功访问到我啦!')
    return funIn() ##返回的是函数的调用
    
funOut()#调用

结果为

宾果!你成功访问到我啦!
def funOut():
    def funIn():
        print('宾果!你成功访问到我啦!')
    return funI n## 返回的是函数名
    
funOut()()#调用

结果为

宾果!你成功访问到我啦!

def funX():
    x = 5
    def funY():
        nonlocal x
        x += 1
        return x
    return funY

a = funX()
print(a())
print(a())
print(a())

结果为
6
7
8

分析一波,只要 a 没有被重新赋值,funx()就没有被释放,局部变量 x 就不会被初始化!


2 高阶函数 map()

高阶函数:一个函数可以作为参数传给另外一个函数,或者一个函数的返回值为另外一个函数(若返回值为该函数本身,则为递归),满足其一则为高阶函数。

def add_func(x,y):
    return x+y

def mul_func(a,b,c,d,add_func):
    return add_func(a,b)*add_func(c,d)

print(mul_func(1,2,3,4,add_func))

output

21

上面例子中, add_func 就是一般的函数,mul_func 中的形参含有函数,属于高阶函数


下面我们来介绍高阶函数 map——映射

map() 会根据提供的函数对指定序列做映射。

Help on class map in module builtins:

class map(object)
 |  map(func, *iterables) --> map object
 |  
 |  Make an iterator that computes the function using arguments from
 |  each of the iterables.  Stops when the shortest iterable is exhausted.
 |  
 |  Methods defined here:
 |  
 |  __getattribute__(self, name, /)
 |      Return getattr(self, name).
 |  
 |  __iter__(self, /)
 |      Implement iter(self).
 |  
 |  __new__(*args, **kwargs) from builtins.type
 |      Create and return a new object.  See help(type) for accurate signature.
 |  
 |  __next__(self, /)
 |      Implement next(self).
 |  
 |  __reduce__(...)
 |      Return state information for pickling.

第一个参数 function 以参数序列中的每一个元素调用 function 函数,返回包含每次 function 函数返回值的新列表。

简单一点可以理解为,map 是把函数和参数绑定在一起

就像群体攻击技能(锁定技)一样,map(群体技能,【对象1,对象2,…,对象n】)

在这里插入图片描述

参考 Python进阶系列连载(9)——Python内置高阶函数map(上)

先来个简单的例子,以前面定义的加法函数为例

def add(x,y):
    return x+y
    
print(map(add,[1],[2])) # 把函数和要输入的参数 map 起来
print(type(map(add,[1],[2])))
list1 = list(map(add,[1],[2])) #转化为列表
print(list1)

output

<map object at 0x0000019D86DC1080>
<class 'map'>
[3]

支持多输入

def add(x,y):
    return x+y

list2 = list(map(add,[1,2],[2,3]))
print(list2)

output

[3, 5]

用 tuple 的形式来传入函数的参数也可以

def add(x,y):
    return x+y

list3 = list(map(add,(1,2),(2,3)))
print(list3)

output

[3, 5]

下面看一下稍微复杂一点的例子,

求解列表中每个元素的平方

实现求解列表中每个元素的平方,生成新的列表

import time

list1 = [x for x in range(1000000)] # 新建列表,元素 0~999999

# 方式一:创立列表逐个元素添加求解
start = time.time()
list2 = []
for i in list1:
    list2.append(i**2)
print(time.time()-start)

# 方式二:列表生成式
start = time.time()
list3 = [x**2 for x in list1]
print(time.time()-start)

# 方式三:map
start = time.time()
list4 = list(map(lambda x: x**2, list1))
print(time.time()-start)

output

0.48311352729797363
0.33878660202026367
0.4389934539794922

可以看出列表生成式速度还是很给力的

验证码不区分大小写

password = ["xikYLSD57qdASDF4sdf", "adfSADoi123povETRGa", "adEFASDFlkxm78wSDF3r"]

list1 = list(map(lambda x: x.upper(), password))

print(list1)

output

['XIKYLSD57QDASDF4SDF', 'ADFSADOI123POVETRGA', 'ADEFASDFLKXM78WSDF3R']

去掉列表中字符串的空格

1)方式一,借助字符串的 strip() 函数,可以去掉首尾给定的字符,默认为空格和换行符

在这里插入图片描述

来自 Python strip()方法

list1 = ["I", "Love ", " KobeBryant"]
print(list1)

list2 = list(map(lambda x: x.strip(), list1))
print(list2)

output

['I', 'Love ', ' KobeBryant']
['I', 'Love', 'KobeBryant']

OK 不错,功能实现了,不过下面情况呢?


list1 = ["I", "Lo ve ", " Kobe Bryant"]
print(list1)

list2 = list(map(lambda x: x.strip(), list1))
print(list2)

output

['I', 'Lo ve ', ' Kobe Bryant']
['I', 'Lo ve', 'Kobe Bryant']

strip() 面对字符串中间出现的空格符略显无力,

此时我们可以采用 replace() 方法,把空格 “ ” 替换成 “”,参考 【python】基本数据类型(1)

list3 = list(map(lambda x: x.replace(" ", ""), list1))
print(list3)

output

['I', 'Love', 'KobeBryant']

利用map 进行列表的类型转换

list1 = list(map(int, ['1', '2', '3']))
list2 = list(map(float, [1, 2, 3]))
print(list1, list2)

output

[1, 2, 3] [1.0, 2.0, 3.0]

3 高阶函数 reduce()

参考 Python进阶系列连载(12)——Python内置高阶函数reduce(下)

reduce 也有缩小的意思,只不过,这里的缩小指的不是物理上的,而是对一个这个reduce高阶函数传入的参数(序列 或者说是 可迭代对象)进行"缩小"操作!

在这里插入图片描述

来自 Python reduce() 函数

python 3 中,reduce 被放在了 functools 库中了,不能像 map 那样直接调用

在这里插入图片描述

def add(a,b):
    result = a + b
    print(f"{
      
      a} + {
      
      b} = {
      
      result}")
    return result

from functools import reduce

result = reduce(add, list(range(1,10)))
print("结果:",result,"\n")

result = reduce(add, list(range(1,10)), 100) # 有初始值
print("结果:",result)

output

1 + 2 = 3
3 + 3 = 6
6 + 4 = 10
10 + 5 = 15
15 + 6 = 21
21 + 7 = 28
28 + 8 = 36
36 + 9 = 45
结果: 45 

100 + 1 = 101
101 + 2 = 103
103 + 3 = 106
106 + 4 = 110
110 + 5 = 115
115 + 6 = 121
121 + 7 = 128
128 + 8 = 136
136 + 9 = 145
结果: 145

计算过程如下

在这里插入图片描述

这样看起来也没有什么特别之处啊,我 sum 也可以求和耶~

如果是乘法呢? reduce 的作用就发挥出来了,看看下面的例子

from functools import reduce

def mul(a,b):
    result = a * b
    print(f"{
      
      a} * {
      
      b} = {
      
      result}")
    return result

print(reduce(mul,[1,2,3,4]))

output

1 * 2 = 2
2 * 3 = 6
6 * 4 = 24
24

from functools import reduce

list1 = [x for x in range(5)] # 0~4

def add_func(x,y):
    return 10*x+y

print(reduce(add_func, list1)) # 无初始化的值
print((((10*0 + 1)*10 + 2)*10 + 3)*10 + 4) # 详细的计算过程
print(reduce(add_func, list1, 1)) # 有初始化的值
print(((((10*1 + 0)*10 + 1)*10 + 2)*10 + 3)*10 + 4) # 详细的计算过程

output

1234
1234
101234
101234

相当于把每个位置上的数组合在一起形成了一个数,哈哈,妙蛙种子吃着妙脆角进了米奇妙妙屋,妙到家了~

嫌蛮烦的话用下面一句话就可以 print(reduce(lambda x, y: 10*x+y, list1, 1))

Ps:

阶乘可以直接调用 math

import math
print(math.factorial(5))

output

120

4 高阶函数 filter()

参考

filter() 函数用于过滤序列,过滤掉不符合条件的元素,返回一个迭代器对象,如果要转换为列表,可以使用 list() 来转换。

该接收两个参数,第一个为函数,第二个为序列,序列的每个元素作为参数传递给函数进行判定,然后返回 True 或 False,最后将返回 True 的元素放到新列 filter(function, iterable)

Help on class filter in module builtins:

class filter(object)
 |  filter(function or None, iterable) --> filter object
 |  
 |  Return an iterator yielding those items of iterable for which function(item)
 |  is true. If function is None, return the items that are true.
 |  
 |  Methods defined here:
 |  
 |  __getattribute__(self, name, /)
 |      Return getattr(self, name).
 |  
 |  __iter__(self, /)
 |      Implement iter(self).
 |  
 |  __new__(*args, **kwargs) from builtins.type
 |      Create and return a new object.  See help(type) for accurate signature.
 |  
 |  __next__(self, /)
 |      Implement next(self).
 |  
 |  __reduce__(...)
 |      Return state information for pickling.
def func1(a):
    return a%2
tmp = range(10)
print (filter(func1,tmp))
list(filter(func1,tmp))

结果为

<filter object at 0x7f7e642580b8>
[1, 3, 5, 7, 9]

注意是把迭代的输入到函数中,输出函数为 true 时的输入值

用上面的匿名函数简化下代码如下

tmp = range(10)
list(filter(lambda x:x%2,tmp))

第一个参数为函数名,可以为空

list(filter (None,[1,2,0,False,True]))

结果为

[1, 2, True]

下面看看一些简单的例子

list1 = [x for x in range(20)] # 0~19

print(list(filter(lambda x: x >= 10, list1))) # 筛选出大于等于 10 的数字
print(list(filter(lambda x: x % 2 == 1, list1))) # 筛选出所有奇数

output

[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]

下面展示下更复杂的应用,比如找素数

import numpy as np
list1 = [x for x in range(1, 501)]


def isprime(n):
    if n < 2:
        return False
    for i in range(2, int(np.sqrt(n))+1):
        if n % i == 0:
            return False
    return True

list2 = list(filter(isprime, list1))
print(list2)

output

[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499]

更简洁的写法

list3 = list(filter(lambda x: all(x % y != 0 for y in range(2, x)), range(2, 13)))
print(list3)

output

[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499]

优化下,缩减判断空间

list3 = list(filter(lambda x: all(x % y != 0 for y in range(2, int(x**0.5)+1)), range(2, 501)))
print(list3)

output

[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499]

Note:

猜你喜欢

转载自blog.csdn.net/bryant_meng/article/details/109637177
9.1