函数(三)

闭包函数

为函数传参有两种方式

方式一:以参数的形式

def func(x):
    print(x)

func(1)

# 1

方式二:包给函数

def outter(x):
    def inner():
        print(x)
    return inner

inner = outter(1)
inner()

# 1

闭包:闭是封闭(函数内部函数),包是包含(该内部函数对外部作用域的变量的引用,而非对全局作用域的变量的引用)。闭包指的是函数内部函数对外部作用域的引用,而非对全局作用域的引用。

闭包函数就是把变量和函数一起包起来,下次要用直接调用。

闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域。

装饰器

函数是具备某一功能的工具,装饰器就是可以为被装饰对象添加额外的功能。因此装饰器就是定义一个函数,只不过这个函数的功能就是给其他函数添加额外的功能。

需要注意的是:

  • 装饰器本身其实是可以任意可调用的对象
  • 被装饰的对象也可以是任意可调用的对象

装饰器的实现必须遵循两个原则:

  1. 不修改被装饰对象的源代码
  2. 不修改被装饰对象的调用方式
1. 装饰器:
import time

def deco(func):
    def inner():
    	start = time.time()
    	func()
    	end = time.time()
    	print(end - start)
    
    return inner

def index():
    print('Hello, index')
    time.sleep(1)

index = deco(index)
index()
2. 给inner()方法传参:
import time

def deco(func):
    def inner(*args, **kwargs):
    	start = time.time()
        res = func(*args, **kwargs)
        end = time.time()
        print(end - start)
        
        return res
    
    return inner

def index():
    print('Hello, index')
    time.sleep(1)

index = deco(index)
index()
3. 语法糖:

在被装饰函数的正上方,而且是单独一行的写上@装饰器名

4. 装饰器模板:
def deco(func):
    def inner(*args, **kwargs):	# inner是未来要运行的代码
        # 需要添加的功能写这里
        res = func(*args, **kwargs) # func是被装饰的函数
        return res
    return inner
5. 三层装饰器:就是给双层装饰器加参数,多个参数也只需在三层装饰器多加几个就可以了
def auth(engine):
    def login(func):
        def inner(*args, **kwargs):
            if engine == 'file':
                username = input('username:')
                password = input('password:')
                if username == 'xiaowu' and password == '123':
                    print('登录成功')
                    res = func(*args, **kwargs)
                    return res
                else:
                    print('登录失败')
            elif engine == 'db':
                print('账号密码来自数据库,非法请求')
        return inner
    return login

@auth('file') 
def shopping():
    print('shopping')

shopping()

迭代器

迭代器:迭代的工具。迭代是更新换代,迭代也可以说成是重复,但是每一次的重复都是基于上一次的结果推出下一次的结果。

一、可迭代对象

对象:python中一切皆对象

在这一切的对象,只要内置有__iter__方法的,都叫可迭代对象。

可迭代对象:除了数字类型和函数,字符串/列表/字典/元组/集合/文件都是可迭代对象。

二、迭代器对象

在字符串、列表、字典、元组、集合、文件这些可迭代对象中,只有字符串、列表和元组是依赖索引取值的,其他的可迭代对象都是无法依赖索引取值的,所以我们要找到一个方法让其他的可迭代对象不依赖索引也可以取值。

可迭代对象执行__iter__方法会成为迭代器对象,然后迭代器对象可以使用__next__方法获取值。

迭代器对象:具有__iter__方法和__next__方法的就叫做迭代器对象,只有文件是迭代器对象。

迭代器对象一定是可迭代对象,可迭代对象不一定是迭代器对象

dic = {'a': 1, 'b': 2, 'c': 3}
dic_iter = dic.__iter__()
print(dic_iter.__next__())
print(dic_iter.__next__())
print(dic_iter.__next__())
print(dic_iter.__next__())

# a
# b
# c
# StopIteration # 没有第四个值会报错,我们可以捕捉它
# 使用while循环精简代码,并使用try...except...异常方法,出现异常后捕捉异常并终止代码
dic = {'a': 1, 'b': 2, 'c': 3}
dic_iter = dic.__iter__()
while True:
    try:
        print(dic_iter.__next__())
    except StopIteration:
        break

# a
# b
# c

三、for循环

for循环又称为迭代循环,in后面的对象必须是可迭代对象。

因为迭代器对象使用__iter__方法后还是迭代器本身,因此for循环不用考虑in后面的对象是可迭代对象还是迭代器对象。

for循环的工作过程

  1. 把可迭代对象或迭代器对象用__iter__方法转换成迭代器对象
  2. 使用__next__方法取出迭代器里的所有值
  3. 当用__next__方法取尽迭代器里的所有值后,一定会报错,然后通过异常捕捉退出while循环

for循环解决了不依赖索引就可以取值

原文地址:https://www.cnblogs.com/yunluo/p/11341103.html