今日内容回顾

  • global与nonlocal
  • 函数名的多种用法
  • 闭包函数
  • 装饰器简介
  • 装饰器推导流程
  • 装饰器模板
  • 装饰器语法糖

global与nonlocal

money = 666
def index():
global money #局部修改全局变量 需要使用关键字声明
money = 123
index()
print(money) # 123
'''
global 在局部名称空间直接修改全局名称空间的数据
'''
def index():
name = 'jason'
def inner():
nonlocal name #内部局部修改外部局部
name = 'kevin'
inner()
print(name) # name就是kevin 不加声明则name就是jason 把握函数定义原则函数在定义阶段就已经把名字的查找顺序固定死了
index()
'''
nonlocal 在内部名称空间修改局部名称空间中的数据
''' name_list = ['jason', 'kevin']
def index():
name_list.append('oscar')
index()
print(name_list) # ['jason', 'kevin', 'oscar'] 当是可变类型使用了内置方法局部可以直接往全局列表里添加数据值

函数名的多种用法

函数其绑定的也是一块内存地址 只不过该地址里面存放的不是数据值而是一段代码 函数名加括号就会找到该代码并执行
# 用法1:函数名可以当做变量名赋值
def index():pass
res = index
res() # 本质就是在调用index函数
# 用法2:函数名可以当做函数的参数
def index():
print('from index')
def func(a):
print(a)
a()
func(index) # 打印函数名index ——> <function index at 0x00000159E2A660D0>然后再打印from index
# 用法3:函数名可以当做函数的返回值
def index():
print('from index')
def func():
print('from func')
return index
res = func() # 先执行func()打印from func再返回index赋值给变量名res
print(res) # 此时变量名res指的是index函数内存地址打印的是内存地址
res() # 相当于index加括号调用函数index函数体代码 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
}
whie True:
print('''
1.注册功能
2.登入功能
3.提现功能
4.转账功能
5.购物功能
''')
choice = input('请选择功能项>>>:').strip()
# 判断用户输入的编号在不在字典的K中
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 idex():
name = 'jasn'
def inner():
print(name) 闭包函数实际应用>>>:是另一种给函数体代码传参的方式!!! # 给函数体代码传参的方式1:代码里面缺什么变量名形参里面就补什么变量名
def register(name ,age):
print(f'''
姓名:{name}
年龄:{18}
''')
register('jason', 18)
# 给函数体代码传参的第二种方式:闭包函数
def outer(name, age):
# name = 'jason'
# age = 18
def register():
print('''
姓名:{name}
年龄:{age}
''')
return register
res = outer('jason', 18) # outer函数调用name=jason age=18返回值是register函数名赋值给res变量名
res() # res加括号相当于register加括号调用
res() # 并且res加括号可以反复调用
res = outer('kevin', 28)
res()
res()

装饰器简介

