Python核心基础|第十讲 函数(三)

高阶函数

  1. 接收函数作为参数
  2. 或者将函数作为返回值返回的函数就是高阶函数
list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]


def fn1(i):
    if i % 2 == 0:
        return True


def fn(fun, list1):

    new_list = []
    for i in list1:
        if fun(i):
            new_list.append(i)

    return new_list


r = fn(fn1, list1)
print(r)

结果:
[2, 4, 6, 8, 10]

匿名函数

  • filter

filter() 函数用于过滤序列,过滤掉不符合条件的元素,返回由符合条件元素组成的新列表。
该接收两个参数,第一个为函数,第二个为序列,序列的每个元素作为参数传递给函数进行判断,然后返回 True 或 False,最后将返回 True 的元素放到新列表中。

#!/usr/bin/python
# -*- coding: UTF-8 -*-
 
def is_odd(n):
    return n % 2 == 1
 
newlist = list(filter(is_odd, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]))
print(newlist)

结果:
[1, 3, 5, 7, 9]
#!/usr/bin/python
# -*- coding: UTF-8 -*-
 
import math
def is_sqr(x):
    return math.sqrt(x) % 1 == 0
 
newlist = list(filter(is_sqr, range(1, 101)))

结果:
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

  • lambda

使用lambda来创建匿名函数。

print((lambda a,b:a+b)(1,2))

结果:
3
MAXIMUM = lambda x, y: (x > y) * x + (x < y) * y
MINIMUM = lambda x, y: (x > y) * y + (x < y) * x

if __name__ == '__main__':
    a = 10
    b = 20
    print('The largar one is %d' % MAXIMUM(a, b))
    print('The lower one is %d' % MINIMUM(a, b))

闭包

闭包的作用:
闭包可以保存外部函数的变量,不会随着外部函数调用完而销毁
注意点:
由于闭包引用了外部函数的变量(参数), 则外部函数的变量没有及时释放,消耗内存
• 闭包的好处
• 通过闭包可以创建一些只有当前函数能访问的变量
• 可以将一些私有数据藏到闭包中
• 行成闭包的条件
• 函数嵌套
• 将内部函数作为返回值返回
• 内部函数必须要使用到外部函数的变量

def fun_out(num1):
    def fun_inner(num2):
        r = num1 + num2
        print(r)
    return fun_inner


r = fun_out(1)
r(3)
r(3)
r(3)
r(3)
r(3)
r(3)

结果:
C:\Users\Administrator\AppData\Local\Programs\Python\Python37\python.exe D:/python/day09.py
4
4
4
4
4
4

Process finished with exit code 0
def fun_out(num1):
    def fun_inner(num2):
        num1 = 10
        r = num1 + num2
        print(r)
    return fun_inner
r = fun_out(1)
r(2)

结果:
12

生成器

  • 迭代器

迭代是Python最强大的功能之一,是访问集合元素的一种方式。
迭代器是一个可以记住遍历的位置的对象。
迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
迭代器有两个基本的方法:iter() 和 next()。
字符串,列表或元组对象都可用于创建迭代器:

  • 创建一个迭代器

把一个类作为一个迭代器使用需要在类中实现两个方法 iter() 与 next() 。
如果你已经了解的面向对象编程,就知道类都有一个构造函数,Python 的构造函数为 init(), 它会在对象初始化的时候执行。
iter() 方法返回一个特殊的迭代器对象, 这个迭代器对象实现了 next() 方法并通过 StopIteration 异常标识迭代的完成。
next() 方法(Python 2 里是 next())会返回下一个迭代器对象。
创建一个返回数字的迭代器,初始值为 1,逐步递增 1:

class MyNumbers:
  def __iter__(self):
    self.a = 1
    return self
 
  def __next__(self):
    x = self.a
    self.a += 1
    return x
 
myclass = MyNumbers()
myiter = iter(myclass)
 
print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))

结果:
1
2
3
4
5

  • 生成器

生成器的特性: 生成器相当于一个容器, 当你把容器里的数据全部取出来之后,那么容器里面就不在有数据了
生成器只能取一次,用完了之后就没有了,需要你自己在重新生成一次才可以
第二种方式: 用函数的方式 yield
当使用yield关键字之后,函数不再是函数,而是一个生成器
当程序执行到yield的时候,程序就会停止 和 input类似
生成器,会记住你之前取到的元素的位置,下一次继续去数据的时候,他会在那个位置继续往下取数据

