函数名的多种用法

函数名其实绑定的也是一块内存地址 只不过该地址里面存放的不是数据值而是一段代码 函数名加括号就会找到该代码并执行

1.可以当作变量名赋值

def index():pass
res = index
res()

2.可以当作函数的参数

def index():
print('from index')
def func(a):
print(a)
a()
func(index)

3.可以当作函数的返回值

def index()
print('from index')
def func():
print('from func')
return index
res = func()
print(res)
res() def index():
print('from index')
def func():
print('from func')
return func res = index()
print(res)
res()

4.可以当作容器类型(可以存放多个数据的数据值类型)的数据

def register():
print('注册功能') def login():
print('登录功能') def withdraw():
print('提现功能') def transfer():
print('转账功能') def shopping():
print('购物功能') # 定义功能编号与功能的对应关系
func_dict = {
'1':register,
'2':login,
'3':withdraw,
'4':transfer,
'5':shopping
} while True:
print(
"""
1.注册功能
2.登录功能
3.提现功能
4.转账功能
5.购物功能
""")
choice = input('请输入功能编号>>>:').strip()
if choice in func_dict:
func_name = func_dict.get(choice)
func_name()
else:
print('功能编号不存在')
# if choice == '1':
# register()
# elif choice == '2':
# login()
# elif choice == '3':
# withdraw()
# elif choice == '4':
# transfer()
# elif choice == '5':
# shopping()
# else:
# print('去你妹的 终于写完了')

闭包函数

定义在函数内部的函数,并且用到了外部名称空间的名字

1.定义在函数内部

2.用到外部函数名称空间中的名字

def index():
name = 'jason'
def inner():
print(name)
闭包函数实际应用>>>:是另外一种给函数体代码传参的方式!!!
# 给函数体代码传参的方式1:代码里面缺什么变量名形参就补什么变量名
def register(name,age):
print(f"""
姓名:{name}
年龄:{age}
""")
register('jason',18)
# 给函数体代码传参的方式2:闭包函数
def outer(name,age):
# name = 'jason'
# age = 18
def register():
print(f"""
姓名:{name}
年龄:{age}
""")
return register
res = outer('jason',18)
res()
res()
res = outer('kevin', 28)
res()
res()
res()

装饰器简介

1.概念
在不改变被装饰对象原代码和调用方式的情况下给被装饰对象添加新的功能
2.本质
并不是一门新的技术 而是由函数参数、名称空间、函数名多种用法、闭包函数组合到一起的结果
3.口诀
对修改封闭 对扩展开放
4.储备知识
时间相关操作
import time
# print(time.time()) # 时间戳(距离1970-01-01 00:00:00所经历的秒数)
time.sleep(3)
print('睡醒了 干饭')
count = 0
# 循环之前先获取时间戳
start_time = time.time()
while count < 100:
print('哈哈哈')
count += 1
end_time = time.time()
print('循环消耗的时间:', end_time - start_time)

装饰器推导流程