1.概念
什么叫装饰器?
在不改变被装饰对象原代码和调用方式的情况下给被装饰对象添加新的功能
2.本质
并不是一门新的技术 而是由函数参数、名称空间、函数名多种用法、闭包函数组合到一起的结果
3.口诀
对修改封闭 对扩展开放
4.储备知识
时间相关操作
import time
print(time.time()) # 时间戳(距离1970-01-01零时零分所经历的秒数)
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(1)
print('from index')
def home():
time.sleep(2)
print('from home')
'''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.tiem()
print('函数index的执行时间为:', end_time - start_time)
get_time()
'''3.函数体代码写死了 只能统计index的执行时间 如何才能做到统计更多的函数运行时间 直接传参变换统计的函数'''
def get_time(xxx):
start_time = time.time()
xxx()
end_time = time.tiem()
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):
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)
l1 = outer(index)
index = outer(index)
index()
home = outer(home)
home()
'''6.上述装饰器只能装饰无参函数 兼容性太差'''
def func(a):
time.sleep(0.1)
print('from func', a) def func1(a, b):
time.sleep(0.2)
print('from func1', a, b) def func2():
time.sleep(0.3)
print('from func2') def outer(xxx):
def get_time(a, b):
start_time = time.time()
xxx(a, b)
end_time = time.time()
print('函数的执行时间为:', end_time - start_time)
return get_time
func1 = outer(func1)
func1(1, 2)
func = outer(func)
func(1)
func2 = outer(func2)
fucn2()
'''7.被装饰函数不知道有没有参数以及有几个参数 如何兼容'''
def func(a):
time.sleep(o.1)
print('from func', a) def func1(a, b):
time.sleep(0.2)
print('from func1', a, b)
def ouet(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(0.1)
print('from func', a)
return 'func'
def func1(a, b):
time.sleep(0.2)
print('from func1', a, b)
return 'func1' def outer(xxx):
def get_time(*args, **kwargs):
start_time = time.time()
res1 = xxx(*args, **kwargs)
end_time = time.time()
print('函数执行时间为:', end_time - start_time)
return res1
return get_time func = outer(func)
res = func(123)
print(res) func1 = outer(func1)
res = func1(123, 123)
print(res)

装饰器模板

---------------------------务必掌握----------------------------
def outer(func):
def inner(*args, **kwargs):
print('执行函数前可以添加的额外功能')
res = func(*args, **kwags) # 执行被装饰的函数
print('执行函数之后可以添加的额外功能')
return res # 将被装饰函数执行之后的返回值返回
return inner

装饰器语法糖

def outer(func_name):
def inner(*args, **kwargs):
print('执行被装饰对象之前可以做的额外操作')
res = func_name(*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
# 拔高练习(有点难度)
# 执行被装饰的函数 只要有一次认证成功 那么后续的校验都通过
is_flag = False def outer(func):
def inner(*args, **kwargs):
global is_flag
if is_flag == False:
user = input('校验用户>>>:').strip()
pwd = input('校验密码>>>:').strip()
if user == 'jason' and pwd == '123':
is_flag = True
res = func(*args, **kwargs)
return res
elif is_flag == True:
res = func(*args, **kwargs)
return res
return inner @outer
def register():
while True:
name = input('请注册您的用户名>>>:').strip()
password = input('请创建您的密码>>>').strip()
with open(r'z.txt', 'r', encoding='utf8') as read_f:
for read_line in read_f:
name1, pwd1 = read_line.split('|')
if name1 == name:
print('用户已存在')
break
else:
with open(r'z.txt', 'a', encoding='utf8') as write_f:
write_f.write(f'{name}|{password}\n')
return '注册成功' @outer
def login():
user_name = input('请输入您的用户名>>>:').strip()
user_pwd = input('请输入您的密码>>>:').strip()
with open(r'z.txt', 'r', encoding='utf8') as read_f:
for line in read_f:
real_name, real_pwd = line.split('|')
if user_name == real_name and user_pwd == real_pwd.strip('\n'):
return '登入成功'
return '用户名或密码错误' @outer
def transfer():
print('转账功能')
return '转账成功' @outer
def withdraw():
balance = 100
while True:
withdraw_money = int(input('请输入您要提现的金额>>>:'))
if withdraw_money <= balance:
print(f'提现成功 剩余余额{balance - withdraw_money}')
return '提现成功'
else:
print(f'余额不足 {withdraw_money}提现不了')
continue func_dict = {'1': register, '2': login, '3': transfer, '4': withdraw} while True:
print('''
1.注册功能
2.登入功能
3.转账功能
4.提现功能
''')
choice = input('请输入功能项>>>:').strip()
if choice in func_dict:
index = func_dict.get(choice)()
print(index)
else:
print('无该功能项')

global与nonlocal、函数名用法、闭包函数、装饰器的更多相关文章

  1. 函数名、闭包、装饰器 day11

    1, 函数名的内存地址,print(func) 2, 函数名可以赋值给其他变量 3, 函数名可以当做容器类的元素 4, 函数名可以当做函数的参数. 5, 函数名可以当做函数的返回值. 学名:第一对象 ...

  2. Day 11 函数名,闭包,装饰器. +作业

    '''一.函数名.def func(): print(5555)print(func)#输出结果 <function func at 0x026B5E88> 打印函数地址. # 1. 函数 ...

  3. python函数知识七 闭包、装饰器一(入门)、装饰器二(进阶)

    21.闭包 闭包:在嵌套函数内,使用非全局变量(且不使用本层变量) 闭包的作用:1.保证数据的安全性(纯洁度).2.装饰器使用 .__closure__判断是否是闭包 def func(): a = ...

  4. Python虚拟机函数机制之闭包和装饰器(七)

    函数中局部变量的访问 在完成了对函数参数的剖析后,我们再来看看,在Python中,函数的局部变量时如何实现的.前面提到过,函数参数也是一种局部变量.所以,其实局部变量的实现机制与函数参数的实现机制是完 ...

  5. Python函数进阶:闭包、装饰器、生成器、协程

    返回目录 本篇索引 (1)闭包 (2)装饰器 (3)生成器 (4)协程 (1)闭包 闭包(closure)是很多现代编程语言都有的特点,像C++.Java.JavaScript等都实现或部分实现了闭包 ...

  6. python函数作用域,闭包,装饰器

    第一:函数作用域: L:local 函数内部作用域 E:enclosing       函数内部与内嵌函数之间(闭包) G:global            全局作用域 B:build_in    ...

  7. python基础16_闭包_装饰器

    不了解是否其他语言也有类似 python 装饰器这样的东西. 最近才发现ECMAScript6也是有生成器函数的,也有 yield  generator 装饰器的基础知识是闭包: # 闭包:嵌套函数, ...

  8. Python高级--闭包与装饰器

    前言:在Python中,闭包是一种非常有用的功能!它通常与装饰器一起搭配使用,可以在不改变被装饰函数的功能的基础上,完成更多的功能.如权限认证. 一.如何定义闭包 1.闭包就是两个嵌套的函数,外层函数 ...

  9. Python—闭包和装饰器

    闭包 定义:内部函数对外部函数变量的引用,则将该函数与用到的变量称为闭包. 闭包必须满足以下三个条件: 必须有一个内嵌函数. 内嵌函数必须引用外部函数中的变量. 外部函数返回值必须是内嵌函数的引用. ...

  10. python_函数名的应用、闭包、装饰器

    0.动态传参内容补充: 0.1 单纯运行如下函数不会报错. def func1(*args,**kwargs): pass func1() 0.2 *的魔性用法 * 在函数定义的时候,代表聚合. *在 ...

