第十一节课

装饰器的引入

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

def fun(fn, *args, **kwargs): #对其他函数拓展功能的方法: 定义一个功能函数让这个函数在目标函数里面运行并调用它
    print('程序开始执行')
    r = fn(*args, **kwargs) #使用不定长参数来解决
    print(r)
    print('程序执行结束')


def fun1():
    print('我是fun1函数')



def dyg(a, b):
    return a + b


def drg(a, b):  # (ocp)原则 o open 开放对代码的扩展,c close 关闭对代码的修改。
    return a * b


# r = dyg(1, 2)
# print(r)

fun(fun1)  # 执行结果为: 程序开始执行
#                        我是fun1函数
#                        程序执行结束
# fun(dyg, 1, 2) # 执行的结果 : 程序开始执行
#                              3
#                           程序执行结束

装饰器的使用

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

装饰器是一个特殊的闭包

#通用装饰器
def fun(fn):   # 装饰器

    def new_fun1(*args, **kwargs):  # 不定长参数,不管你传递多少参数或者不传递参数,不定长参数都可以保证不报错。
        print('程序开始执行')
        fn(*args, **kwargs)
        print('程序执行结束')

    return new_fun1


@fun  #装饰器的语法糖方法   @fun = r = fun(fun2)
def fun2():
    print('我是fun2函数')

fun2()
# r = fun(fun2)  # 首先调用外层函数, 然后内层不会暂时不会执行的,因为没有调用,外层函数的调用等于外层函数的返回值。
# 那么现在外层函数的返回值是内层函数的对象,内层函数的调用等于内层函数的函数对象加上一个括号,也就是调用,那么也就是外层函数的调用加上括号。
# r()
# fun = 外层函数的返回值,fun1 = r = fun()   fun() = r()
# fun(fun2) 中的fun2 是实参, 那么fun这个函数的形参就等于实参  fn = fun2

推导式

一、推导式分为 列表推导式,字典推导式,集合推导式等。在这里我们主要说的是列表推导式也是用的最多的一种。
二、列表推导是是pytho构建列表(list)的一种快捷方式可以使用简单的代码就创建出一个列表简单理解就是用一个旧的列表构建出一个新列表
三、语法:
[表达式 for 变量 in 旧列表]
[表达式 for 变量 in 旧列表 if 条件]

lis = ['jia', 'jie', 'jiang', 'yang', 'yang']
lis1 = [i for i in lis if len(i) > 3]
print(lis1)

# 需求, 求1~100之间的偶数
lis2 = [i for i in range(1, 101) if i % 2 == 0]
print(lis2)
# 需求, 求1~100之间的偶数,还要整除4的数
lis3 = [i for i in range(1, 101) if i % 2 == 0 and i % 4 == 0]
print(lis3)

生成器

生成器
背景
通过列表推导式我们可以直接创建出一个列表,但是受到内存的限制,我们不可能创造出一个无限大的列表。而且创建一个有200万个元素的列表,会占用很大的内存空间,而这个时候我们仅仅需要访问列表中几个元素,那么后面的元素就占用着空间就是一种浪费的行为。那么我们可不可以用几个元素就创建出几个元素。这样在一定程度上就优化了内存。那么在Python中有一种一边循环一边计算的机制就是生成器
创建生成器的方式
一、通过列表推导式的方式

# 把列表解析的[]换成()得到的就是生成器表达式
g = (x * 3 for x in range(10)) # Generator 生成器
print(next(g)) # 得 0
print(next(g)) # 得 3 这里 next(g) == g.__next__()

二、通过函数的方式

def f():
	n = 0 
	while n < 5:
		n += 1
		yield n
m = f()
print(next(m)) # 得 1
print(next(m)) # 得 2  当值取完了再取时会报错:StopIteration

特性:

