Python高级特性

Python高级特性

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). 求1-50所有数的平方
square = [(i + 1) ** 2 for i in range(50)]
print(square)
2). 生成一个2n+1的数字列表,n为从3到11的数字。
nums_list = [2 * n + 1 for n in range(3, 12)]
print(nums_list)
3). 求以r为半径的圆的面积和周长(r的范围从1到10)。
import math
circle = [(math.pi * (r ** 2), 2 * math.pi * r) for r in range(1, 11)]
print(circle)

3.集合生成式与字典生成式
1)集合生成式:用来快速生成集合。
2)字典生成式:用来快速生成字典。
在这里插入图片描述

生成器

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

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

1)如何创建生成器?
第一种:列表生成式的改写。(将生成式中的【】改为())
第二种:yield关键字。
2)如何打印生成器的每个元素呢?
通过for循环, 依次计算并生成每一个元素。
如果要一个一个打印出来,可以通过next()函数获得生成器的下一个返回值。
3)生成器的特点:
1.节约内存。2.迭代到下一次的调用时,所使用的参数都是第一次所保留下的,即是说,在整个所有函数调用的参数都是第一次所调用时保留的,而不是新创建的。

生成器实例:

1.斐波那契数列
除第一个和第二个数外,任意一个数都可由前两个数相加得到.
1, 1, 2, 3, 5, 8, 13, 21, 34

 def fib(n):
# 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
# f是一个生成器(函数里面有yield)
f = fib(5)
while True:
    try:
        print(next(f))
    except:
        break

2.利用yield求平均值。
在这里插入图片描述

def averager():
    # 所有数的和, 默认为0;
    total = 0.0
    # 数值的个数;
    count = 0
    # 平均值结果;
    average = None
    # 所有数值存储的容器(List);
    all_items = []
    while True:
        # 函数包含yield关键字
        new_item = yield average, all_items
        all_items.append(int(new_item))
        total += new_item
        count += 1
        average = total / count
def main():
    # AVERAGER是个生成器;
    AVERAGER = averager()
    # 第一次调用next方法, 遇到yield停止,
    next(AVERAGER)
    # 死循环, 依次求解平均值;
    while True:
        new_num = input("请输入求平均值的数: ")
        if new_num == 'q':
            print("程序执行结束.....")
            break
        # 1). 通过send方法将求平均值的数值传到yield所在位置,(14行);
        # 2). send方法的返回值是求平均值的列表和平均值结果;
        average, all_items = AVERAGER.send(int(new_num))
        print(all_items, "的平均值为:", average)
main()

迭代器

什么是迭代器?
迭代是访问容器元素的一种方式。迭代器是一个可以记住遍历的位置的对象。
迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。

可迭代对象:可以直接作用于for循环的对象(如何判断是否可以迭代?)
一类是集合数据类型,如list, tuple,dict, set,str等;
一类是generator,包括生成器和带yield的generator function。

迭代器特点:
(1)可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。
(2)生成器都是Iterator对象,但list、dict、str虽然是Iterable,却不是Iterator。
(3)把list、dict、str等Iterable变成Iterator可以使用iter()函数。

迭代器与生成器的区别:在这里插入图片描述

闭包

什么是闭包?

1)闭包的概念就是当我们在函数内定义一个函数时,这个内部函数使用了外部函数的临时 变量,且外部函数的返回值是内部函数的引用时,我们称之为闭包。

2)闭包再理解 :内部函数对外部函数作用域里变量的引用(非全局变量),则称内部函数为闭包。

3)nonlocal关键字:显式的指定变量不是闭包的局部变量
闭包的一个常用场景就是装饰器。

闭包的实际例子:在这里插入图片描述
函数line与变量a,b构成闭包。在创建闭包的时候,我们通过line_conf的参数a,b说明了这两个变量的取值,这样,我们就确定了函数的最终形式(y=x+1和y=4x+5)。
优点:闭包也具有提高代码可复用性的作用。

装饰器

什么是装饰器?
答:装饰器本质上是一个函数,该函数用来处理其他函数,它可以让其他函数在不需要修改代码的
前提下增加额外的功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,
比如:插入日志、性能测试、事务处理、缓存、权限校验等应用场景。
为什么需要装饰器?
答:写代码要遵循 开放封闭 原则,虽然在这个原则是用的面向对象开发,但是也适用于函数式编程,简单来说,它规定已经实现的功能代码不允许被修改,但可以被扩展,即:
1.封闭:已实现的功能代码块
2.开放:对扩展开发。

装饰器实例:动画片问题
在这里插入图片描述
运行结果为:‘开始播放动画片《喜羊羊和灰太狼》‘

装饰器的功能:

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

