python基础与高级特性(七):高级特性

一.生成式与生成器

1.列表生成式

(1)列表生成式:

列表生成式就是一个用来生成列表的特定语法形式的表达式。是python提供得一种生成列表的简洁形式,可快速生成一个新的list。
普通的语法格式:[exp for iter_var in iterable]
带过滤功能语法格式: [exp for iter_var in iterable if_exp]
循环嵌套语法格式: [exp for iter_var_A in iterable_A for iter_var_B in iterable_B]

(2)列表生成式实例

1). 生成一个2n+1的数字列表,n为从3到11的数字

list = [2*item + 1 for item in range(3,12)]
print(list)

在这里插入图片描述
2).求以r为半径的圆的面积和周长(r的范围从1到10)。

import math
perimeter_list = [2*math.pi*item for item in range(1, 11)]
print(perimeter_list)

area_list = [math.pi *item** 2 for item in range(1, 11)]
print(area_list)

在这里插入图片描述
3).找出1~100之间所有的质数

def is_prime(num):
    if num <= 1:
        return False
    else:
        for item in range(2, num):
            if num % item == 0:
                return  False
        else:
            return True
prime_list = [num for num in range(1, 101) if is_prime(num)]
print(prime_list)

在这里插入图片描述
4). 找出1~100之间所有奇数, 并且返回一个列表。如果能被3整除, 返回该数的平方,否则返回该数的三次方 。

oddNums = [num**2 if num%3 == 0 else num**3 for num in range(1,101,2)]
print(oddNums)

在这里插入图片描述
5).给定一个列表li = [2,3,4,5,6,3,1,4,5], 如果是偶数返回0, 如果是奇数返回1。

li = [2,3,4,5,6,3,1,4,5]
odd_list = [0 if num%2==0 else 1 for num in li]
print(odd_list)

在这里插入图片描述

2.集合生成式和字典生成式

(1)集合生成式和字典生成式

字典生成式:用来快速生成字典;
集合生成式:用来快速生成集合;
在这里插入图片描述

(2)集合和字典生成式实例

1). 将字典的key值和value值调换;

dict = {'name' : 'fentiao',
        'age' : 5,
        'gender' : 'male'
}
dict_list = {value:key for key,value in dict.items()}
print(dict_list)

在这里插入图片描述
2). 大小写计数合并 : 已知字典{‘A’:10, ‘b’:5, ‘a’:2}, 合并后为{‘a’:12, ‘b’:5}key值最终全部为小写.

dict = {'A':10, 'b':5, 'a':2}
add_dict = {key.lower():dict.get(key.lower(), 0 )+ dict.get(key.upper(), 0) for key,value in dict.items()}
print(add_dict)

在这里插入图片描述
3). 假设有20个学生,学生分数在60-100之间,筛选出成绩在90分以上的学生;

import random
score = {random.randint(60, 100) for item in range(21)}
new_score = {item for item in score if item >= 90}
print(new_score)

在这里插入图片描述

3.生成器Generator

(1)什么是生成器?

生成器:在Python中,一边循环一边计算的机制,称为生成器:Generator。

(2)什么时候需要使用生成器?

一般情况下我们不需要使用生成器,只有当我们因为性能限制才需要用到,比如我们使用python读取一个10g的文件,如果一次性将10g的文件加载到内存处理的话(read方法),内存肯定会溢出;这里如果可以使用生成器把读写交叉处理进行,比如使用(readline和readlines)就可以再循环读取的同时不断处理,这样就可以节省大量的内存空间。

(3)如何创建生成器?

第一种方法: 列表生成式的改写。 []改成()
第一种方法: yield关键字。

(4)如何打印生成器的每一个元素呢?

通过for循环, 依次计算并生成每一个元素。
如果要一个一个打印出来,可以通过next()函数获得生成器的下一个返回值。

(5)生成器的特点是什么?

1).节约内存
2). 迭代到下一次的调用时,所使用的参数都是第一次所保留下的,即是说,在整个所有函数调用的参数都是第一次所调用时保留的,而不是新创建的。

