python自动化day4-函数嵌套、名称空间、作用域、装饰器
1.函数嵌套
#函数的镶套调用:在调用一个函数的过程中,又调用其他函数
def max2(x,y): if x > y: return x else: return y def max4(a,b,c,d): res1=max2(a,b) res2=max2(res1,c) res3=max2(res2,d) return res3 print(max4(1,2,3,-1))
#函数的嵌套定义:在一个函数的内部又定义了另一个函数
def f2(): print('from f2') def f1(): x=1 # def f2() # print('from f2') f2() f1()
2.名称空间
存放名字的地方,准确的说名称空间是存放名字与变量值绑定关系的地方
#名称空间的加载顺序
#python test.py#1、python解释器先启动,因而首先加载的是:内置名称空间#2、执行test.py文件,然后以文件为基础,加载全局名称空间#3、在执行文件的过程中如果调用函数,则临时产生局部名称空间
#内置名称空间:在python解释器启动时产生,存放一些python内置的名字#全局名称空间:在执行文件时产生,存放文件级别定义的名字
#局部名称空间:在执行文件的过程中,如果调用了函数,则会产生该函数的局部名称空间#用来存放该函数内定义的名字,该名字在函数调用时生效,在函数调用结束后失效
加载顺序
内置---》全局---》局部
优先掌握一
名字的查找顺序是:局部-》全局-》内置
def foo(): max= #内置 foo() print(max) ###########################得到的是全局 <built-in function max>
x=0 def f1(): x=1 def f2(): x=2 def f3(): x=3 print(x) f3() f2() print(x) f1() ---------------------------------> 3 1
作用域:作用的范围
全局作用域:全局存活,全局有效:globals()
max=1111111 def f1(): def f2(): def f3(): def f4(): print(max) f4() f3() f2()
局部作用域:临时存活,局部有效:locals()
#global nonlocal掌握
x=1 def f1(): global x x=2 f1() print(x)
l=[] def f2(): l.append('f2') f2() print(l)
x=0 def f1(): x=1 def f2(): x=2 def f3(): # global x nonlocal x x=3 f3() f2() print(x) f1() print(x)
优先掌握二作用域关系,在函数定义时就已经固定 ,于调用位置无关,在调用函数时,必须必须必须回到函数原来定义的位置去找作用域关系
x=1 def f1(): def f2(): print(x) return f2 x=100 def f3(func): x=2 func() x=10000 f3(f1())
查看作用域:globals(),locals()
LEGB 代表名字查找顺序: locals -> enclosing function -> globals -> __builtins__ locals 是函数内的名字空间,包括局部变量和形参 enclosing 外部嵌套函数的名字空间(闭包中常见) globals 全局变量,函数定义所在模块的名字空间 builtins 内置模块的名字空间
3.闭包函数
定义在函数内部的函数,包含对外部作用域名字的引用,而不是对全局作用域名字的引用,那么该内部函数称为闭包函数
x=1 def f1(): x = 11111111 def f2(): print(x) return f2 func = f1() func()
闭包函数的应用:惰性计算
import requests def index(): url='https://www.python.org' def get(): print(requests.get(url).text) return get webb=index() webb()
4.装饰器
装饰器就是闭包函数的一种应用场景
一 为何要用装饰器
开放封闭原则:对修改封闭,对扩展开放
二 什么是装饰器
装饰他人的工具:本身可以是任意可调用对象,被装饰者也可以是任意可调用对象。
强调装饰器的原则:1 不修改被装饰对象的源代码 2 不修改被装饰对象的调用方式
装饰器的目标:在遵循1和2的前提下,为被装饰对象添加上新功能
装饰器的语法
被装饰函数的正上方,单独一行 @deco1 @deco2 @deco3 def foo(): pass foo=deco1(deco2(deco3(foo)))
import time def index(): time.sleep(3) print('hellow world!') def ti(x): #x=index def www(): start=time.time() x() stop=time.time() print('sdsadAdsd %s' %(stop-start)) return www index=ti(index) index()
#########简单写法 import time def ti(x): def www(): start=time.time() x() stop=time.time() print('sdsadAdsd %s' %(stop-start)) return www @ti #idex=ti(index) def index(): time.sleep(3) print('hellow world!') index()
简单写法
def auth(driver='file'): def auth2(func): def wrapper(*args,**kwargs): name=input("user: ") pwd=input("pwd: ") if driver == 'file': ': print('login successful') res=func(*args,**kwargs) return res elif driver == 'ldap': print('ldap') return wrapper return auth2 @auth(driver='file') def foo(name): print(name) foo('egon')
有参数装饰器
import time def timmer(func): def wrapper(*args,**kwargs): start_time=time.time() res=func(*args,**kwargs) stop_time=time.time() print('run time is %s' %(stop_time-start_time)) return res return wrapper @timmer def foo(): time.sleep(3) print('from foo') foo()
无参装饰器
装饰器查看注释
from functools import wraps def deco(func): @wraps(func) #加在最内层函数正上方 def wrapper(*args,**kwargs): return func(*args,**kwargs) return wrapper @deco def index(): '''哈哈哈哈''' print('from index') print(index.__doc__)
装饰多个函数
# 叠加多个装饰器 # 1. 加载顺序(outter函数的调用顺序):自下而上 # 2. 执行顺序(wrapper函数的执行顺序):自上而下
def outter1(func1): #func1=wrapper2的内存地址 print('加载了outter1') def wrapper1(*args,**kwargs): print('执行了wrapper1') res1=func1(*args,**kwargs) return res1 return wrapper1 def outter2(func2): #func2=wrapper3的内存地址 print('加载了outter2') def wrapper2(*args,**kwargs): print('执行了wrapper2') res2=func2(*args,**kwargs) return res2 return wrapper2 def outter3(func3): # func3=最原始的那个index的内存地址 print('加载了outter3') def wrapper3(*args,**kwargs): print('执行了wrapper3') res3=func3(*args,**kwargs) return res3 return wrapper3 @outter1 # outter1(wrapper2的内存地址)======>index=wrapper1的内存地址 @outter2 # outter2(wrapper3的内存地址)======>wrapper2的内存地址 @outter3 # outter3(最原始的那个index的内存地址)===>wrapper3的内存地址 def index(): print('from index') print('======================================================') index() 示范代码
迭代器
#迭代是一个重复的过程,每一次重复,都是基于上一次的结果而来
l=['a','b','c','d'] count=0 while count < len(l): #迭代 print(l[count]) count+=1
#迭代对象:凡是对象下游__iter__方法:对象.__iter__,该对象就是迭代对象#所有字符串类型,列表,字典,元组等等都是
dic={'name':'zbb','sex':'m','age':8} i=dic.__iter__() # print(i) # i.__next__() #next(i) print(next(i)) print(next(i)) print(next(i)) print(next(i)) #StopIteration
l=[1,2,3,4,5,6] i=l.__iter__() print(i) i1=i.__iter__() print(i1) <list_iterator object at 0x0000024138121518> <list_iterator object at 0x0000024138121518>
迭代器一种不依赖索引的取值方式
l=[1,2,3,4,5,6] i=l.__iter__() print(next(i)) print(next(i)) print(next(i)) print(next(i))
#取列表
l=['1',2,3,4,5,6]
xz=iter(l) while True: try: print(next(xz)) except StopIteration: break 取出字典 dic={'name':'zbb','sex':'m','age':8} zzx=iter(dic) while True: try: #print(next(zzx)) k=next(zzx) print(k,dic[k]) except StopIteration: break
#什么是迭代器对象#有 __iter__,执行得到的仍是迭代本身#y有 __next__ #迭代器对象的优点#提供一种统一的(不依赖索引的)迭代方式#迭代器本身,比起其他数据类型更省内存
with open('a.txt') as f: print(next(f)) print(next(f)) print(next(f))
#迭代器的缺点#一次性,只能往后走,不能回退,不如索引取值灵活、#无法预知什么时候结束,既无法预知长度
l=[1,2,3,4,5] i=iter(l) print(next(i)) print(next(i)) print(next(i))
#for循坏原理
l=[1,2,3,4,5,5] for item in l:#==iter_l=l.__iter__() print(item)
#补充:判断可迭代对象与迭代器对象(了解) from collections.abc import Iterable,Iterator s='hello' l=['a','b','c','d'] t=('a','b','c','d') dic={'name':'egon','sex':'m',"age":18} set1={1,2,3} f=open('a.txt') # print(isinstance(s,Iterable)) # print(isinstance(l,Iterable)) # print(isinstance(t,Iterable)) # print(isinstance(dic,Iterable)) # print(isinstance(set1,Iterable)) # print(isinstance(f,Iterable)) print(isinstance(s,Iterator)) print(isinstance(l,Iterator)) print(isinstance(t,Iterator)) print(isinstance(dic,Iterator)) print(isinstance(set1,Iterator)) print(isinstance(f,Iterator))
生成器
#只要函数内部包含有yield关键字,那么函数名()的到的结果就是生成器,并且不会执行函数内部代码 #生成器就是迭代器 #yield的功能:1、把函数的结果做成迭代器(以一种优雅的方式封装好__iter__,__next__) #y函数暂停与再继续运行的状态是由yield决定 以挂起/保存函数的运行状态
def func(): print('====>first') yield 1 print('====>second') yield 2 print('====>third') yield 3 print('====>end') g=func() print(g) #<generator object func at 0x0000000002184360> next(g) print(next(g)) #可以打印yield for i in g: # pass print(i)
def func(n): print("wee") while True: yield n n+=1 g=func(1) print(next(g)) print(next(g)) for i in g: print(i) for i in range(1000000000000000000000): print(i)
def my_range(start,stop): while True: if start == stop: raise StopIteration yield start start+=1 # g=my_range(1,3) # print(next(g)) # print(next(g)) # print(next(g)) #自己写一个range # for i in my_range(1,2): # print(i)
yield与return的比较
#都有返回值功能#return 只能返回一次,yield可以返回多次值
面向过程编程 #1、首先强调:面向过程编程绝对不是用函数编程这么简单,面向过程是一种编程思路、思想,而编程思路是不依赖于具体的语言或语法的。言外之意是即使我们不依赖于函数,也可以基于面向过程的思想编写程序 #2、定义 面向过程的核心是过程二字,过程指的是解决问题的步骤,即先干什么再干什么 基于面向过程设计程序就好比在设计一条流水线,是一种机械式的思维方式 #3、优点:复杂的问题流程化,进而简单化 #4、缺点:可扩展性差,修改流水线的任意一个阶段,都会牵一发而动全身 #5、应用:扩展性要求不高的场景,典型案例如linux内核,git,httpd #6、举例 流水线1: 用户输入用户名、密码--->用户验证--->欢迎界面 流水线2: 用户输入sql--->sql解析--->执行功能 ps:函数的参数传入,是函数吃进去的食物,而函数return的返回值,是函数拉出来的结果,#面向过程的思路就是,把程序的执行当做一串首尾相连的功能,该功能可以是函数的形式,然后一个函数吃,拉出的东西给另外一个函数吃,另外一个函数吃了再继续拉给下一个函数吃。。。
#=============复杂的问题变得简单 #注册功能: #阶段1: 接收用户输入账号与密码,完成合法性校验 def talk(): while True: username=input('请输入你的用户名: ').strip() if username.isalpha(): break else: print('用户必须为字母') while True: password1=input('请输入你的密码: ').strip() password2=input('请再次输入你的密码: ').strip() if password1 == password2: break else: print('两次输入的密码不一致') return username,password1 #阶段2: 将账号密码拼成固定的格式 def register_interface(username,password): format_str='%s:%s\n' %(username,password) return format_str #阶段3: 将拼好的格式写入文件 def handle_file(format_str,filepath): with open(r'%s' %filepath,'at',encoding='utf-8') as f: f.write(format_str) def register(): user,pwd=talk() format_str=register_interface(user,pwd) handle_file(format_str,'user.txt') register() #=============牵一发而动全身,扩展功能麻烦 #阶段1: 接收用户输入账号与密码,完成合法性校验 def talk(): while True: username=input('请输入你的用户名: ').strip() if username.isalpha(): break else: print('用户必须为字母') while True: password1=input('请输入你的密码: ').strip() password2=input('请再次输入你的密码: ').strip() if password1 == password2: break else: print('两次输入的密码不一致') role_dic={ ':'user', ':'admin' } while True: for k in role_dic: print(k,role_dic[k]) choice=input('请输入您的身份>>: ').strip() if choice not in role_dic: print('输入的身份不存在') continue role=role_dic[choice] return username,password1,role #阶段2: 将账号密码拼成固定的格式 def register_interface(username,password,role): format_str='%s:%s:%s\n' %(username,password,role) return format_str #阶段3: 将拼好的格式写入文件 def handle_file(format_str,filepath): with open(r'%s' %filepath,'at',encoding='utf-8') as f: f.write(format_str) def register(): user,pwd,role=talk() format_str=register_interface(user,pwd,role) handle_file(format_str,'user.txt') register() #ps:talk内对用户名\密码\角色的合法性校验也可以摘出来做成单独的功能,#但本例就写到一个函数内了,力求用更少的逻辑来为大家说明过程式编程的思路
python自动化day4-函数嵌套、名称空间、作用域、装饰器的更多相关文章
- Python自动化面试必备 之 你真明白装饰器么?
Python自动化面试必备 之 你真明白装饰器么? 装饰器是程序开发中经常会用到的一个功能,用好了装饰器,开发效率如虎添翼,所以这也是Python面试中必问的问题,但对于好多小白来讲,这个功能 有点绕 ...
- Python 函数对象-函数嵌套-名称空间与作用域-闭包函数
今日内容: 1. 函数对象 函数是第一类对象: 指的是函数名指向的值可以被当中数据去使用 1.可以被引用 2.可以当做参数传给另一个函数 3.可以当做一个函数的返回值 4.可以当做容器类型的元素 2. ...
- Python入门之函数的嵌套/名称空间/作用域/函数对象/闭包函数
本篇目录: 一.函数嵌套 二.函数名称空间与作用域 三.函数对象 四.闭包函数 ============================================================ ...
- python12--字符串的比较 函数的默认值的细节 三元表达式 函数对象 名称空间 作用域 列表与字典的推导式 四则运算 函数的嵌套
复习 1.字符串的比较; 2.函数的参数; ******实参与形参的分类: 3.函数的嵌套调用: # 字符串的比较# -- 按照从左往右比较每一个字符,通过字符对应的ascii进行比较 ...
- python基础之函数参数,名称空间,以及函数嵌套
函数进阶内容梗概: 1. 函数参数--动态传参 2. 名称空间, 局部名称空间, 全局名称空间, 作⽤用域, 加载顺序. 3. 函数的嵌套 4. gloabal , nonlocal 关键字 1. 函 ...
- Python 入门基础10 --函数基础3 函数对象、名称空间、装饰器
今日内容 1.函数对象 2.名称空间与作用域 3.函数的嵌套调用与闭包 4.装饰器 一.函数对象 1.1 定义 函数名存放的就是函数地址,所以函数名也就是对象,称之为函数对象 1.2 函数对象的应用 ...
- day_12函数默认值,数据类型的补充,函数对象名称空间与作用域,函数的嵌套定义
复习, 昨天讲了字符串的比较,按照从左往右比较每一个字符,通过字符对应的ASCII码进行比较 函数的参数,‘ 实参与形参 形参:在函数定义时()中出现的参数 实参,在函数调用时()中出现的参数 实参的 ...
- Python记录9:函数4:名称空间作用域+闭包函数+装饰器
''' 一: 名称空间namespaces 名称空间就是存放名字与值绑定关系的内存空间 二: 名称空间分为三种 内置名称空间: 1. 特点: 存放是python解释器自 ...
- 函数的名称空间,函数的嵌套(global, nonlocal),函数名的运用
一 函数的名称空间 内置空间:存放python解释器内置函数的空间 全局空间:py文件运行时开辟的,存放的是执行的py文件(出去函数内部)的所有的变量与值的对用关系,整个py文件结束后才会消失. 局部 ...
- 十一. Python基础(11)—补充: 作用域 & 装饰器
十一. Python基础(11)-补充: 作用域 & 装饰器 1 ● Python的作用域补遗 在C/C++等语言中, if语句等控制结构(control structure)会产生新的作用域 ...
随机推荐
- jquery页面初始化控件时间
this.InitControlTime = function () { if ($("#txt_Id_").val() == "") { var today ...
- Docker 实现的 redis 主从
计划用 Docker 实现 Redis 的主从,简单主从而已.主的名称叫 redis-master 一步步来. 先新建个Dockerfile ,从alpine 开始,比较简单. FROM alpine ...
- java重载方法的二义性
http://blog.csdn.net/lavor_zl/article/details/40746813
- 彻底修改Eclipse的默认编码
引用各位前辈经验得到彻底修改eclipse默认编码的方法. 单在eclipse里设置编码方式非常复杂且容易遗漏,全部修改后,有些代码生成模板内的${encode}变量仍为原编码方案,经过查阅许多资料得 ...
- Maven常用配置
运行mvn install时跳过Test 方法一: <project> [...] <build> <plugins> <plugin> <gro ...
- JS中的唯一容器:数组
JS中的唯一容器:数组 一.什么类型的数据都可以存储 二. 定义的方式有两种 1 . var arra=[];var arra=[“a”,“b”,"c"]; 2.v ...
- 如何在IIS中承载WCF NetTcpBinding 服务
这篇博客将介绍如何在IIS中承载NetTcpBinding的服务. 1. 首先准备服务代码. Contract namespace Contract { [ServiceContract] publi ...
- Smarty配置与实例化
在smarty文件夹下建立一个test文件夹,test下建立如下: 编辑test.php如下: <?php require('../smarty/Smarty.class.php'); $sma ...
- UVa 10766 Organising the Organisation (生成树计数)
题意:给定一个公司的人数,然后还有一个boss,然后再给定一些人,他们不能成为直属上下级关系,问你有多少种安排方式(树). 析:就是一个生成树计数,由于有些人不能成为上下级关系,也就是说他们之间没有边 ...
- Appium命令行工作模式
前面如何快速搭建基于python+appium的自动化测试环境介绍过安装Appium-desktop的客户端版本,然后每次需要运行脚本的时候都要先去找到Appium应用并双击打开,再点击Start S ...