在 Python 中,使用了 yield 的函数被称为生成器(generator)。 跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。 在调用生成器运行的过程中,每次遇到
yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。
调用一个生成器函数,返回的是一个迭代器对象。

def fn():
    print('fn执行了')
    i = 1
    while True:
        yield i
        i += 1

r = fn()
# print(r)
print(next(r))
print(next(r))
print(next(r))
print(next(r))

结果:
C:\Users\Administrator\AppData\Local\Programs\Python\Python37\python.exe D:/python/day09.py
fn执行了
1
2
3
4

Process finished with exit code 0
def fibonacci(n):  # 生成器函数 - 斐波那契
    a, b, counter = 0, 1, 0
    while True:
        if (counter > n):
            return
        yield a
        a, b = b, a + b
        counter += 1

f = fibonacci(10)  # f 是一个迭代器,由生成器返回生成
print(f)
while True:
    try:
        print(next(f), end=" ")
    except:
        pass

结果:
<generator object fibonacci at 0x0000000001E07750>
0 1 1 2 3 5 8 13 21 34 55 

推导式

类表推导式
旧的类表 ----> 新的列表
语法: [表达式 for 变量 in 旧列表 if 条件]

list1 = ['cheney', 'jerry', 'amy', '居然', 'tony', 'anny', 'james', '豆腐', 'wolf']


def fn():
    pass

result = [name for name in list1 if len(name) > 4]
print(result)

装饰器

为什么要这样
要想理解装饰器为什么要有这种结构,要首先想明白装饰器的目标是什么。
它的价值在于为原函数f增加一些行为,前提必须不能破坏函数f,所以肯定不能改变f的内部结构,所以只能在调用f前后定义一些行为。
同时,装饰器函数decorator返回值又是什么?你可以思考下,返回一个函数是再好不过的了,它包装了原函数f.

• 我们可以直接通过修改函数中的代码来完成需求,但是会产生以下一些问题
• 如果修改的函数多,修改起来会比较麻烦
• 不方便后期的维护
• 这样做会违反开闭原则(ocp)
• 程序的设计,要求开发对程序的扩展,要关闭对程序的修改

  • 装饰一个函数
def decorator(f):
  # 定义要返回的函数
  def g():
    print('函数f执行前的动作')
    f()
    print('函数f执行后的动作')
  return g
def printStar(f):
    def g():
        print('*'*20)
        f()
        print('*'*20)
    return g
@printStar
def f():
    print('hello world')
if __name__ == '__main__':
   f()
   
结果:
********************
hello world
********************
  • 装饰一个类
def decorator(cls):
  # 定义要返回的函数
  def g():
    print('类cls执行前的动作')
    f()
    print('类cls执行后的动作')
  return g

@+自定义装饰器 装饰要想装饰的函数。

def decorator(f):
  # 定义要返回的函数
  def g():
    print('函数f执行前的动作')
    f()
    print('函数f执行后的动作')
  return g

@decorator
def f():
    print('hello word')
f()

结果:
函数f执行前的动作
hello word
函数f执行后的动作
def add(a, b):
    return a + b
def fn1():
    print('我是fn1')
def fn(a, b):
    print('函数开始执行')
    r = add(a, b)
    print('函数执行结束')
    return r
r = fn(1, 2)
print(r)

结果:
函数开始执行
函数执行结束
3

  • 装饰器层叠
def printStar(f):
    def g():
        print('*'*20)
        f()
        print('*'*20)
    return g
def printLine(f):
    def g():
        print('-'*20)
        f()
        print('-'*20)
    return g
@printStar
@printLine
def f():
    print('hello world')
if __name__ == '__main__':
   f()

结果:
********************
--------------------
hello world
--------------------
********************

作业
1.请使用装饰器实现已存在的函数的执行所花费的时间。

import time
def run_time(fn):
    def wrapper(*args, **kw):
        start = time.time()
        res = fn()
        print('%s 运行了 %f 秒' % (fn.__name__, time.time() - start))
        return res
    return wrapper


@run_time
def fn():
    a = input("请输入4位整数作为年份:")
    a = eval(a)
    if a % 400 == 0 or (a % 4 == 0 and not a % 100 == 0):
        print("{}是闰年".format(a))
    else:
        print("{}不是闰年".format(a))
fn()


结果:
C:\Users\giser\AppData\Local\Programs\Python\Python37\python.exe D:/pycharm/pythonbasic/day09.py
请输入4位整数作为年份:2020
2020是闰年
fn 运行了 2.180000 秒

Process finished with exit code 0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值