Python基础复习函数篇

目录

1.猴子补丁
2. global和nonlocal关键字
3.迭代器和生成器
4.递归函数
5.高阶函数和lamdba函数
6.闭包
7.装饰器


1.   猴子补丁

  猴子补丁主要用于在不修改已有代码情况下修改其功能或增加新功能的支持。

  例如: 在使用第三方模块时,模块中的某些方法可能无法满足我们的开发需求。此时,我们可以在不修改这些方法代码的情况下,通过猴子补丁用一些

      自己编写的新方法进行替代,从而实现一些新的功能。

      如很多代码用到 import json,后来发现ujson性能更高,如果觉得把每个文件的import json 改成 import ujson as json成本较高,或者说想测试一下用ujson替换json是否符合预期,只需要在入口加上:

import json
import ujson
def monkey_patch_json():
           json.__name__ = ‘ujson‘
           json.dump = ujson.dumps
           json.loads = ujson.loads
monkey_patch_json()

2.   global和nonlocal关键字

  在一个函数中使用global关键字,可以声明在该函数中使用的是全局变量

  而非局部变量。

  在一个函数中要修改全局变量,必须使用global声明。

  在python中,函数的定义可以嵌套,即在一个函数的函数体中可以包含另一个函数的定义。

  通过nonlocal关键字,可以使内层的函数直接使用外层函数中定义的变量。

  例如:

def outer1():  # 不加nonlocal
    x = 10  # 局部变量
    def inner():
        x = 20
        print(x)
    print(x)

outer1()
输出结果:
20
10

def outer2():  # 加nonlocal
    x = 10  # 局部变量
    def inner():
        nonlocal x = 20
        print(x)
    print(x)

outer2()
输出结果:
20
20

3.迭代器和生成器

迭代器 Iterator

  迭代器是访问可迭代对象的工具。迭代器有两个基本的方法:iter() 和 next()
迭代器是指用iter(obj) 返回的对象(实例)。迭代器可以用next(it) 获取可迭代对象的数据。

iter(iterable)  从可迭代对象中返回一个迭代器,其中iterable必须是一个能提供一个迭代器的对象,如字符串,列表或元组对象都可用于创建迭代器。
  next(iterator)  从迭代器iterator中获取下一个数据,如果无法获取下一行数据,则触发StopIteration异常
  说明:
      代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
      用iter函数可以返回一个可迭代对象的迭代器

L = [2, 3, 5, 7]
it = iter(L)     # it 绑定的是可迭代对象 L 提供的迭代器
print(next(it))  # 2  # 向迭代器要数据
print(next(it))  # 3
print(next(it))  # 5
print(next(it))  # 7
print(next(it))  # StopIteration异常

myit = iter(range(1, 10, 3))  # range也可以作为一个迭代器对象 1, 4, 7
print(next(myit))  # 1
print(next(myit))  # 4
print(next(myit))  # 7
print(next(myit))  # StopIteration异常 可用try捕获

迭代器对象也可以使用常规for语句进行遍历:

list=[1,2,3,4]
it = iter(list)    # 创建迭代器对象
for x in it:
    print (x, end=" ")

输出结果如下:
1 2 3 4

生成器 generator

含有yield语句的函数是生成器函数,此函数被调用将返回一个生成器对象在生成器函数调用return会触发一个StopIteration异常(即生成结束)

生成器函数调用时返回的生成器是一次性的,当生成结束后将不再提供数据

  yield 可翻译为产生或生成
  yield 语句
    语法:
      yield 表达式
    说明:
      yield 用于
def
函数中,目的是将此函数作为生成器函数使用
      yield 用来生成数据,提供迭代器 next(it) 函数使用

下面举例 自己用生成器实现python内建函数 filter

这个函数也可以加深对迭代器的理解:

def myfilter(fn, iterable):
    it = iter(iterable)  # 先拿到迭代器
    while True:
        try:
            x = next(it)  # 取值
            if fn(x):
                yield x
        except StopIteration:
            return  # 生成结束

for x in myfilter(lambda y: y % 2 == 1, range(10)):
    print(x)  # 1 3 5 7 9
iter(可迭代对象)  用可迭代对象生成迭代器
next(iter(可迭代对象)) 从迭代器中取值
yield x   包含yield的函数即生成器函数   

4.    递归函数

     递归函数是指在一个函数内部通过调用自己来完成一个问题的求解

  

  当我们在进行问题的分解时,发现分解之后待解决的子问题与原问题有着相同

的特性和解法,只是在问题规模上与原问题相比有所减小,此时,就可以设计递归

函数进行求解

比如,对于计算n!的问题,可以将其分解为: n! = n * (n – 1) .可见,分解后的子问题