当有多个装饰器时:(以两个为例)
运行有两个装饰器的程序时可以分为有两个步骤:
1.装饰函数阶段:装饰函数时,先用第二个装饰器,再用第一个。
2.调用函数阶段:调用函数阶段,先执行第一个装饰器,再执行第二个装饰器。

多个装饰器应用实例:学生管理系统,需要判断用户是否登陆账号,以及判断账号有无权限执行操作。

    #1.判断用户是否登录
    #2.判断用户是否有权限
    #3.系统中的用户信息
db = {
    'root': {'name': 'root',
             'passwd': 'westos',
             'is_super': 0},
    'admin': {'name': 'admin',
              'passwd': 'westos',
              'is_super': 1}
}

login_user_session = {}
#存储当前登录用户信息
def is_login(fun):
    def wrapper1(*args, **kwargs):
        if login_user_session:
            result = fun(*args, **kwargs)
            return result
        else:
            print("跳转登陆".center(50, '*'))
            user = input('user:')
            passwd = input('Passwd:')
            if user in db:
                if db[user]['passwd'] == passwd:
                    login_user_session['username'] = user
                    print("登陆成功")
                    result = fun(*args, **kwargs)
                    return result
                else:
                    print("密码错误")
            else:
                print("该用户不存在")
    return wrappe1
     #判断是否有权限修改
def is_permisson(fun):
    def wrapper2(*args, **kwargs):
        print("判断是否有权限......")
        current_user = login_user_session.get('username')
        permission = db[current_user]['is_super']
        if permission == 1:
            result = fun(*args, **kwargs)
            return result
        else:
            print("用户%s没有权限" % (current_user))
    return wrapper2
@is_login
@is_permisson
def delete():
    return '正在删除用户信息'
result = delete()
print(result)


**** 被装饰的过程: 
1). delete = is_permission(delete)   # delete = wrapper2
2). delete = is_login(delete)        # delete = is_login(wrapper2)       # delete = wrapper1
*******被调用的过程: 
delete()    ------>  wrapper1()   ---> wrapper2()  ---> delete()
"""

练习部分

1.装饰器加日志并存入日志

  import datetime
  import os
  import json
	
	
  def rizhi(kan):
	    def zhuangshi(*args, **kwargs):
	        starttime = datetime.datetime.now()
	        hostname = os.getenv("computername")
	        file = open('rizhi.txt', 'a+')
	        json.dumps(str(starttime))
	        json.dumps(str(hostname))
	        file.write(str(starttime))
	        file.write(str(hostname))
	        file.close()
	        kan(*args, **kwargs)
	
	    return zhuangshi
	
	
	@rizhi
	def chakan():
	    result = 'you program is OK'
	    print("运行完成,函数结果为:%s" % result)
	    return result

2.斐波那契数列高速递归

import time


def num_catch(func):
    list = []

def wapper1(*args):
    if func(*args) not in list:
        list.append(func(*args))
        return func(*args)
    else:
        return func(*args)
return wapper1


def timeit(func):
    def wapper2(*args, **kwargs):
        start = time.time()
        time0 = func(*args, **kwargs)
        end = time.time()
        print("执行时间为:%s" % (end - start))
        return time0

    return wapper2


@num_catch
@timeit
def fibonacci(n):
    if (int(n) <= 2):
        return 1
    result = fibonacci(int(n) - 1) + fibonacci(int(n) - 2)
    return result
print(fibonacci(10))

3.求微信好友省份前五

import itchat

itchat.auto_login()
friends = itchat.get_friends(update=True)
prov_dict = {}
for fri_info in friends[1:]:
    prov = fri_info['Province']
    if prov and prov not in prov_di**加粗样式**ct.keys():
        prov_dict[prov] = 1
    elif prov:
        prov_dict[prov] += 1
prov_dict_top10 = sorted(prov_dict.items(),key=lambda x:x[1],reverse=True)[0:10]
print(prov_dict_top10)

模块与包

工具包的定义:模块就是工具包,想要使用这个工具包的工具就要导入这个模块

模块是非常简单的Python文件,一个python文件是一个python模块,两个python文件就是两个python模块。
模块导图:在这里插入图片描述
在这里插入图片描述

如何导入模块?
答:当解释器遇到import语句时,如果模块在当前的搜索路径就会被导入。
为什么一定要加上模块名导入呢?
答:因为可能存在这样一种情况:在多个模块中含有相同名称的函数,如果只是通过函数名来调用,解释器无法知道到底要调用哪个函数。所以如果像上述这样引入模块的时候,调用函数必须加上模块名。
在这里插入图片描述如果只需要用到模块中的某个函数/变量/类,如何导入呢?
答:通过这种方式引入的时候,调用函数时只能给出函数名,不能给出模块名,但是当两个模块中含有相同名称函数的时候,后面一次引入会覆盖前一次引入。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值