import time # def index():
# time.sleep(2)
# print('from index')
#
#
# def home():
# time.sleep(3)
# print('from home') # start_time = time.time()
# index()
# end_time = time.time()
# print('函数index的执行时间为>>>',end_time - start_time)
'''1.直接在调用index函数的前后添加代码'''
# start_time = time.time()
# index()
# end_time = time.time()
# print('函数index的执行时间为>>>',end_time - start_time)
'''2.index调用的地方较多 代码不可能反复拷贝>>>:相同的代码需要在不同的位置反复执行>>>:函数'''
# def get_time():
# start_time = time.time()
# index()
# end_time = time.time()
# print('函数index的执行时间为>>>',end_time - start_time)
# get_time()
'''3.函数体代码写死了 只能统计index的执行时间 如何才能做到统计更多的函数运行时间 直接传参变换统计的函数''' #
# def get_time(xxx):
# start_time = time.time()
# xxx()
# end_time = time.time()
# print('函数的执行时间为>>>', end_time - start_time)
#
#
# get_time(index)
# get_time(home) '''4.虽然实现了一定的兼容性 但是并不符合装饰器的特征 第一种传参不行 只能考虑闭包''' # def outer(xxx):
# # xxx = index
# def get_time():
# start_time = time.time()
# xxx()
# end_time = time.time()
# print('函数的执行时间为>>>', end_time - start_time)
# return get_time
# res = outer(index)
# res()
# res1 = outer(home)
# res1() '''5.调用方式还是不对 如何变形>>>:变量名赋值绑定(**********)''' # def outer(xxx):
# # xxx = index
# def get_time():
# start_time = time.time()
# xxx()
# end_time = time.time()
# print('函数的执行时间为>>>', end_time - start_time)
#
# return get_time # res = outer(index)
# res1 = outer(index)
# res2 = outer(index)
# jason = outer(index)
# index = outer(index)
# index()
# home = outer(home)
# home()
'''6.上述装饰器只能装饰无参函数 兼容性太差''' # def func(a):
# time.sleep(3)
# print('from func', a)
# # func(123)
#
# def func1(a, b):
# time.sleep(2)
# print('from func1', a, b)
#
# def func2():
# time.sleep(2)
# print('from func2') # def outer(xxx):
# def get_time(a,b):
# start_time = time.time()
# xxx()
# end_time = time.time()
# print('函数的执行时间为>>>', end_time - start_time)
# return get_time # func1 = outer(func1)
# func(1,2)
# func = outer(func)
# func(1)
# func2 = outer(func2)
# func2() '''7.被装饰的函数不知道没有参数以及几个参数 如何兼容''' # def func(a):
# time.sleep(3)
# print('from func', a)
#
# def func1(a, b):
# time.sleep(2)
# print('from func1', a, b)
#
# def outer(xxx):
# def get_time(*args, **kwargs): # get_time(1,2,3) args = (1,2,3)
# start_time = time.time()
# xxx(*args, **kwargs) # xxx(*(1,2,3)) xxx(1,2,3)
# end_time = time.time()
# print('函数的执行时间为>>>', end_time - start_time)
# return get_time
# func = outer(func)
# func(123)
# func1 = outer(func1)
# func1(1,2)
'''8.如果被装饰的函数有返回值'''
def func(a):
time.sleep(3)
print('from func', a)
return 'func'
def func1(a, b):
time.sleep(2)
print('from func1', a, b)
return 'func1'
def outer(xxx):
def get_time(*args, **kwargs):
start_time = time.time()
res = xxx(*args, **kwargs)
end_time = time.time()
print('函数的执行时间为>>>', end_time - start_time)
return res
return get_time
# func = outer(func)
# res = func(123)
# print(res) func1 = outer(func1)
res = func1(123,333)
print(res)

装饰器模板

# 必须掌握
def outer(func): # 形参func将来用于绑定真正被装饰对象的内存地址
def inner(*args, **kwargs):
# 执行被装饰对象之前可以作的操作
res = func(*args, **kwargs)
# 执行被装饰对象之后可以作的额外操作
return res
return inner

装饰器语法糖

def outer(func):
def inner(*args, **kwargs):
print('执行被装饰对象之前可以作的操作')
res = func(*args, **kwargs)
print('执行被装饰对象之后可以作的额外操作')
return res
return inner
@outer # func = outer(func)
def func():
print('from func')
return 'func'
@outer # index = outer(index)
def index():
print('from index')
return 'index' func()
index()

小练习

编写一个用户认证装饰器

函数:register login transfer withdraw

基本要求

执行每个函数的时候必须先校验身份 eg: jason 123

拔高练习(有点难度)

执行被装饰的函数 只要有一次认证成功 那么后续的校验都通过

提示:全局变量 记录当前用户是否认证

user_login = False   # 写一个是否登录过的条件 user_login
def outer(func):
def inner(*args, **kwargs):
global user_login # 将user_login变量设置成全局变量
if user_login: # 为True执行装饰器功能
ret = func(*args, **kwargs)
return ret
else:
# 执行用户校验功能
username = input('username>>>:').strip()
password = input('password>>>:').strip()
if username == 'jason' and password == '123':
user_login = True # 校验后为True 下面执行装饰器功能
ret = func(*args, **kwargs)
return ret
else:
print('用户名或密码不正确')
return inner # @outer
# def register():
# print('用户注册功能') @outer
def login():
print('登录功能') def transfer():
print('转账功能') def withdraw():
print('提现功能') # register()
login()
transfer()
withdraw()

