Python 入门基础10 --函数基础3 函数对象、名称空间、装饰器
今日内容
1.函数对象
2.名称空间与作用域
3.函数的嵌套调用与闭包
4.装饰器
一、函数对象
1.1 定义
函数名存放的就是函数地址,所以函数名也就是对象,称之为函数对象
1.2 函数对象的应用
1.可以直接被引用
2.可以当作函数参数传数
3.可以作为函数的返回值
4.可以作为容器类型的元素
def fn():
num = 10
print('fn function run')
# 直接被引用
func = fn
fn()
func()
案例:四则运算
def add(n1, n2):
return n1 + n
def sub(n1, n2): # subtraction 减法
return n1 - n2
def mul(n1, n2): # multiplication 乘法
return n1 * n2
def div(n1, n2): # division 除法
return n1 / n2
method_map = {
'add': add,
'sub': sub,
'mul': mul,
'div': div
}
def computed(fn):
if fn in method_map:
return method_map[fn]
else:
return add
def func():
cmd = input("方法名:")
method = computed(cmd)
result = method(100, 20)
print(result)
func()
二、名称空间
2.1 三种名称空间
built-in:内置名称空间,系统级,一个,随解释器执行而产生,解释器停止而销毁
global:全局名称空间,文件级,多个,随所属文件加载而产生,文件运行完毕而销毁
local:局部名称空间,函数级,多个,随所属函数执行而产生,函数执行完毕而销毁
注:加载顺序:built-in > global > local
num = 10
def fn2():
num = 20
print("this is fn2", num)
def fn3():
num = 30
print("this is fn3", num)
fn2() # this is fn2 20
fn3() # this is fn3 30
print(num) # 10
三、作用域
3.1 LEGB
不同作用域之间名字不冲突,以达到名字的重用
直接查找顺序: Local -> Enclosing -> global -> built-in
built-in : 内置作用域,所有函数
global:全局作用域,当前文件所有函数
enclosing:嵌套作用域,当前函数
local:局部作用域
len = 10
def outer():
len = 20
def inner():
len = 30
print('1', len)
inner()
print('2', len)
outer()
print('3', len) # 10 global --> built-in
del len
print('4', len) # len地址--》built-in
nonlocal:
作用:将L与E的名字统一(E中的名字需要提前定义)
应用场景:如果想在被嵌套的函数中修改外部函数变量(名字)的值
案例:
def outer():
num = 10
print(num) # 10
def inner():
nonlocal num
num = 20
print(num) # 20
inner()
print(num) # 20
outer()
# 第三行打印的 num ,是上一行定义的num
# 由于第五行用 nonlocal 声明了,所以inner里面的num和outer里面定义的num指代的是同一个东西
# 第七行打印的 num ,在第六行重新赋值(num指向的内存地址发生改变)
四、函数嵌套
将函数直接定义到另一个函数内部就可以使用外部函数中的名字
def outer():
num = 20
def inner():
print(num) # inner 可以直接使用outer中的名字
inner()
outer()
五、闭包
函数嵌套(格式稍作改良)
inner : 可以使用outer的局部变量
def outer():
num = 10
def inner:
print(num)
return inner
fn = outer()
fn()
# 案例一:外部函数可以为闭包传递参数
import time
def download():
print('开始下载...')
time.sleep(2)
print('完成下载...')
data = ""
outer(data)
# 传参
def outer(data):
def inner():
# 保存,播放,删除等操作
print("闭包打印:", data)
inner()
download()
# 案例二:延迟执行
import requests
def outer(url):
def get_html():
html = requests.get(url)
print(html.text)
return get_html
# 先预定义多个爬虫方法,爬页面操作并未执行
baidu = outer('https://www.baidu.com')
python = outer('https://www.python.org')
sina = outer('https://www.sina.com.cn')
# 什么时候想爬什么页面就调用指定页面的爬虫方法
baidu()
sina()
2019.04.02 更新
四、装饰器
4.1 什么是装饰器
名字上来看,就是用来装饰的东西
从使用上来看,用来‘装饰’其他函数的函数,可以在原先函数功能基础上添加新的功能
4.2 开放封闭原则
在不改变调用方式和源码上增加功能
1.不能修改被装饰对象(函数)的源代码(封闭)
2.不能更改被修饰对象(函数)的调用方式,且能达到增加功能的效果(开放)
4.3 装饰器语法格式
def outer(fn):
def inner(*args,**kwargs):
#实现的功能
result = fn(*args,**kwargs)
#实现的功能
return result
return inner
4.4 案例们
4.4.1 实现原理
def fn():
print("这是最初的函数!")
# 装饰器
def outer(func):
def inner():
func()
print("打印一行给你看看,这就是添加的新功能!")
return inner
fn = outer(fn)
fn()
# 打印结果:
# 这是最初的函数!
# 打印一行给你看看,这就是添加的新功能!
分析:
函数的执行顺序:
1.python 程序是从上往下执行的,程序先读第1,4行程序(不执行),
2.执行第9行代码,但是先从右侧开始执行,
3.执行outer(fn),程序跳转到第4行,读入inner函数,跳转到8行,执行return,将inner地址返回
4.返回的inner地址被fn接收,执行最后一行代码
5.执行的fn()相当于执行inner()函数,也就是执行inner函数的函数体,由func()和其下一行组成
6.其中第6行就是原先的函数 fn(),下一行就是增加的功能
7.整个程序就实现了在原有基础函数不改变的情况下,增加了新的功能
# 外层函数
def outer(f):
def inner():
f()
print("这里是新增加的功能!11")
return inner
def wrap(f):
def inner():
f()
print("这里也是新增加的功能!22")
return inner
@wrap
@outer
def fn():
print("这里是本来的功能!")
fn()
# 执行结果:
# 这里是本来的功能!
# 这里是新增加的功能!11
# 这里也是新增加的功能!22
分析:
多个装饰器同时装饰同一个函数,可以理解成 俄罗斯套娃 的形式,
谁离被装饰的函数越近,谁就先执行装饰任务
"""
# 有参数有返回值的函数被装饰
"""
def check_user(fn):
def inner(usr, pwd): # inner == login
# 在原功能的基础上添加新功能
# 如果名字长度超过 3 并且 名字是纯字母数字
if not (len(usr) >= 3 and usr.isalpha()):
print("账号验证失败!")
return False
# 满足条件情况下,执行原有的功能
result = fn(usr, pwd)
return result
return inner
@check_user # login = check_user(login)
def login(usr,pwd):
if usr == 'abc' and pwd =='123qwe':
print('登录成功!')
return True
print('登录失败!')
return False
login('abc', '123qwe') # 应该先看最下面这一条执行的函数
总结:
1.login有参数,所以inner与fn都有相同的参数
2.login有返回值,所以inner与fn都有返回值
"""
# 装饰器最终写法
"""
def wrap(fn):
def inner(*args, **kwargs):
print('前增功能')
result = fn(*args, **kwargs)
print('后增功能')
return result
return inner
@wrap
def fn1():
print('fn1的原有功能')
@wrap
def fn2(a, b):
print('fn2的原有功能')
@wrap
def fn3():
print('fn3的原有功能')
return True
@wrap
def fn4(a, *, x):
print('fn4的原有功能')
return True
fn1()
fn2(10, 20)
fn3()
fn4(10, x=20)
"""
# 带参装饰器
"""
def outer(input_color):
def wrap(fn):
if input_color == 'red':
info = '\033[36;42m new action \033[0m'
else:
info = 'yellow:new action'
def inner(*args, **kwargs):
pass
result = fn(*args, **kwargs)
print(info)
return result
return inner
return wrap # outer(color) => wrap
color = input('color: ')
@outer(color) # @outer(color) ==> @wrap # func => inner
def func():
print('func run')
func()
"""
# 案例
# 登录认证功能
"""
is_login = False
def login():
usr = input('usr: ')
if not (len(usr) >= 3 and usr.isalpha()):
print('账号验证失败!')
return False
pwd = input('pwd: ')
if usr == 'abc' and pwd == '123qwe':
print('登录成功!')
is_login = True
else:
print('登录失败!')
is_login = False
# 完成一个登录状态验证的装饰器
def check_login(fn):
def inner(*args,**kwargs):
if is_login != True:
print("你未登录!")
login()
# 执行被装饰的函数功能
result = fn(*args,**kwargs)
return result
return inner
# 查看个人主页功能
@check_login
def home():
print('个人主页')
# 销售功能
@check_login
def sell():
print('清仓大甩卖!')
# 测试函数
home()
Python 入门基础10 --函数基础3 函数对象、名称空间、装饰器的更多相关文章
- python入门(10)使用List和tuple
python入门(10)使用List和tuple list Python内置的一种数据类型是列表:list.list是一种有序的集合,可以随时添加和删除其中的元素. 比如,列出班里所有同学的名字,就可 ...
- python 全栈开发,Day12(函数的有用信息,带参数的装饰器,多个装饰器装饰一个函数)
函数的执行时,*打散.函数的定义时,*聚合. from functools import wraps def wrapper(f): # f = func1 @wraps(f) def inner(* ...
- 12、Python函数高级(命名空间、作用域、装饰器)
一.名称空间和作用域 1.命名空间(Namespace) 命名空间是从名称到对象的映射,大部分的命名空间都是通过 Python 字典来实现的. 命名空间提供了在项目中避免名字冲突的一种方法.各个命名空 ...
- python基础学习Day17 面向对象的三大特性之继承、类与对象名称空间小试
一.课前回顾 类:具有相同属性和方法的一类事物 实例化:类名() 过程: 开辟了一块内存空间 执行init方法 封装属性 自动的把self返回给实例化对象的地方 对象:实例 一个实实在在存在的实体 组 ...
- python 函数结果缓存一段时间的装饰器
把函数结果缓存一段时间,比如读取一个mongodb,mongodb中的内容又在发生变化,如果从部署后,自始至终只去读一次那就感触不到变化了,如果每次调用一个函数就去读取那太频繁了耽误响应时间也加大了c ...
- python 之 面向对象基础(定义类、创建对象,名称空间)
第七章面向对象 1.面向过程编程 核心是"过程"二字,过程指的是解决问题的步骤,即先干什么再干什么 基于该思想编写程序就好比在编写一条流水线,是一种机械式的思维方式 优点:复杂的问 ...
- day_12函数默认值,数据类型的补充,函数对象名称空间与作用域,函数的嵌套定义
复习, 昨天讲了字符串的比较,按照从左往右比较每一个字符,通过字符对应的ASCII码进行比较 函数的参数,‘ 实参与形参 形参:在函数定义时()中出现的参数 实参,在函数调用时()中出现的参数 实参的 ...
- python--函数的返回值、函数参数的使用、名称空间与作用域、函数嵌套、函数对象
今天学习内容有函数的返回值.函数参数的使用.名称空间与作用域.函数嵌套. 下来我们一一查看. 函数的返回值 看几个栗子: def func(x): y=func() print(y) def foo( ...
- 搞懂Python的类和对象名称空间
代码块的分类 python中分几种代码块类型,它们都有自己的作用域,或者说名称空间: 文件或模块整体是一个代码块,名称空间为全局范围 函数代码块,名称空间为函数自身范围,是本地作用域,在全局范围的内层 ...
- Python小白学习之路(二十四)—【装饰器】
装饰器 一.装饰器的本质 装饰器的本质就是函数,功能就是为其他函数添加附加功能. 利用装饰器给其他函数添加附加功能时的原则: 1.不能修改被修饰函数的源代码 2.不能修改被修饰函数的调用 ...
随机推荐
- PAT甲级题解-1097. Deduplication on a Linked List (25)-链表的删除操作
给定一个链表,你需要删除那些绝对值相同的节点,对于每个绝对值K,仅保留第一个出现的节点.删除的节点会保留在另一条链表上.简单来说就是去重,去掉绝对值相同的那些.先输出删除后的链表,再输出删除了的链表. ...
- PAT甲题题解-1105. Spiral Matrix (25)-(模拟顺时针矩阵)
题意:给定N,以及N个数.找出满足m*n=N且m>=n且m-n最小的m.n值,建立大小为m*n矩阵,将N个数从大到下顺时针填入矩阵中. #include <iostream> #in ...
- 2018软工实践—Beta冲刺(7)
队名 火箭少男100 组长博客 林燊大哥 作业博客 Beta 冲鸭鸭鸭! 成员冲刺阶段情况 林燊(组长) 过去两天完成了哪些任务 协调组内工作 整体软件测试 展示GitHub当日代码/文档签入记录(组 ...
- 剑指offer:数组中出现次数超过一半的数
题目描述: 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2 ...
- NServiceBus官方文档翻译(二)NServiceBus 入门
在这篇教程中我们将学习如何创建一个非常简单的由客户端向服务端发送消息的订单系统.该系统包括三个项目:Client.Server 和 Messages,我们将按照以下步骤来完成这个任务. 创建 Clie ...
- Zoom 会议系统
Jfrog的培训过程中 发现ppt的效果很不理想 讲师使用zoom的方式效果很好 首先说一下 zoom的定价体系 官网信息: https://www.zoom.us/profile 好像必须使用 企 ...
- thinkphp在app接口开发过程中的通讯安全认证
对于我们写好的接口,如果不经过安全认证就可以直接访问的话,则将对我们网站产生非常大的安全隐患,一些hack可能直接用你的接口去操作数据库,后果无法估量.那么如何才能进行有效的安全验证呢? 这里我采用了 ...
- 异步查询json传日期格式到前台,变成了时间戳的格式
问题: 使用mybatis 查询mysql数据库,其中一个日期格式的字段,由异步查询使用 json传递到前台,变成了时间戳,而不是日期格式了.如何使查询出的日期展示成日期格式呢 解决办法: 1.尝试使 ...
- sql server 小技巧 集锦
sql server 小技巧(1) 导入csv数据到sql server sql server 小技巧(2) 删除sql server中重复的数据 sql server 小技巧(3) SQL Serv ...
- CODE FESTIVAL 2017 qual B 题解
失踪人口回归.撒花\^o^/ 说来真是惭愧,NOI之后就没怎么刷过题,就写了几道集训队作业题,打了几场比赛还烂的不行,atcoder至今是蓝名=.= 以后还是多更一些博客吧,我可不想清华集训的时候就退 ...