Python--生成式、生成器、迭代器与可迭代对象(高级特性)

一、生成式详解
生成式:快速生成对象的公式。一般有列表生成式,字典生成式,集合生成式。
列表生成式就是一个用来生成列表的特定语法形式的表达式。是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]
列表生成式案例:
案例1:生成30个1~50之间的随机数
代码:

import random

def use_list_expression(count = 30,start = 1,end = 50):
    """第一种:使用列表生成式实现需求"""
    return [random.randint(start,end) for count in range(count)]

def use_loop(count = 30,start = 1,end = 50):
    """第二种:使用for循环的传统方法实现"""
    nums = []
    for count in range(count):
        num = random.randint(start,end)
        nums.append(num)
    return nums

print(use_list_expression(count=5))
print(use_loop(count=5))

结果:[2, 15, 9, 24, 38] [44, 40, 2, 3, 16]
案例2:找出1-100之间能被3整除的数值(过滤功能)

def use_loop1(start = 1,end = 30,div_num = 3):
    """第一种:使用传统方法实现"""
    nums = []
    for num in range(start,end):
        if num%div_num == 0:
            nums.append(num)
    return nums

def use_list_expression1(start = 1,end = 30,div_num = 3):
    """第二种:使用列表生成式"""
    return [num for num in range(start,end) if num%div_num == 0]   #带过滤功能的语法格式

print(use_loop1())
print(use_list_expression1())
[3, 6, 9, 12, 15, 18, 21, 24, 27]
[3, 6, 9, 12, 15, 18, 21, 24, 27]

案例3:循环嵌套结构

items = [item1+item2 for item1 in 'abc' for item2 in '123']
print(items)
#解释过程
items = []
for item1 in 'abc':             # item1='a'             item1='b'               item1='c'
    for item2 in '123':         # item2='1', '2', '3'   item2='1', '2', '3'     item2='1', '2', '3'
        items.append(item1+item2)

print(items)

结果:['a1', 'a2', 'a3', 'b1', 'b2', 'b3', 'c1', 'c2', 'c3']
集合生成式
#需求:生成10个1~50之间的随机且不重复的数

#需求:生成10个1~50之间的随机且不重复的数
#利用集合不存在重复的元素的特点

import random

set = {random.randint(1,50) for count in range(10)}
print(set)
{33, 36, 39, 7, 43, 45, 46, 22, 29}

字典生成式
#需求:生成100个用户字典,key是用户名userx(x = 1,2,3,4…),value是密码passwordx(x=1,2,3,4…)