(n - 1)! 与原问题的 n! 的计算方法完全一样,只是规模有所减少。

同样,(n - 1)! 这个子问题有可以进一步分解为(n-1) * (n-2)! 可以进一步分解为

(n - 2)(n - 3)! ... , 直到要计算 1! 时,直接返回1 .

def fac(n):
    if n == 1:      # 递归特性一:必须有一个明确的结束条件
        return 1
    else:
        return n * fac(n-1)  # 递归特性二:每次递归都是为了让问题规模变小,即找出函数的等价关系式  

print(fac(5)) # 120  #递归特性三:递归层次过多会导致栈溢出,且效率不高

注意:

当问题规模较大时,递归调用会涉及到很多层的函数调用,一方面会由于栈操作影响程序运行速度,另一方面在Python中有栈的限制,

太多层的函数调用会引起栈溢出问题,如将  fac(5) 改成 fac(1000)则会报错。

在定义递归函数时,要先明确函数的功能,这样才能完成递归特性二的写法。

5.高阶函数和lamdba函数

高阶函数是指把函数作为参数的一种函数

其中注意 函数不仅可以赋给形参 ,也可以赋给变量。赋值后,既可以用变量名替代函数名完成函数调用,

此时变量储存的是函数的内存地址,通过()调用这个地址的内容,即函数。

lambda函数也称为匿名函数, 是一种不使用def定义函数的形式,其作用是能快速定义一个简短的函数

lambda函数的函数体只是一个表达式, 所以lambda函数通常只能实现比较简单的功能。

形式 :

  lamdba[参数1[,参数2,...,参数n]] : 表达式

冒号后面的表达式的计算结果即为该lamdba函数的返回值。实例如下:

1 def FunAdd(f,x,y): # 定义函数FunAdd
2     return f(x) + f(y) # 用传给f的函数先对x和y分别处理后,再求和并返回
3 print(FunAdd(lambda x:x**2, 3, -5)) # 计算32 + (-5)2
4 print(FunAdd(lambda x:x**3,3,-5))  # 计算33 + (-5)3

也可以将lamdba函数赋值给一个变量,然后通过该变量去调用响应的lamdba函数。如:

fun = lamdba x:x**2

print(fun(3)) # 输出9

其他高阶函数

filter函数

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.‘‘‘

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

zip函数

zip(iter1 [,iter2 [...]]) --> zip object

| Return a zip object whose .__next__() method returns a tuple where
| the i-th element comes from the i-th iterable argument. The .__next__()
| method continues until the shortest iterable in the argument sequence
| is exhausted and then it raises StopIteration.

参数iterable为可迭代的对象,并且可以有多个参数。该函数返回一个以元组为元素的列表,其中第 i 个元组包含每个参数序列的第 i 个元素。返回的列表长度被截断为最短的参数序列的长度。只有一个序列参数时,它返回一个1元组的列表。没有参数时,它返回一个空的列表。

a = [‘张三‘,‘小花‘,‘老王‘]
b = [‘男‘,‘女‘,‘男‘]
c = [‘已婚‘,‘已婚‘,‘未婚‘]
z = zip(a,b,c)
print(type(z)) # 注意:python3 不再返回列表,而是返回zip对象
print([x for x in z])
输出:
<class ‘zip‘>
[(‘张三‘, ‘男‘, ‘已婚‘), (‘小花‘, ‘女‘, ‘已婚‘), (‘老王‘, ‘男‘, ‘未婚‘)]

enumerate函数

enumerate(iterable, start=0)  

返回一个enumerate对象此对象生成的类型为(索引,值)的元组,默认索引从零开始,也可以用第二个参数start指定

  • iterable -- 一个序列、迭代器或其他支持迭代对象。
  • start -- 下标起始位置

例:

day = [‘None‘,‘Monday‘,‘Tuesday‘,‘Wednesday‘,‘Thursday‘,‘Friday‘,‘Saturday‘,‘Sunday‘]
for i in enumerate(day):
    print(‘星期{} :{}‘.format(*i))
输出:
星期0 :None
星期1 :Monday
星期2 :Tuesday
星期3 :Wednesday
星期4 :Thursday
星期5 :Friday
星期6 :Saturday
星期7 :Sunday

6.闭包

如果内层函数使用了外层函数中定义的局部变量,并且外层函数的返回值是内层函数的引用,就构成了闭包

其中定义在外层函数中但由内层函数使用的变量被称为自由变量。

一般情况下,如果一个函数结束,那么该函数中定义的局部变量就都会被释放。

然而闭包是一种特殊情况, 外层函数在结束时会发现其定义的局部变量将来会在内层函数中使用,此时

