函数名的多种用法

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

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. 前端图形:SVG与Canvas

    00.前端图形 前端代码实现图形的几种方式:CSS.SVG.Canvas(主要是JavaScript编码) CSS也是可以画图的,需要借助于高宽.边框border.clip-path裁剪.渐变色背景等 ...

  2. 再有人说synchronized是重量级锁,就把这篇文章扔给他看

    synchronized作为Java程序员最常用同步工具,很多人却对它的用法和实现原理一知半解,以至于还有不少人认为synchronized是重量级锁,性能较差,尽量少用. 但不可否认的是synchr ...

  3. 齐博x1标签实例:标签如何调用论坛内容

    论坛的内容不像CMS其它模块可以直接用变量 {$rs.content} 因为论坛的内容数据表是放在另一个表的,单独分开的. 当前也是为了考试效率问题而这样设计的. 所以他的调用要用下面的代码 {:fu ...

  4. go-zero docker-compose 搭建课件服务(二):编写courseware rpc服务

    0.转载 go-zero docker-compose 搭建课件服务(二):编写courseware rpc服务 0.1源码地址 https://github.com/liuyuede123/go-z ...

  5. 使用NEON指令加速RGB888和RGB565的相互转换

    最近在做一个项目需要将RGB888转换为RGB565,用C语言转换的代码很简单,这是从ffmpeg中摘抄的代码 static inline void rgb24to16_c(const uint8_t ...

  6. ansible应用之安装elk框架

    最近在学习ansible,先大致看了下视频,现在需要练习使用了.对照视频中的练习方式,我觉得用处也不是太大,正好现在还要学习elk,以集群方式部署es,需要执行一些批量命令,而且还有一些修改配置文件的 ...

  7. java学习之Servlet

    0x00前言 Servlet就是一个接口我们需要写一个类然后去实现Servlet,就可以被服务器识别到.request是用来接受客户端传过来的参数,respone是用来响应客户端的页面.我们所用的容器 ...

  8. 洛谷 P4135 作诗 题解

    题面. 之前做过一道很类似的题目 洛谷P4168蒲公英 ,然后看到这题很快就想到了解法,做完这题可以对比一下,真的很像. 题目要求区间内出现次数为正偶数的数字的数量. 数据范围1e5,可以分块. 我们 ...

  9. 第2-3-4章 上传附件的接口开发-文件存储服务系统-nginx/fastDFS/minio/阿里云oss/七牛云oss

    目录 5.3 接口开发-上传附件 5.3.1 接口文档 5.3.2 代码实现 5.3.3 接口测试 5.3 接口开发-上传附件 第2-1-2章 传统方式安装FastDFS-附FastDFS常用命令 第 ...

  10. cookies和session总结

    1.作为基础知识,但是也是容易被我们忽略的知识. 2.从我的一次面试中,面试官问到,session是什么?和cookies有什么关系,当时我以为很简单,便顺口回答到,session是为了解决http无 ...