#需求:生成100个用户字典,key是用户名userx(x = 1,2,3,4...),value是密码passwordx(x=1,2,3,4...)
import pprint
user_info = {"user" + str(item) : 'password' + str(item) for item in range(100)}
pprint.pprint(user_info)
{'user0': 'password0',
 'user1': 'password1',
 'user10': 'password10',
 'user11': 'password11',
 'user12': 'password12',
 'user13': 'password13',
 'user14': 'password14',

生成式练习
1、求以r为半径的圆的面积和周长(r的范围从1到10)和将字典的key值和value值调换

import math

def circle_example():
    """求以r为半径的圆的面积和周长(r的范围从1到10)"""
    square = lambda r: math.pi * r ** 2      #使用匿名函数实现面积个周长的求解
    C =  lambda r : 2 * math.pi * r
    return [(square(r),C(r)) for r in range(1,11)]   #列表生成式快速生成

#print(circle_example())

def swap_key_value(dict0bj):
    """将字典的key值和value值调换"""
    return {value:key for key,value in dict0bj.items()}

if __name__ == '__main__':

    d = {'user1' : 'password1',
         'user2' : 'password2'
         }
    print(circle_example())
    print(swap_key_value(d))
[(3.141592653589793, 6.283185307179586), (12.566370614359172, 12.566370614359172), (28.274333882308138, 18.84955592153876), (50.26548245743669, 25.132741228718345), (78.53981633974483, 31.41592653589793), (113.09733552923255, 37.69911184307752), (153.93804002589985, 43.982297150257104), (201.06192982974676, 50.26548245743669), (254.46900494077323, 56.548667764616276), (314.1592653589793, 62.83185307179586)]
{'password2': 'user2', 'password1': 'user1'}

2、找出1~100之间所有的质数和判断是否是质数

import math

l = [2,3]
def find_prime():
    """找出范围内所有质数"""
    for i in range(5,101):
        for j in range(2,int(math.sqrt(i))+1):
            if i%j==0:
                # return False
                break
        else:
            l.append(i)
    print(' '.join(map(str,l)))

def is_prime(num):
    """判断是否为质数?是则返回为True,不是则返回为false"""

    if num > 1:
        for i in range(2,num):
            if (num%i) == 0:
                print("False")
                break
        else:
            print("True")
    else:
        print("False")

if __name__ == '__main__':
    num=int(input("请输入一个数字: "))
    is_prime(num)
    find_prime()
请输入一个数字: 5
True
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

3、字典key值大小写计数合并 : 已知字典{‘A’:10, ‘b’:5, ‘a’:2}, 合并后为{‘a’:12, ‘b’:5} 注意: key值最终全部为小写.

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

二、生成器

• 什么叫生成器?
在Python中,一边循环一边计算的机制,称为生成器:Generator。
• 什么时候需要使用生成器?
性能限制需要用到,比如读取一个10G的文件,如果一次性将10G的文件加载到内存处理的话 (read方法),内存肯定会溢出;但使用生成器把读写交叉处理进行,比如使用(readline和readlines) 就可以再循环读取的同时不断处理,这样就可以节省大量的内存空间。
生成器的特点是什么?
• 解耦. 爬虫与数据存储解耦;
• 减少内存占用. 随时生产, 即时消费, 不用堆积在内存当中;
• 可不终止调用. 写上循环, 即可循环接收数据, 对在循环之前定义的变量, 可重复使用;
• 生成器的循环, 在 yield 处中断, 没那么占 cpu.
• 如何创建生成器?
第一种方法: 列表生成式的改写。[ ]改成()
第二种方法: yield关键字。
• 如何打印生成器的每一个元素呢?
通过for循环, 依次计算并生成每一个元素。
如果要一个一个打印出来,可以通过next()函数获得生成器的下一个返回值。
生成器的创建与访问—第一种方法:列表生成式:将[]改写为()

#第一种方法:列表生成式:将[]改写为()

#列表生成式
"""
    nums = [num for num in range(1,1001) if num % 8 == 0]
    print(nums)
"""
#生成器的创建
nums_gen = (num for num in range(1,101) if num % 8 ==0)
print(nums_gen)     #<generator object
print(type(nums_gen))     #<genexpr> at 0x7f7cb4b612d0> <class 'generator'>
#打印生成器的每一个元素
#查看一个对象是否可以进行for循环?使用for循环进打印

from collections.abc import Iterable
print("生成器是否是可迭代对象:" , isinstance(nums_gen,Iterable))  #查看生成器是否是可迭代对象

#访问生成器对象元素的方法之一:通过for循环,依次遍历打印每一个元素
for num in nums_gen:
    if num > 50:
        break
    print(num)

#访问生成器对象元素的方法之二:使用next()函数获得生成器的下一个返回值,一个一个打印出来
print(next(nums_gen))      #每执行一次next()生成一个值
print(next(nums_gen))
print(next(nums_gen))
<generator object <genexpr> at 0x0000016D414E7938>
<class 'generator'>
生成器是否是可迭代对象: True
8
16
24
32
40
48
64
72
80

生成器的创建与访问—第二种方法:函数中包含yield关键字–Fib数列的案例理解生成器的创建

def fib1(num):
    """传统递归实现Fib数列"""
    if num in (1,2):
        return 1
    else:
        return fib1(num - 1) + fib1(num - 2)

#第二种方法:函数中包含yield关键字
def fib2(num):
    """不使用递归方式实现Fib数列"""
    count = 0
    a = b = 1
    while True:
        if count < num:
            count += 1
            yield a          #返回函数值后,会在前面停留的位置继续执行,直到程序结束,第一次执行next()输出a=1
            a,b = b,a+b      #a=b=1,b=a+b=1+1=2,第二次执行next()输出a=1;a=b=2,b=1+2=3,第三吃执行()输出a=2;a=b=3,b=2+3=5,第四次执行next()输出a=3;.......
        else:
            break
#如果函数中含有yeild关键字,那么函数的返回值是生成器对象
result = fib2(10)
print(result)        #<generator object fib2 at 0x7f4096467350>


#访问生成器对象元素的方法1:通过for循环,依次计算并生成每一个元素
"""
result = fib2(10)

for num in result:
    print(num)

"""
#访问生成器对象元素的方法2:如果要一个一个打印出来,可以通过next()函数获取生成器的下一个返回值
print(next(result))
print(next(result))
print(next(result))
print(next(result))
print(next(result))
<generator object fib2 at 0x0000017FB9697A40>
1
1
2
3
5

python中return关键字和yield关键字的区别?
• return:在程序函数中返回某个值,返回之后函数不在继续执行,彻底结束。
• yield: 带有yield的函数是一个迭代器,函数返回某个值时,会停留在某个位 置,返回函数值后,会在前面停留的位置继续 执行,直到程序结束
代码理解

# def return_example():
#     """
#     理解return的工作原理
#         1).函数的运行结果是什么?
#         2).是否会打印‘step 1’? why?      会执行
#         3).是否会打印‘step 2’? why?      不会执行,return执行后后面的代码不会执行,代码执行结束
#     :return:
#     """
#     print('step 1')
#     #函数遇到return,函数执行结束,后面的代码不会执行
#     return True
#     print('step 2')

def yield_example():
    """
    理解yeild的工作原理
        1).函数的运行结果是什么?
        函数中包含yield关键字,返回的是生成器对象,函数执行到yield处不执行函数后面的代码
        当第一次调用next()函数时,才执行函数内容
        遇到yield关键字,执行停止
        当再次执行next()函数时,从上次停止的代码位置继续执行
        遇到yield关键字执行停止,一直重复下去..........
    :return:
    """
    for count in range(100):
        yield 'step' + str(count)
        print("success")

if __name__ == '__main__':
    result = yield_example()
    print(next(result))         #step0
    print(next(result))         #success step1
    print(next(result))         #success  step2
    print(next(result))         #success  step3
step0
success
step1
success
step2
success
step3

生成器的send方法
send方法和next方法唯一的区别是在执行send方法会首先把上一次挂起的yield语句的返回值通过参数设定,从而实现与生成器方法的交互。
但是需要注意,在一个生成器对象没有执行next方法之前,由于没有yield语句被挂起,所以执行send方法会报错

def grep(key_word):
    """搜索关键字"""
    while True:
        response = ''
        request = yield response
        if key_word in request:
            print(request)

if __name__ == '__main__':
    grep_gen = grep('python')
    next(grep_gen)
    #send方法可以给生成器传递数据,并一直执行,遇到yield为止
    grep_gen.send('I love python')   #将'I love python'传递给response,response再将值传递给request
    grep_gen.send('I love Java')
I love python

生成器应用案例:聊天机器人

#requests库时python中实现的最简单的易用的HTTP库,多用于网络爬虫
import requests
#json库是实现python中实现json的序列化和反序列化的模块
import json

def robot_api(word):
    #青云提供的API地址
    url = 'http://api.qingyunke.com/api.php?key=free&appid=0&msg=%s' %(word)
    try:
        #访问URL,获取网页响应的内容,响应结果为字符串
        response_text = requests.get(url).text
        #将json字符串转换成字典,并获取字典的'content'key对应的value值
        #eg:{'result': 0, 'content': '有做广告的嫌疑,清静点别打广告行么'}
        return json.loads(response_text).get('content','无响应')
    except Exception as e:
        #如果访问失败,响应内容为‘’
        return ''

def chatRobot():
    response = ''

    while True:
        #yield response:response就是生成器执行next方法或者send方法的返回值
        #request = yield
        request = yield response
        if 'name' in request:
            response = '姓名暂时保密'
        elif 'hello' in request:
            response = '你好!Hello'
        else:
            response = robot_api(request)

if __name__ == '__main__':
    Robot = chatRobot()                #1).调用chatRobot函数,在yield前面停止
    next(Robot)                         #2).执行yield语句,不包括if语句
    while True:
        request = input("Me>> ")        #3).输入
        if request == 'goodbye':        #4).如果输入为goodbye,退出
            print('欢迎下次聊天')
            break
        response = Robot.send(request)   #5).通过send将输入传递给yield后面的response,并接着往下执行(if语句),直到遇到yield为止,将返回值response赋值给response
        print('Robot>>:',response)       #6).输出response

结果:
在这里插入图片描述
三、生成器、迭代器与可迭代对象
生成器: generator, 一边循环一边计算的工具。
迭代器: iterator, 可以调用next方法访问元素的对象.
可迭代对象: Iterable, 可以实现for循环的

生成器都是迭代器么? Yes, 生成器内部实现了迭代器的协议。
生成器都是可迭代对象吗? Yes 通过能否for循环进行判断
可迭代对象都是迭代器吗? Not Always, 比如: str,list,tuple,set,dict,不能够使用next()函数
如何将可迭代对象转换成迭代器? iter()内置函数

迭代器和生成器的区别 ?
在这里插入图片描述
四、闭包
• 什么是闭包?如何实现闭包?
闭包就是指有权访问另一个函数作用域中的变量的函数。
创建闭包最常见方式,就是在一个函数内部创建另一个函数。
常见形式: 内部函数使用了外部函数的临时变量,且外部函数的返回值是内部函数的引用。 闭包的一个常用场景就是装饰器。
优点: 闭包也具有提高代码可复用性的作用
闭包的理解和画图

"""
line_conf:外部函数
line:内部函数

line是否为闭包?Yes,line调用了line_conf的局部变量a和b
"""
import matplotlib.pyplot as plt

def line_conf(a,b):
    """y = ax + b"""
    def line(x):
        return a * x + b
    return line #返回一个函数名

#line1是一个函数名
line1 = line_conf(2,3)
line2 = line_conf(3,3)
line3 = line_conf(4,3)

# x = [1,3,5,7....,99]
x = range(1,100,2)
y1 = [line1(item) for item in x]
y2 = [line2(item) for item in x]
y3 = [line3(item) for item in x]

#plot:折线图
# plt.plot(x,y1,label = 'y=2x+3')
# plt.plot(x,y2,label = 'y=3x+3')
# plt.plot(x,y3,label = 'y=4x+3')

#scatter:散点图
plt.scatter(x,y1,label = 'y = 2x + 3')
plt.scatter(x,y2,label = 'y = 3x + 3')
plt.scatter(x,y3,label = 'y = 4x + 3')

#显示绘制的图形
plt.title('line display')   #添加标题
plt.legend()                #添加图例
plt.show()                  #显示图形

在这里插入图片描述
在这里插入图片描述
五、装饰器
装饰器指的是为被装饰对象添加额外功能的工具/函数。

为什么使用装饰器?

如果我们已经上线了一个项目,我们需要修改某一个方法,但是我们不想修改方法的使用方法,这个时 候可以使用装饰器。因为软件的维护应该遵循开放封闭原则,即软件一旦上线运行后,软件的维护对修 改源代码是封闭的,对扩展功能指的是开放的。
装饰器的实现必须遵循两大原则:
• 封闭: 对已经实现的功能代码块封闭。 不修改被装饰对象的源代码
• 开放: 对扩展开发

装饰器其实就是在遵循以上两个原则的前提下为被装饰对象添加新功能。

如何实现装饰器?
装饰器本质上是一个函数,该函数用来处理其他函数,它可以让其他函数在不需要修改代 码的前提下增加额外的功能,装饰器的返回值也是一个函数对象。
装饰器应用案例1:日志记录或者处理

#logging:专门做日志记录或者处理的模块
import logging

logging.basicConfig(
    level=logging.DEBUG,        #控制台打印的日志级别
    filename='message.log',      #日志文件位置
    filemode='a',              #写入文件的模式,a是追加模式,默认是追加模式
    #日志格式
    format = '%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s'
)

#1).定义装饰器
from functools import wraps

def logger(func):
    """插入日志的装饰器"""
    #wraps装饰器,用来保留func函数原有的函数名和帮助文档
    @wraps(func)
    def wrapper(*args,**kwargs):     #*args,**kwargs是形参,args是元组,kwargs是字典
        """闭包函数"""
        logging.debug("函数%s开始执行" %(func.__name__))
        result = func(*args,**kwargs) #*args,**kwargs是实参,*args,**kwargs解包
        logging.debug("函数%s执行结束" %(func.__name__))
        return result
    return wrapper

#2).如何使用装饰器?
#   1).@logger语法糖,login = logger(login),python解释器遇到语法糖就直接执行
#   2).login函数目前指向logger(login)函数的返回值wrapper,login = wrapper
@logger
def login(username,password):
    """用户登陆"""
    if username == 'root' and password == 'redhat':
        print("LOGIN OK")
        logging.debug('%s LOGIN OK' %(username))
    else:
        print("LOGIN FAILED")
        logging.error("%s LOGIN FAILED" %(username))

#实质执行的是装饰器里面的wrapper函数
login('root','westos')
# print(login.__name__)         #func原有的函数名
# print(login.__doc__)          #func的帮助文档
LOGIN FAILED

在这里插入图片描述
在这里插入图片描述装饰器应用案例2:性能统计的装饰器—打印被装饰函数运行的总时间的装饰器

from functools import wraps
#计时模块
import time

def timeit(func):       #2)执行timeit函数
    """打印被装饰函数运行的总时间的装饰器"""
    #@wraps保留被装饰函数的函数名和帮助文档,否则是wrapper函数的函数名和帮助文档
    @wraps(func)
    def wrapper(*args,**kwargs):    #5)执行wrapper('Music')函数
        start_time = time.time()
        result = func(*args,**kwargs) #6).func('Music') = download_music('Music'),执行download_music函数
        end_time = time.time()
        print("%s函数运行的总时间为%fs" %(func.__name__,end_time - start_time))
        return result                #8).
    return wrapper       #3)得到返回值wrapper

@timeit    # 1).遇到语法糖直接执行:download_music=timeit(download_music),先执行timeit(download_music)得到返回值wrapper,后执行download_music=wrapper
def download_music(name):          #7).
    time.sleep(0.4)
    print('[Download]:',name)
    return True

download_music('Music')     #4).此时download_music实质为wrapper,执行wrapper函数
[Download]: Music
download_music函数运行的总时间为0.400059s

装饰器应用案例3:事务处理的装饰器—被装饰函数的返回值序列化成json格式字符串

import json
import string
from functools import wraps
import pprint

def json_result(func):                  #2)func = get_user
    """被装饰函数的返回值序列化成json格式字符串"""
    #保留被装饰函数的函数名和帮助文档
    @wraps(func)
    def wrapper(*args,**kwargs):            #5).
        result = func(*args,**kwargs)       #6).get_user()函数
        return json.dumps(result)           #8)
    return wrapper       #3)

@json_result        #1). get_user=json_result(get_user) = wrapper
def get_user():     #7)
    return {'user' + item : 'passwd' + item for item in string.digits}

result = get_user()             #4)实质为wrapper
pprint.pprint(result)           #9)
('{"user6": "passwd6", "user5": "passwd5", "user9": "passwd9", "user3": '
 '"passwd3", "user7": "passwd7", "user4": "passwd4", "user1": "passwd1", '
 '"user0": "passwd0", "user2": "passwd2", "user8": "passwd8"}')

装饰器应用案例4:Fib数列缓存的装饰器—计算有缓存和没缓存的执行时间

from functools import wraps
from functools import lru_cache
import time

def timeit(func):
    """打印被装饰函数运行总时间的装饰器"""
    @wraps(func)
    def wrapper(*args,**kwargs):
        start_time = time.time()
        result = func(*args,**kwargs)
        end_time = time.time()
        print("%s函数运行总时间为%fs" %(func.__name__,end_time-start_time))
        return result
    return wrapper


def fib_cache(func):
    """打印被装饰函数运行总时间的装饰器"""
    caches = {1:1,2:1,3:2,4:3}

    #@wraps保留被装饰函数的函数名和帮助文档,否则是wrapper的信息
    @wraps(func)
    def wrapper(num):
        #如果缓存中能找到第num个Fib数列的值,直接返回
        if num in caches:
            return caches.get(num)
        #如果缓存中不能找到第num个Fib数列的值
        #   1).先执行func(num)函数计算结果
        #   2).然后将计算的信息存储在缓存中,并返回计算结果
        else:
            result = func(num)
            caches[num] = result
            return result
        return wrapper

@lru_cache(maxsize=10000)
def fib1(num):
    """计算第num个Fib数列"""
    if num in (1,2):
        return 1
    else:
        return fib1(num - 1) + fib1(num - 2)

def fib2(num):
    """计算第num个Fib数列"""
    if num in (1,2):
        return 1
    else:
        return fib2(num - 1) + fib2(num - 2)

@timeit
def no_cache():
    result = fib2(20)
    print(result)

@timeit
def use_cache():
    result = fib1(20)
    print(result)

if __name__ == '__main__':
    use_cache()
    no_cache()

在这里插入图片描述
装饰器应用案例5:权限验证与多装饰器
多个装饰器装饰顺序是自下而上的(就近原则),而调用/执行顺序是自上而下的(顺序执行)##

from functools import wraps

#系统中的用户信息
db ={
    'root':{
        'name':'root',
        'passwd':'westos',
        'is_super':0   #0-不是,1-是
    },
    'admin':{
        'name':'admin',
        'passwd':'westos',
        'is_super':1    #0-不是,1-是
    }
}

#存储当前登陆用户的信息
login_user_session = {}

def is_login(func):
    """判断用户是否登陆的装饰器"""
    @wraps(func)
    def wrapper1(*args,**kwargs):
        if login_user_session:          #如果存在用户信息,直接执行buy()操作
            result = func(*args,**kwargs)
            return result
        else:
            print("未登录,请先登录......")  #不存在用户的登录信息
            print("跳转登录".center(20,'*'))
            user = input("User: ")         #输入用户名和密码
            passwd = input("Passwd: ")
            if user in db:                 #查看用户是否是系统用户
                if db[user]['passwd'] == passwd:        #检查系统用户的密码是否正确
                    login_user_session['username'] = user   #将该用户信息存储起来
                    print("登录成功")
                    result = func(*args,**kwargs)           #登录成功后执行buy()操作
                    return result
                else:
                    print("密码不正确")
            else:
                print("此用户不存在")
    return wrapper1

def is_permission(func):
    """判断用户是否有权限的装饰器"""
    @wraps(func)
    def wrapper2(*args,**kwargs):
        print("判断是否有权限......")
        current_user = login_user_session.get('username')     #获取用户名
        permission = db[current_user]['is_super']             #查看权限
        if permission == 1:
            result = func(*args,**kwargs)
            return result
        else:
            print("用户%s没有权限" %(current_user))
    return wrapper2

#多个装饰器装饰顺序是自下而上的(就近原则),而调用/执行顺序是自上而下的(顺序执行)

"""
被装饰的过程: 
1). @is_permission:  buy = is_permission(buy)  ===> buy=wrapper2
2). @is_login: buy = is_login(buy)  ===> buy = is_login(wrapper2)   ===> buy=wrapper1
"""

@is_login
@is_permission
def buy():
    print("购买商品......")

"""
调用的过程: 
    1). buy() ===>  wrapper1()  print("判断用户是否登录..........")
    2). wrapper2()              print("判断用户是否有权限..........")
    3). buy()                   print("购买商品........")        
       
"""
buy() 

在这里插入图片描述
在这里插入图片描述
多装饰器总结: 一般情况下,在函数中可以使用一个装饰器,但是有时也会有两个或两个以上的装饰器。 多个装饰器装饰的顺序是自下而上(就近原则),而调用的顺序是自上而下(顺序执行)。

装饰器应用案例6:有参数的装饰器
无参装饰器只套了两层,有参装饰器: 套三层的装饰器,实现一个用户登录的装饰器。

from functools import wraps

def auth(type):
    print("认证类型为:",type)
    def desc(func):
        @wraps(func)
        def wrapper(*args,**kwargs):
            if type == 'local':
                user = input('User: ')
                passwd = input("Passwd: ")
                if user == 'root' and passwd == 'westos':
                    result = func(*args,**kwargs)
                    return result
                else:
                    print("用户名/密码不正确")
            else:
                print('暂不支持远程用户登录')
        return wrapper
    return desc

"""
结论:@后面跟的是装饰器函数的名称,如果不是名称,先执行,再和@结合
1).@auth(type='remote')
2).desc = auth(type='remote')
3).@desc
4).home = desc(home)
5).home = wrapper
"""
@auth(type='remote')
def home():
    print("网站主页")

home()
认证类型为: remote
暂不支持远程用户登录

六、内置高阶函数
把函数作为参数传入,这样的函数称为高阶函数,函数式编程就是指这种高度抽象的编程范式。
1、map() 内置高阶函数。
map() 会根据提供的函数对指定序列做映射。
在这里插入图片描述

当序列多于一个时,map可以并行(注意是并行)地对每个序列执行如下图所示的过程:
在这里插入图片描述
map内置高阶函数
map()会根据提供的函数对指定序列做映射:
1).map的传递函数名可以是内置函数
2).map传递的函数名可以是匿名函数
3).map的传递函数名可以是非匿名函数
4).map的传递的可迭代对象可以是多个

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