外层函数就会把这些自由变量绑定到内层函数。

因此所谓闭包, 实际上就是将内层函数的代码以及自由变量(外层函数定义,但会由内层函数使用)打包在一起。

def outer(x):
    y = 10 # 定义局部变量y并赋值为10
    def inner(z): # 在out函数中定义嵌套函数inner
        nonlocal x,y
        return x + y + z
    return inner # 返回嵌套函数inner的引用

f = outer(5) # 将返回的inner函数赋给f
g = outer(50) # 将返回的inner函数赋给g
print(‘f(20)的值为:‘,f(20))
print(‘g(20)的值为:‘,g(20))
print(‘f(30)的值为:‘,f(30))
print(‘g(20)的值为:‘,g(30))

输出结果:
f(20)的值为: 35
g(20)的值为: 80
f(30)的值为: 45
g(20)的值为: 90

提示:

  闭包的主要作用在于可以封存函数执行的上下文环境。

  比如,上例通过两次调用outer函数形成了两个闭包 f 和 g 。这两个闭包具有相互独立的上下文

环境(一个闭包(f)中x = 5,y = 10,另一个闭包中x = 50,y = 10),且每个闭包可多次调用。

7.装饰器(Decorator)

  利用装饰器,可以在不修改已有函数的情况下向已有函数中注入代码,使其具备新的功能。

比如利用装饰器可以将日志处理,执行事件计算,性能测试,事务处理等较为通用且与函数功能本身无关的代码注入到不同的函数中,从而使得代码更加简洁。

  一个装饰器可以为多个函数注入代码, 一个函数也可以注入多个装饰器的代码

  本质上,装饰器就是一个返回函数的高阶函数。

实例1:

def deco(func): # 定义装饰器函数deco
    def inner(*args, **kwargs):
        print(‘deco begin‘)
        func(*args, **kwargs)
        print(‘deco end‘)
    return inner  # 返回函数inner的引用

@deco  #语法糖,相当于在f函数执行前执行了f = deco(f)
def f(a,b,c):
    print(‘a+b+c =‘,a+b+c)

f(1,2,3)
输出结果:
deco begin
a+b+c = 6
deco end

7.2 带参数和有返回值的装饰器

装饰器还有更大的灵活性,例如带参数的装饰器,在上面的装饰器调用中,装饰器函数的参数就是业务函数 f。

装饰器的语法允许我们在调用时,提供其他参数,比如@deco(a) 。

这样就Wie装饰器的编写和使用提供了更大的灵活性。比如,我们可以在装饰器中指定日志的等级,因为不同业务

函数可能需要的日志等级是不一样的。

另外有些业务函数有自己的return值,所以我们在装饰器函数中也要设定返回值,即将业务函数的返回值在装饰函数中再返还给业务函数。示例如下:

 1 import logging
 2
 3 def use_deco(level):  # 这个函数将装饰器参数传到内部环境中
 4     def deco(func):   # 真正的装饰器函数
 5         def wrapper(*args, **kwargs):  #内部用来实现装饰功能的函数
 6             if level == ‘warn‘:
 7                 logging.warning("%s is running" % func.__name__) # 打印一个警告信息; 每个函数对象都有一个__name__属性,可以拿到函数的名字
 8             elif level == "info":
 9                 logging.info("%s is running" % func.__name__) # 默认日志级别是warning,所以info不会被打印
10             return func(*args)  # 返回业务函数的返回
11         return wrapper  # 返回函数wrapper的引用
12     return deco  # 返回装饰器函数的引用
13
14 @use_deco(level=‘warn‘)  #语法糖,还是相当于@deco(f = deco(f)),因为use_deco(level=‘warn‘) 返回的是deco
15 def f(a,b,c):
16     print(‘a+b+c =‘,a+b+c)
17     return a * b * c
18
19 a = f(1,2,3)
20 print(‘a*b*c =‘,a)
21
22 运行结果:
23 a+b+c = 6
24 WARNING:root:f is running
25 a*b*c = 6

装饰器顺序

一个函数还可以同时定义多个装饰器,比如:

@a

@b

@c

def f():

  pass

他的执行顺序是从里到外,最先调用最里层的装饰器,最后调用最外层的装饰器,它等效于

f = a ( b ( c ( f ) ) )

原文地址:https://www.cnblogs.com/Jimmy00/p/10754178.html

时间: 2024-11-07 15:32:25

Python基础复习函数篇的相关文章

python基础——sorted()函数