随机推荐

  1. Java SE 19 虚拟线程

    Java SE 19 虚拟线程 作者:Grey 原文地址: 博客园:Java SE 19 虚拟线程 CSDN:Java SE 19 虚拟线程 说明 虚拟线程(Virtual Threads)是在Pro ...

  2. TCP和UDP的区别与联系以及网络字节序和主机字节序的转换函数实践

    TCP和UDP的区别 TCP是一个面向连接的.可靠的.基于字节流的传输层协议. 而UDP是一个面向无连接的传输层协议. 具体来分析,和 UDP 相比,TCP 有三大核心特性: 面向连接:所谓的连接,指 ...

  3. 设计模式之观察者模式_C++

    1 // ADBHelper.cpp : This file contains the 'main' function. Program execution begins and ends there ...

  4. 关于多个 Kubernetes 集群指标的采集操作

    简介 在使用观测云期间,有时需要针对一个工作空间接入多个 Kubernetes 集群指标,通过观测云提供的全局 Tag 的方式来进行区分,大大提高了效率.下面是我总结的操作步骤. 当集群中只有一个采集 ...

  5. Tomcat 调优之从 Linux 内核源码层面看 Tcp backlog

    前两天看到一群里在讨论 Tomcat 参数调优,看到不止一个人说通过 accept-count 来配置线程池大小,我笑了笑,看来其实很多人并不太了解我们用的最多的 WebServer Tomcat,这 ...

  6. 23.mixin类源码解析

    mixin类用于提供视图的基本操作行为,注意mixin类提供动作方法,而不是直接定义处理程序方法 例如.get() .post(),这允许更灵活的定义,mixin从rest_framework.mix ...

  7. webRTC demo

    准备: 信令服务 前端页面用于视频通话 demo github 地址. 前端页面 为了使 demo 尽量简单,功能页面如下,即包含登录.通过对方手机号拨打电话的功能.在实际生成过程中,未必使用的手机号 ...

  8. HTML5+CSS3常见布局方式

    1.等高布局 1.1 代码 等高布局是指子元素在父元素中高度相等的布局方式 <div class="father"> <div class="f1&qu ...

  9. 万字详解JVM,让你一文吃透

    摘要:本文将带大家详细地了解关于JVM的一些知识点. 本文分享自华为云社区<[JVM]关于JVM,你需要掌握这些 | 一文彻底吃透JVM系列>,作者: 冰 河 . JDK 是什么? JDK ...

  10. webpack -- element-ui 的按需引入

    简单说明原理: 使用babel-plugin-component实现按需引入.打包.将webpack配置成多入口,保证最终打包的目录结构符合babel-plugin-component插件的要求,实现 ...