python进阶之路11 闭包函数 装饰器的更多相关文章

  1. 【Python 函数对象 命名空间与作用域 闭包函数 装饰器 迭代器 内置函数】

    一.函数对象 函数(Function)作为程序语言中不可或缺的一部分,但函数作为第一类对象(First-Class Object)却是 Python 函数的一大特性. 那到底什么是第一类对象(Firs ...

  2. Python的高级特性7:闭包和装饰器

    本节跟第三节关系密切,最好放在一起来看:python的高级特性3:神奇的__call__与返回函数 一.闭包:闭包不好解释,只能先看下面这个例子: In [23]: def outer(part1): ...

  3. python 生成器,迭代器,闭包,装饰器

    1.生成器,迭代器,闭包,装饰器的优点 生成器就是一类特殊的迭代器 迭代器的优点也即生成器的优点: 1.节约内存.python在使用生成器时对延迟操作提供了支持. 2.迭代到下一次的调用时,所使用的参 ...

  4. python闭包函数&装饰器

    一.函数引用 函数可以被引用 函数可以被赋值给一个变量 def hogwarts(): print("hogwarts") # hogwarts() # 函数调用 print(ho ...

  5. python 内嵌函数, 闭包, 函数装饰器

    一.  函数内嵌 闭包 在python中,函数可以作为返回值, 可以给变量赋值. 在python中, 内置函数必须被显示的调用, 否则不会执行. #!/usr/bin/env python #-*- ...

  6. Python记录9:函数4:名称空间作用域+闭包函数+装饰器

    ''' 一: 名称空间namespaces     名称空间就是存放名字与值绑定关系的内存空间 二: 名称空间分为三种     内置名称空间:         1. 特点: 存放是python解释器自 ...

  7. Python作用域-->闭包函数-->装饰器

    1.作用域: 在python中,作用域分为两种:全局作用域和局部作用域. 全局作用域是定义在文件级别的变量,函数名.而局部作用域,则是定义函数内部. 关于作用域,我要理解两点:a.在全局不能访问到局部 ...

  8. python3 闭包函数 装饰器

    闭包函数 1.闭:定义在函数内部的函数 2.包:内部函数引用了外部函数作用域的名字 在函数编程中经常用到闭包.闭包是什么,它是怎么产生的及用来解决什么问题呢.给出字面的定义先:闭包是由函数及其相关的引 ...

  9. Day 12 闭包函数,装饰器

    闭包函数 回顾: 1.函数对象:可以将定义在函数内的函数返回到全局使用.从而打破了函数层级限制 2.名称空间与作用域:作用域关系在函数定义阶段时就已经固定死了,与调用位置无关,即在任意位置调用函数都需 ...

  10. 【0812 | Day 13】闭包函数/装饰器/迭代器

    目录 闭包函数 无参装饰器 有参装饰器 迭代器 闭包函数 一.什么是闭包? 闭包指的是:函数内部函数对外部作用域而非全局作用域的引用. def outter(): x = 1 def inner(): ...

随机推荐

  1. react.js 实现音乐播放、下一曲、以及删除歌曲(仅播放列表)

    import React, { Component } from 'react'; export default class Music extends Component {   construct ...

  2. CVE-2021-44832 log4j_2.17.0 RCE复现与吐槽

    先说一句,这傻x洞能给cve就离谱,大半夜给人喊起来浪费时间看了一个小时. 先说利用条件: 需要加载"特定"的配置文件信息,或者说实际利用中需要能够修改配置文件(你都能替换配置文件 ...

  3. springboot整合mybatisplus遇到的错误

    完全跟着mybatis_plus官网的案例一步一步来的,但是到junit的时候突然报错 Internal Error occurred. org.junit.platform.commons.JUni ...

  4. 基于 Docker 构建轻量级 CI 系统:Gitea 与 Woodpecker CI 集成

    WoodpeckerCI 是一个由社区维护的 DroneCI 分支,使用 Apache License 2.0 许可证发布.社区版进一步扩展了 pipeline 的功能特性.支持对文件路径设置 pip ...

  5. kubernetes之kubectl与YAML详解1

    k8s集群的日志,带有组件的信息,多看日志. kubectl命令汇总 kubectl命令汇总 kubectl命令帮助信息 [root@mcwk8s04 ~]# kubectl -h kubectl c ...

  6. 小程序基础之引用vant组件库

    第一步:终端npm init -y 会生成一个pack.json文件.(初始化包管理,记录这个项目用的包.) 第二步:npm install 会生成一个 package-lock.json文件.(一个 ...

  7. Linux配置篇 - Vmware网络配置

    网络配置 VM 网络详解 vmware提供了三种网络工作模式,Bridged(桥接模式).NAT(网络地址转换模式).Host-Only(仅主机模式): vmware网络配置步骤:编辑 -> 虚 ...

  8. Android Studio 卡在download fastutil下载慢

    需要替换国内镜像,现在阿里云地址已经更新了.需要使用新的地址.可以参考 https://developer.aliyun.com/mvn/guide 以下是更改buil.gradle文件的代码 // ...

  9. devexpress中searchLookUpEdit赋值不显示

    给searchLookUpEdit进行赋值的时候使用 string str="123"; searchLookUpEdit1.EditValue = str; 一直不显示或者显示为 ...

  10. CAP 7.0 版本发布通告 - 支持延迟消息,性能炸了?

    前言 今天,我们很高兴宣布 CAP 发布 7.0 版本正式版,我们在这个版本中带来了大批新特性以及对性能的优化和改进. 自从今年 1月份发布 6.0 版本以来,已经过去了快1年的时间.在过去的将近1年 ...