python基础——sorted()函数 排序算法 排序也是在程序中经常用到的算法.无论使用冒泡排序还是快速排序,排序的核心是比较两个元素的大小.如果是数字,我们可以直接比较,但如果是字符串或者两个dict呢?直接比较数学上的大小是没有意义的,因此,比较的过程必须通过函数抽象出来. Python内置的sorted()函数就可以对list进行排序: >>> sorted([36, 5, -12, 9, -21]) [-21, -12, 5, 9, 36] 此外,sorted()函数也是一个

Python基础07 函数

Python基础07 函数 作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 函数最重要的目的是方便我们重复使用相同的一段程序. 将一些操作隶属于一个函数,以后你想实现相同的操作的时候,只用调用函数名就可以,而不需要重复敲所有的语句. 函数的定义 首先,我们要定义一个函数, 以说明这个函数的功能. def square_sum(a,b): c = a**2 + b**2 return c 这个函数的功能是求两个数的平方和. 首先

python基础——匿名函数及递归函数

python基础--匿名函数及递归函数 1 匿名函数语法 匿名函数lambda x: x * x实际上就是: def f(x): return x * x 关键字lambda表示匿名函数,冒号前面的x表示函数参数. 匿名函数有个限制,就是只能有一个表达式,不用写return,返回值就是该表达式的结果. 2 匿名函数举例 用匿名函数有个好处,因为函数没有名字,不必担心函数名冲突.此外,匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量,再利用变量来调用该函数: >>> f = lam

第七篇 python基础之函数,递归,内置函数

阅读目录 一 数学定义的函数与python中的函数 二 为何使用函数 背景提要 三 函数和过程 四 函数参数 五 局部变量和全局变量 六 前向引用之'函数即变量' 七 嵌套函数和作用域 八 递归 九 匿名函数 十 函数式编程 十一 内置函数 十二 本节作业 一 数学定义的函数与python中的函数 初中数学函数定义:一般的,在一个变化过程中,如果有两个变量x和y,并且对于x的每一个确定的值,y都有唯一确定的值与其对应,那么我们就把x称为自变量,把y称为因变量,y是x的函数.自变量x的取值范围叫做

【python第三篇】 python基础之函数,递归,内置函数

一 数学定义的函数与python中的函数 1.函数的好处:代码重用,保持一致性,易维护性,可扩展性 2.什么是过程?就是没有返回值的函数值,函数返回值:1.若没有返回值,返回None(没有return):2.有返回值时,直接返回值: 总结: 返回值数=0:返回None 返回值数=1:返回object 返回值数>1:返回tuple 3.1形参和实参 a.形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元,因此,形参只在函数内部有效,函数调用结束返回主调用函数不能再使用该形

python基础1--小结篇

如果有别的编程语言基础,python属于极好上手的一门语言.应用上,用“自取所需”来描述,最为贴切. 首先,放上一些推荐. 安装上: 1.python3.5.1(推荐官网直接下载,自带IDLE),安装不麻烦,记得增加环境变量即可 2.编辑器:sublime 其实,并没有使用很多,但是推荐的人超多 ,破解版网上很多,按资源下载即可 3.IDE: 强推 pycharm 对JetBrains软件执着的热爱  方便又美观 网上能找到找到注册码,学生用edu邮箱可以免费使用,当然,支持正版! 熟悉上: 语

python基础教程函数参数

python里有很多的内置函数给我们的工作带来了很多发便利,在我们实现某些功能或者优化代码的时候,可以自己定义一个函数,同时我们在定义一个类的时候也会用到函数的一些知识去构造一个方法,这里就涉及到一些关于函数的基础知识和函数传参的知识. 一.函数的相关介绍 1.函数定义:函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可. 函数特性: 减少重复代码 使程序变的可扩展 使程序变得易维护 2.函数的定义示例 定义一个函数要使用def语句,依次写出函数名.括

Python学习笔记(一)python基础与函数

1.python基础 1.1输入与输出 输出 用print加上字符串,就可以打印指定的文字或数字 >>> print 'hello, world' hello, world >>> print 300 300 >>> print 100+200 300 print语句也可以跟上多个字符串,用逗号","隔开,就可以连成一串输出: >>> print 'The quick brown fox', 'jumps over

python基础-第六篇-6.2模块

python之强大,就是因为它其提供的模块全面,模块的知识点不仅多,而且零散---一个字!错综复杂 没办法,二八原则抓重点咯!只要抓住那些以后常用开发的方法就可以了,哪些是常用的?往下看--找答案~ 模块定义 模块,用一砣代码实现了某个功能的代码集合. 类似于函数式编程和面向过程编程,函数式编程则完成一个功能,其他代码用来调用即可,提供了代码的重用性和代码间的耦合.而对于一个复杂的功能来,可能需要多个函数才能完成 (函数又可以在不同的.py文件中),n个 .py 文件组成的代码集合就称为模块.