Python_Base_5

Python基础第五天


闭包与装饰器

闭包

如果在一个内部函数里,外作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包。

def f():
    x = 10
    def g():
        print(x)
    return g
f()()        # 10

(f()相当于g f()()相当于g())
h = f()
h()         # 10
闭包=内部函数g()+定义函数时的环境(x)


def f(x):
    def g():
        print(x)
    return g
h = f(1)
h()
也是闭包函数

装饰器

无参

import time                                              #使用time模块需要导包(调用方式:time.time)

def foo():
    start = time.time()    

# 是一个时间戳,表示从1970年1月1日00:00:00至现在的总秒数。
    print("foo...")
    time.sleep(1)    

# 添加休眠1秒,否则程序进行太快,看不出来运行时间。
    end = time.time()
    print(f"运行了{end-start}秒")
foo()               #在后面一定要调用否则运行不出来

不修改源代码的基础上给函数增加新的功能:
def foo():           #原函数
    print("foo...")
    time.sleep(1)
def show_time(func):    # 该函数用来展示时间
    def inner():
        start = time.time()
        func()
        end = time.time()
        print(f"运行了{end-start}秒")
    return inner
foo = show_time(foo)    # 这里类似闭包
foo()          # 增加计算运行时间功能

也可以这样写:
import time          # 一定要写的
def show_time(func):       # 该函数用来展示时间
    def inner():
        start = time.time()
        func()
        end = time.time()
        print(f"运行了{end-start}秒")
    return inner


@ show_time    

# 等价于foo = show_time(foo)
def foo():
    print("foo...")
    time.sleep(1)
@ show_time    

# 等价于too = show_time(too)
def too():
    print("too...")
    time.sleep(2)
foo()
too()

原函数参数

import time
def show_time(func):    # 该函数用来展示时间
    def inner(a, b):
        start = time.time()
        func(a, b)
        end = time.time()
        print(f"运行了{end-start}秒")
    return inner
@ show_time    

# 等价于add = show_time(add)
def add(a, b):
    print(a+b)
    time.sleep(1)
add(1,2)

关于*args **kwargs:
import time
def show_time(func):    # 该函数用来展示时间
    def inner(*args, **kwargs):
        start = time.time()
        func(*args, **kwargs)
        end = time.time()
        print(f"运行了{end-start}秒")
    return inner

 

@ show_time    # 等价于add = show_time(add)
def add(*args, **kwargs):
    sum = 0
    for i in args:
        sum += i
    print(sum)
    time.sleep(1)
add(1,2,3,4)

总结:

闭包:就是能够读取其他函数内部变量的函数
python闭包的作用:保存外部函数的变量,不会随着外部函数调用完而销毁

python闭包的条件:

  1. 函数嵌套
  2. 内部函数必须使用了外部函数的变量或参数
  3. 外部函数返回内部函数,这个使用了外部函数变量的内部函数被称为闭包

装饰器:实际上也是一个闭包函数,也是一个函数嵌套。
装饰器的作用:在不改变原函数的情况下,对已有的函数进行额外的功能扩展
装饰器的形成条件:

  1. 不修改已有函数的源代码
  2. 不修改已有函数的调用方式
  3. 给已有函数增加额外功能

区别:装饰器实质上是一个闭包函数,但是装饰器这个闭包函数的参数有且只有一个,并且是函数类型的。否则它就是闭包函数。


生成器和迭代器

知识点回顾:
列表生成式:[x for x in range(10)]

生成器

是一个可迭代对象
next()
用来调用值

g = (x for x in range(10))
print(next(g))       # 0 (获取g的第一个值)
print(next(g))       # 1 (获取g的第二个值)
print(next(g))       # 2 (获取g的第三个值)
# 不可以指定获取值,也不可以获取的超过此范围,否则报错。


for循环的本质就是调用next
r = (x for x in range(1,6))
for i in r:
    print(i)

创建生成器:

  1. (x for x in range(1,10))
  2. yield关键字实现

def f():
    print("11")
    yield 1
h = f()        # 表示一个生成器函数
print(next(h))
# yield相当于挂起,存档的意思


def a():
    print("a")
    yield 1
    print("aa")
    yield 2
for i in a():
    print(i)
# a
# 1
# aa
# 2

什么是可迭代对象?

  1. 从现象来看,只要可以for循环的都是可迭代对象
  2. 从本质来看,内置有iter方法的是可迭代对象