(6)生成器的应用案例:斐波那契数列
"""

f(1)=1, f(2)=1, f(3)=3.........f(n)=f(n-1)+f(n-2)

"""
# yield关键字
# return 关键字: 工作原理

def fib(n):
    """
    显示多少个fib数列
    :param n:
    :return:
    """
    # a代表第一个数, b代表第2个数, 也就是要显示的数; count: 当前已经显示fib数列的个数;当前为0;
    a, b, count = 0, 1, 0
    # 0<5
    while count < n:
        # print(b)
        yield  b
        # a, b = b, a+b
        a, b = b, a+b
        # 已经显示的次数加1
        count += 1
# fib(5)
# fib(100000)
# f是一个生成器(函数里面有yield)
f = fib(5)
# for i in f:
#     print(i)

while True:
    try:
        print(next(f))
    except:
        break
(7)生成器的应用案例:聊天机器人
def chat_robot():
    """
    聊天机器人
    :return:
    """
    response = ''
    while True:
        receive = yield response
        if '年龄' in receive:
            response = '年龄保密'
        elif '姓名' in receive:
            response = '我是聊天机器人'
        elif receive.endswith('吗?'):
            response = receive.rstrip('吗?')
        else:
            response = '我没听明白,请换种说法'

Robot = chat_robot()
next(Robot)
while True:
    send_data = input('【用户】>>>>:')
    if send_data == 'q' or send_data =='quit':
        print('下次再聊')
        break
    response = Robot.send(send_data)
    print('[机器人]>>>>:', response)

在这里插入图片描述

(8)生成器的应用案例:生产者消费者模型

在这里插入图片描述

生产者消费者模型当中有两大类重要的角色,一个是生产者(负责造数据的任务),另一个是消费者(接收造出来的数据进行进一步的操作)。

1). 为什么要使用生产者消费者模型?

 在并发编程中,如果生产者处理速度很快,而消费者处理速度比较慢,那么生产者就必须等待消费者处理完,才能继续生产数据。同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这个等待的问题,就引入了生产者与消费者模型。让它们之间可以不停的生产和消费。

2). 实现生产者消费者模型三要素:

1、生产者

2、消费者

3、队列(或其他的容哭器,但队列不用考虑锁的问题)

3). 什么时候用这个模型?

程序中出现明显的两类任务,一类任务是负责生产,另外一类任务是负责处理生产的数据的(如爬虫)

4). 用该模型的好处?

1、实现了生产者与消费者的解耦和

2、平衡了生产力与消费力,就是生产者一直不停的生产,消费者可以不停的消费,因为二者不再是直接沟通的,而是跟队列沟通的。

生成器深入理解-生产者消费者模型
import random
import time
cacheList = []
# # 设置缓冲区的最大长度, 当缓冲区到达最大长度, 那么生产者就不能再生产了
cacheListLen = 5

def is_full():
    """
    判断缓冲区队列是否已经满了
    :return:
    """
    return  len(cacheList) == cacheListLen

def Producer(name):
    """
    生产者, 主要用于生产数据
    :return:
    """
    while True:
        if not is_full():
            print("生产者[%s]正在生产任天堂游戏机....." %(name))
            # 模拟生产者生产数据需要的时间, 随机休眠0~1秒,
            time.sleep(random.random())
            print("[%s] 已经生产任天堂游戏机完成" %(name))
            # 将生产的游戏机放入缓冲区
            cacheList.append('任天堂游戏机')
        else:
            print("生产足够多了.....")
            yield


def Consumer(name):
    """
    消费者, 用于处理/消费数据
    :return:
    """
    print("【%s】正在准备购买游戏机" %(name))
    while True:
        item = yield
        print("【%s】正在准备购买游戏机成功" %(name))


# producer是一个生成器
producer = Producer("xxx")
next(producer)

# 列表生成式, 生成消费者
consumers = [Consumer("消费者%s" %(i+1)) for i in range(10)]

# 依次遍历所有的消费者, 给提供游戏机
for consumer in consumers:
    if not cacheList:
        print("目前商店没有游戏机库存.....")
    else:
        #
        if not is_full():
            next(producer)
        else:
            item = cacheList.pop(0)
            next(consumer)
            consumer.send(item)