# 1).map的传递函数名可以是内置函数
map_object =  map(int,['1','2','3'])
for item in map_object:
    print(item,type(item))

iterator_object = (int(item) for item in ['1','2','3'])
for item in iterator_object:
    print(item,type(item))

#2).map传递的函数名可以是匿名函数
map_object = map(lambda x : x**2,[1,2,3,4])
print(list(map_object))     #[1, 4, 9, 16]

# 3).map的传递函数名可以是非匿名函数
def date_process(x):
    return x + 4
map_object = map(date_process,[1,2,3,4])
print(list(map_object))      #[5, 6, 7, 8]

#4).map的传递的可迭代对象可以是多个
map_object = map(lambda x,y:x**2 + y,[1,2,3],[1,2,3])
print(list(map_object))      #[2, 6, 12]
1 <class 'int'>
2 <class 'int'>
3 <class 'int'>
1 <class 'int'>
2 <class 'int'>
3 <class 'int'>
[1, 4, 9, 16]
[5, 6, 7, 8]
[2, 6, 12]

2、内置高阶函数reduce
reduce()函数会对参数序列中的元素进行累积
py2中,reduce是内置高阶函数
py3中,reduce函数需要导入

#reduce()函数会对参数序列中的元素进行累积
#   py2中,reduce是内置高阶函数
#   py3中,reduce函数需要导入

