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-函数嵌套、名称空间、作用域、装饰器的更多相关文章

  1. Python自动化面试必备 之 你真明白装饰器么?

    Python自动化面试必备 之 你真明白装饰器么? 装饰器是程序开发中经常会用到的一个功能,用好了装饰器,开发效率如虎添翼,所以这也是Python面试中必问的问题,但对于好多小白来讲,这个功能 有点绕 ...

  2. Python 函数对象-函数嵌套-名称空间与作用域-闭包函数

    今日内容: 1. 函数对象 函数是第一类对象: 指的是函数名指向的值可以被当中数据去使用 1.可以被引用 2.可以当做参数传给另一个函数 3.可以当做一个函数的返回值 4.可以当做容器类型的元素 2. ...

  3. Python入门之函数的嵌套/名称空间/作用域/函数对象/闭包函数

    本篇目录: 一.函数嵌套 二.函数名称空间与作用域 三.函数对象 四.闭包函数 ============================================================ ...

  4. python12--字符串的比较 函数的默认值的细节 三元表达式 函数对象 名称空间 作用域 列表与字典的推导式 四则运算 函数的嵌套

     复习   1.字符串的比较; 2.函数的参数; ******实参与形参的分类: 3.函数的嵌套调用:     # 字符串的比较#  -- 按照从左往右比较每一个字符,通过字符对应的ascii进行比较 ...

  5. python基础之函数参数,名称空间,以及函数嵌套

    函数进阶内容梗概: 1. 函数参数--动态传参 2. 名称空间, 局部名称空间, 全局名称空间, 作⽤用域, 加载顺序. 3. 函数的嵌套 4. gloabal , nonlocal 关键字 1. 函 ...

  6. Python 入门基础10 --函数基础3 函数对象、名称空间、装饰器

    今日内容 1.函数对象 2.名称空间与作用域 3.函数的嵌套调用与闭包 4.装饰器 一.函数对象 1.1 定义 函数名存放的就是函数地址,所以函数名也就是对象,称之为函数对象 1.2 函数对象的应用 ...

  7. day_12函数默认值,数据类型的补充,函数对象名称空间与作用域,函数的嵌套定义

    复习, 昨天讲了字符串的比较,按照从左往右比较每一个字符,通过字符对应的ASCII码进行比较 函数的参数,‘ 实参与形参 形参:在函数定义时()中出现的参数 实参,在函数调用时()中出现的参数 实参的 ...

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

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

  9. 函数的名称空间,函数的嵌套(global, nonlocal),函数名的运用

    一 函数的名称空间 内置空间:存放python解释器内置函数的空间 全局空间:py文件运行时开辟的,存放的是执行的py文件(出去函数内部)的所有的变量与值的对用关系,整个py文件结束后才会消失. 局部 ...

  10. 十一. Python基础(11)—补充: 作用域 & 装饰器

    十一. Python基础(11)-补充: 作用域 & 装饰器 1 ● Python的作用域补遗 在C/C++等语言中, if语句等控制结构(control structure)会产生新的作用域 ...

随机推荐

  1. jquery页面初始化控件时间

    this.InitControlTime = function () { if ($("#txt_Id_").val() == "") { var today ...

  2. Docker 实现的 redis 主从

    计划用 Docker 实现 Redis 的主从,简单主从而已.主的名称叫 redis-master 一步步来. 先新建个Dockerfile ,从alpine 开始,比较简单. FROM alpine ...

  3. java重载方法的二义性

    http://blog.csdn.net/lavor_zl/article/details/40746813

  4. 彻底修改Eclipse的默认编码

    引用各位前辈经验得到彻底修改eclipse默认编码的方法. 单在eclipse里设置编码方式非常复杂且容易遗漏,全部修改后,有些代码生成模板内的${encode}变量仍为原编码方案,经过查阅许多资料得 ...

  5. Maven常用配置

    运行mvn install时跳过Test 方法一: <project> [...] <build> <plugins> <plugin> <gro ...

  6. JS中的唯一容器:数组

    JS中的唯一容器:数组 一.什么类型的数据都可以存储 二. 定义的方式有两种  1 .    var  arra=[];var  arra=[“a”,“b”,"c"];   2.v ...

  7. 如何在IIS中承载WCF NetTcpBinding 服务

    这篇博客将介绍如何在IIS中承载NetTcpBinding的服务. 1. 首先准备服务代码. Contract namespace Contract { [ServiceContract] publi ...

  8. Smarty配置与实例化

    在smarty文件夹下建立一个test文件夹,test下建立如下: 编辑test.php如下: <?php require('../smarty/Smarty.class.php'); $sma ...

  9. UVa 10766 Organising the Organisation (生成树计数)

    题意:给定一个公司的人数,然后还有一个boss,然后再给定一些人,他们不能成为直属上下级关系,问你有多少种安排方式(树). 析:就是一个生成树计数,由于有些人不能成为上下级关系,也就是说他们之间没有边 ...

  10. Appium命令行工作模式

    前面如何快速搭建基于python+appium的自动化测试环境介绍过安装Appium-desktop的客户端版本,然后每次需要运行脚本的时候都要先去找到Appium应用并双击打开,再点击Start S ...