在这里插入图片描述

基于0库存的生产者消费者模型
import random
import  time
def Consumer(name):
    """消费者"""
    goods = ["电视", "手机", '电脑']
    # buy_name = input("请输入购买物品:")
    buy_name = random.choice(goods)
    print("[%s]需要购买%s" %(name, buy_name))
    while True:
        # 将yield后面的buy_name发送给生产者, 生产者获取生产的信息
        game  = yield buy_name
        print("[%s]购买%s成功" %(name, game))

def Produder(name):
    """生产者"""
    # []生成一个列表, 列表里面是10个生成器(Consumer)
    # ()生成一个生成器, 列表里面是10个生成器(Consumer)
    consumers = (Consumer("消费者%s" %(i+1)) for i in range(10))
    for consumer in consumers:
        # next方法的返回值就是Consumer里面yield后面跟的值;
        buy_name = next(consumer)
        print("工程师[%s]正在生产%s" %(name, buy_name))
        time.sleep(1)
        print("工程师[%s]生产%s成功" % (name, buy_name))
        # 爬虫中返回的内容是的内容;
        # 将生产好的数据发送给消费者
        consumer.send(buy_name)
def main():
    Produder("xxx")
main()

在这里插入图片描述

(9)生成器的应用案例:求平均值
def averager():
    total = 0.0
    count = 0
    average = None
    all_items = []
    while True:
        new_item = yield average, all_items
        all_items.append(int(new_item))
        total += new_item
        count += 1
        average = total / count
def main():
    AVERAGER =averager()
    next(AVERAGER)
    while True:
        new_num = input('请输入求平均值的数:')
        if new_num == 'q':
            break
        average, all_items = AVERAGER.send(int(new_num))
        print(all_items,'的平均值为:', average)

main()

在这里插入图片描述

四.迭代器

1.迭代器

(1)迭代

迭代:迭代是访问容器元素的一种方式。

(2)迭代对象

迭代对象:从集合的第一个元素开始访问,直到所有的元素被访问完结束。

(3)迭代器

迭代器:迭代器是一个可以记住遍历的位置的对象。

(4)可迭代对象

可迭代对象:可以直接作用于for循环的对象(如何判断是否可以迭代?)
一类是集合数据类型,如listtupledictsetstr等;
一类是generator,包括生成器和带yield的generator function。
可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。
生成器都是Iterator对象,但list、dict、str虽然是Iterable,却不是Iterator。
把list、dict、str等Iterable变成Iterator可以使用**iter()**函数
在这里插入图片描述

五.闭包

1.闭包

闭包:闭包的概念就是当我们在函数内定义一个函数时,这个内部函数使用了外部函数的临时变量,且外部函数的返回值是内部函数的引用时,我们称之为闭包。
闭包再理解:内部函数对外部函数作用域里变量的引用(非全局变量),则称内部函数为闭包。
nonlocal关键字:显式的指定变量不是闭包的局部变量。
闭包的应用场景:装饰器是闭包的一个常用场景。
闭包的优点:闭包也具有提高代码可复用性的作用。

2.闭包的应用案例

def line_conf(a, b):
    def line(x):
        return a * x + b
    return line

# 一元线性方程x+1
line1 = line_conf(1, 1)
# 一元线性方程3x+2
line2 = line_conf(3, 2)
# 一元线性方程4x+3
line3 = line_conf(4, 3)

loopCount = 100
y1 = [line1(item) for item in range(loopCount)]
y2 = [line2(item) for item in range(loopCount)]
y3 = [line3(item) for item in range(loopCount)]

# 图形绘制(pyecharts==0.5.11)===导入绘制折线图的类
from pyecharts import Line

# 创建绘制折线图的对象lineObj
x = list(range(loopCount))  # x轴坐标必须是一个列表;
lineObj = Line(title="一元线性方程图形展示")
lineObj.add(name='y=x+1', x_axis=x, y_axis=y1)
lineObj.add(name='y=3x+2', x_axis=x, y_axis=y2)
lineObj.add(name='y=4x+3', x_axis=x, y_axis=y3)
# 将绘制的图形显示为html文件
lineObj.render('./doc/line.html')