from functools import reduce

#求1~100的总和
nums_add = reduce(lambda x,y:x + y,list(range(1,101)))
print(nums_add)

#通过reduce函数求阶乘
N = 5
result = reduce(lambda x,y:x*y,list(range(1,N+1)))
print(result)
5050
120

3、内置高阶函数filter
filter() 函数用于过滤序列,过滤掉不符合条件的元素,返回由符合条件元素组成的新列表。
在这里插入图片描述

#filter()函数用于过滤序列,过滤掉不符合条件的元素,返回符合条件组成的新列表
result = filter(lambda x:x%3==0,list(range(1,21)))
print(list(result))

result = [item for item in range(1,11) if item%3 == 0]
print(list(result))
[3, 6, 9, 12, 15, 18]
[3, 6, 9]

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

import random

def is_odd(x):
    """判断是否为偶数"""
    return x%2==0

#排序需求:偶数在前面,奇数在后面
nums = list(range(10)) #[0,1,2,3,4,5,6,,8,9]
random.shuffle(nums)
print("排序前: ",nums)
nums.sort(key=lambda x:0 if is_odd(x) else 1)
print("排序后: ",nums)

#sorted可以对所有可迭代的对象进行排序操作
result = sorted({1,2,5,4,3})
print(list(result))
排序前:  [9, 4, 6, 7, 2, 0, 8, 5, 3, 1]
排序后:  [4, 6, 2, 0, 8, 9, 7, 5, 3, 1]
[1, 2, 3, 4, 5]

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

  1. 排序对象不同: sort 是应用在 list 上的方法,sorted 可以对所有可迭代的对象进行排序操作。
  2. 返回值不同:
    list 的 sort 方法返回的是对已经存在的列表进行操作,无返回值,
    内建函数 sorted 方法返回的是一个新的 list,而不是在原来的基础上进行的操作。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值