一、一个包含yield关键字的函数就是一个生成器函数。每次运行到yield的时候,函数会暂停,并且保存当前的运行状态,返回返回当前的数值,并在下一次执行next方法的时候,又从当前位置继续往下走。
二、可以使用for循环获取值,也可以使用next获取生成器函数的值
三、yield可以为我们从函数中返回值,但是yield又不同于return,return的执行意味着程序的结束,调用生成器函数不会得到返回的具体的值,而是得到一个可迭代的对象。每一次获取这个可迭代对象的值,就能推动函数的执行,获取新的返回值。直到函数执行结束

迭代器

一、迭代器是访问集合元素的一种方式。迭代器是一个可以记住遍历位置的对象。迭代器对象从集合的第一个元素开始访问,直到所有元素被访问结束。
二、可以被next()函数调用并不断返回下一个值的对象称为迭代器lterator
三、生成器是可迭代的,也是迭代器。列表也是可迭代的,但是列表本身迭代器。
四、通过iter()函数可以将可迭代的变成一个迭代器

# 1、字符创创建迭代器对象
str1 = 'Python'
iter1 = iter ( str1 )
 
# 2、list对象创建迭代器
list1 = [1,2,3,4]
iter2 = iter ( list1 )
 
# 3、tuple(元祖) 对象创建迭代器
tuple1 = ( 1,2,3,4 )
iter3 = iter ( tuple1 )
 
# for 循环遍历迭代器对象
for x in iter1 :
    print ( x , end = ' ' ) # P y t h o n
 
# next() 函数遍历迭代器
while True :
    try :
        print ( next ( iter3 ) )
    except StopIteration :
        break

PEP8代码规范

1、缩进使用4个空格, 空格是首选的缩进方式. Python3
不允许混合使用制表符和空格来缩进.
2、每一行最大长度限制在79个字符以内.
3、顶层函数、类的定义, 前后使用两个空行隔开.
4、import 导入
导入建议在不同的行, 例如:
import os
import sys
不建议如下导包: import os, sys
但是可以如下: from subprocess import Popen, PIPE
5、导包位于文件顶部, 在模块注释、文档字符串之后, 全局变量、常量 之前. 导入按照以下顺序分组:

 标准库导入
 相关第三方导入
 本地应用/库导入
 在每一组导入之间加入空行

6、Python 中定义字符串使用双引号、单引号是相同的, 尽量保持使用同一方式定义字符串. 当一个字符串包含单引号或者双引号时, 在最外层使用不同的符号来避免使用反斜杠转义, 从而提高可读性.
7、表达式和语句中的空格:
避免在小括号、方括号、花括号后跟空格.
避免在逗号、分好、冒号之前添加空格.
冒号在切片中就像二元运算符, 两边要有相同数量的空格. 如果某个切片参数省略, 空格也省略.
避免为了和另外一个赋值语句对齐, 在赋值运算符附加多个空格.
避免在表达式尾部添加空格, 因为尾部空格通常看不见, 会产生混乱.
总是在二元运算符两边加一个空格, 赋值(=),增量赋值(+=,-=),比较(==,<,>,!=,<>,<=,>=,in,not,in,is,is not),布尔(and, or, not
避免将小的代码块和 if/for/while 放在同一行, 要避免代码行太长.
8、永远不要使用字母 ‘l’(小写的L), ‘O’(大写的O), 或者 ‘I’(大写的I) 作为 单字符变量名. 在有些字体里, 这些字符无法和数字0和1区分, 如果想用 ‘l’, 用 ‘L’ 代替.
9、类名一般使用首字母大写的约定.
10、函数名应该小写, 如果想提高可读性可以用下划线分隔.
11、如果函数的参数名和已有的关键词冲突, 在最后加单一下划线比缩写或随意拼写更好. 因此 class_ 比 clss 更好.(也许最好用同义词来避免这种冲突).
12、方法名和实例变量使用下划线分割的小写单词, 以提高可读性

作业

import time

def yx(fn):

    def sj():
        ks = time.time()
        fn()
        js = time.time()
        print('程序一共运行了%s的数时间' % (js - ks))

    return sj


@yx  #语法糖方法
def fun():
    for i in range(10000000):
        pass


fun()

#普通使用方法
#r = yx(fun)
#r()

猜你喜欢

转载自blog.csdn.net/weixin_55924597/article/details/115465300