如:
l = [1, 2, 3]
l.__iter__()
t = (1, 2, 3)
t.__iter__()
d = {'name':'XX'}
d.__iter__()

迭代器

生成器就是迭代器

  1. 有iter方法
  2. 有next方法

l = [1, 2, 3]
d = iter(l)
print(next(d))       # 1
print(next(d))       # 2
print(next(d))       # 3

for循环内部的本质

  1. 调用可迭代对象的iter方法返回一个迭代器
  2. 不断地调用迭代器的next方法
  3. 处理异常

for i in [1, 2, 3]:
    print(i)
[1, 2, 3].__iter__()
# 1
# 2
# 3

die = iter([1, 2, 3])
while True:
    try:
        print(next(die))
    except StopIteration:
        break    

# 否则会报错(超过此范围)

迭代器的优点:

  1. 为序列和非序列类型提供了一种统一的迭代取值方式
  2. 可以只在需要的时候才去调用next来计算出一个值,就迭代器本身来说,同一时刻在内存中只有一个值。因而可以存放无限大的数据流。而对于其他容器类型,比如列表,就需要把所有的元素存放在内存中,受内存大小的限制,可以存放的值的个数是有限的。

递归函数

一个函数的内部调用了自己

def func():
    print("222")
    func()
func()
# 会一直打印222,最后报错

递归的原则:如果要定义一个递归函数,不想让它报错,就要设计一个出口并不断向出口接近

打印1-50
def func(x):
    if x == 51:
        return   # 结束当前函数
    print(x)
    return func(x+1)
func(1)

求9的阶乘
def f(n):
    if n == 1:
        return True
    return n*f(n-1)
a = f(9)
print(a)   # 362880

函数的递归:

是函数嵌套调用的一种特殊形式。函数嵌套调用一个函数的过程中调用了另外的函数,函数的递归在调用一个函数的过程中又调用回到本身。


模块与包

模块

定义:包含一系列数据、函数、类的文件,通常以.py结尾

模块导入

第一种:import 模块名                                     # 将某个模块的整体导入到当前模块中Python_Base_5_第1张图片
第二种:from 模块名 import 成员名                 # 将指定成员导入到当前模块中Python_Base_5_第2张图片
第三种:from 模块名 import *                         # 将指定模块的所有成员导入到当前模块中Python_Base_5_第3张图片

注意:导入进来的成员不要与当前模块成员名称相同。如果相同,按就近原则。(程序是从上往下进行的)
名字太长或有重复的可以取别名(as)Python_Base_5_第4张图片

隐藏成员

隐藏成员只对*导入有作用
模块中以_开头的成员不会被导入Python_Base_5_第5张图片Python_Base_5_第6张图片

 模块变量

__file__:  模块对应的文件路径名
文件绝对路径:从操作系统的根开始的
__name__:  模块自身的名字,可以判断是否为主模块
主模块:__main__
非主模块:真名


python的__main__的作用:
把一些非必要的代码放到main函数里面
main的标准语法:
if __name__ == '__main__':
    print('main在哪里哪里就是主程序')


模块分类

1.内置模块
在内部就可以直接使用的,如print、input
2.标准库模块
安装python的时候就已经安装可以使用的,用import导入即可,如,time、random
3.pip模块
通常是开源的,需要自己安装
通过pip install 模块名
卸载pip:  pip install 模块名
查询所有安装的第三方模块:pip list
Python_Base_5_第7张图片
4.用户自己编写的模块


 包 package

语句  -->  函数  -->  类  -->  模块  -->  包
包的定义:将模块以文件夹的形式进行分组管理,也就是管理模块的。
作用:让一些相关的模块组织在一起,使结构更加清晰。

包的导入Python_Base_5_第8张图片

 from 包.模块 import 成员Python_Base_5_第9张图片
import 模块名 as 新模块名Python_Base_5_第10张图片

 __init__.py

是包内必须存在的文件,会在包加载的时候被自动调用。
在导入这个包里面的模块的时候,__init__.py的代码也会自动执行,所以可以利用这个机制,在__init__.py里面写上关于这个包内模块的说明
调用:f007279b377744f487677236ad171185.png显示:Python_Base_5_第11张图片__init__内部:Python_Base_5_第12张图片包内文件hello内部:Python_Base_5_第13张图片


https://docs.python.org/3/py-modindex.html
可以由这个网站找到python的标准库(可以直接使用的)

 

 

 

 

你可能感兴趣的:(python,pycharm)