在这里插入图片描述

六.装饰器

1.装饰器

装饰器本质上是一个函数,该函数用来处理其他函数,它可以让其他函数在不需要修改代码的前提下增加额外功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等应用场景。

2.为什么需要装饰器

写代码要遵循开放封闭原则,虽然在这个原则是用的面向对象开发,但是也适用于函数式编程,简单来说,它规定已经实现的功能代码不允许被修改,但可以被扩展,即:
1.封闭:已实现的功能代码块
2.开放:对扩展开发

3.装饰器(decorator)功能

1.引入日志
2.函数执行时间统计
3.执行函数前预备处理
4.执行函数后清理功能
5.权限校验等场景
6.缓存

4.通用装饰器

def decorator(fun):
    def wrapper(*args, **kwargs):  # args, kwargs是形参
        # 在函数之前做的操作
        res = fun(*args, **kwargs)       # *args, **kwargs是实参, *args, **kwargs是在解包
        # 在函数之后添加操作
        return res
    return wrapper



@装饰器的名字
@add_log     ======> add=add_log(add)
def add():
    pass


add()

在这里插入图片描述

七.内置高阶函数

函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数!Python对函数式编程提供部分支持。

1.内置高阶函数Higher-order function

内置高阶函数:把函数作为参数传入,这样的函数称为高阶函数,函数式编程就是指这种高度抽象的编程范式。

(1)map()函数

map() 会根据提供的函数对指定序列做映射。
第一个参数接受一个函数名,后面的参数接受一个或多个可迭代的序列,返回的是一个集合。
在这里插入图片描述
当seq多于一个时,map可以并行(注意是并行)地对每个seq执行如下图所示的过程:
注意: map无法处理seq长度不一致、对应位置操作数类型不一致的情况,这两种情况都会报类型错误。
在这里插入图片描述

(2)reduce()函数

**reduce()**函数会对参数序列中元素进行累积。
第一个参数接受一个函数名,后面的参数接受一个或多个可迭代的序列,返回的是一个结果。
在这里插入图片描述

(3)filter()函数

filter() 函数用于过滤序列,过滤掉不符合条件的元素,返回由符合条件元素组成的新列表。
第一个参数接受一个函数名,后面的参数接受一个或多个可迭代的序列,返回的是一个序列。
在这里插入图片描述

(4)sorted/max/min()函数

sorted() 函数对所有可迭代的对象进行排序操作。返回重新排序的列表。
sorted(iterable, key=None, reverse=False)
key: 主要是用来进行比较的元素,只有一个参数,
reverse: 排序规则,True 降序 ,False 升序(默认)。

(5)python排序sort()和sorted()的区别是什么?

1.排序对象不同: sort 是应用在 list 上的方法,sorted 可以对所有可迭代的对象进行排序操作。
2.返回值不同: list 的 sort 方法返回的是对已经存在的列表进行操作,无返回值,内建函数 sorted 方法返回的是一个新的 list,而不是在原来的基础上进行的操作。

2.内置高阶函数实例

1). 对于序列每个元素求绝对值;

listnums = [-1, 3, 5, -9, -4]
map_list=list(map(abs, listnums))
print(map_list)

在这里插入图片描述
2). 接收用户输入3个数字 ; 依次将接收的三个数转换为整形

nums = input('num:').split()
map_nums = list(map(int, nums))
print(map_nums)

在这里插入图片描述
3). 对于序列每个元素求阶乘; 5!

from functools import reduce
result = reduce(lambda  x, y:x*y, range(1, 5))
print(result)

在这里插入图片描述
4). 拿出1~100之间所有的素数

def is_prime(num):
        if num <= 1:
            return False
        else:
            for item in range(2, num):
                if num % item == 0:
                    return False
            else:
                return True
result1 = filter(is_prime, range(1, 101))
print(list(result1))

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值