本文档内容:

1 python中三种名称空间和作用域

2 函数的使用

3 闭包

4 装饰器

一 python中三种名称空间和作用域

1.1名称空间:

当程序运行时,代码从上至下依次执行,它会将变量与值得关系存储在一个空间中,这个空间
也叫命名空间。例如:name='xingchen'
当程序遇到函数时,它会将函数名存在内存中,函数内部的变量和逻辑暂时不关心;
当函数执行时,内存会临时开辟一个空间,存放函数体里面的代码(变量,代码等),这个空间叫临时名称空间
也叫局部名称空间。
函数外面访问不到临时空间的内容;随着函数的执行完毕,临时空间会释放掉。

python中名称空间分三种:
  内置名称空间
  全局名称空间
  局部名称空间
作用域:
  全局作用域:
    内置名称空间
    全局名称空间
局部作用域:
    局部名称空间
加载顺序
内置名称空间 ---》全局名称空间(程序执行时) ---》局部名称空间(函数执行时)
取值顺序:单向不可逆
局部名称空间 ---》全局名称空间 ----》内置名称空间

1.2  globals和locals

print(globals() ) 返回的是全局作用域里面的变量与其值,是一个字典

print(locals())   返回的是当前的局部变量与其值,也是一个字典

例如:

def func1():
a=1
print(a)
print(locals())
print(globals())
func1()

其结果为:

1

{'a':}

{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000024FD014B240>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:/PycharmProjects-x/s22day03/day4/lianxi.py', '__cached__': None, 'time': <module 'time' (built-in)>, 'func1': <function func1 at 0x0000024FD0056048>}

1.3 global和nonlocal

global:声明一个全局变量,可以用作局部变量的关键字来修改或赋值给全局变量,

    但是:对可变数据类型(list,dict,set)可以直接引用不用通过global。如果默认参数是一个可变的数据类型,那么他在内存中永远是一个

例如:下面的list就是可变数据类型,因此就不用global

# def extendList(val,list=[]):
#    list.append(val)
#    return list
# list1 = extendList(10)
# print('list1=%s'%list1) # [10,]
# list2 = extendList(123,[])
# print('list2=%s'%list2) # [123,]
# list3 = extendList('a')
# print('list3=%s'%list3) #[10,'a'] # print('list1=%s'%list1)
# print('list2=%s'%list2)
# print('list3=%s'%list3) 其结果为: [10,a] [123] [10,a]

nonlocal:在局部作用域中,对其父级作用域(或者更外层作用域)进行变量赋值或者修改,但是不能修改全局作用域

例如:

def func1():
a=1
def func2():
b=10
def func3():
nonlocal a,b
a=a+1
b=b+1
print(a,b) #结果为 2,11
func3()
print(a,b) #结果为 2,11,func2函数的b被引用了
func2()
print(a)        #结果为 2,这里的变量a被引用了,但是b不是在这里面引用的,所以打印b会报错
func1()

二函数的使用

函数名的本质就是函数的内存地址

1 函数可以被引用

例如:

def func1():
print('in func1')
f=func1
print(f)
结果为:<function func1 at 0x000001E9313C6048>

2 函数可以作为容器类元素

例如

def func1():
print('f1') def func2():
print('f2') l1=[func1,func2]
l2={'f1':func1,'f2':func2} l1[0]()
l2['f2']()

3 函数可以作为返回值

def f1():
print('f1') def func1(argv):
argv()
return argv f = func1(f1)
f()

其他: 第一类对象

第一类对象(first-class object)指
1.可在运行期创建
2.可用作函数参数或返回值
3.可存入变量的实体。

三 闭包

内部函数包含对外部作用域而非全局作用域变量的引用,该内部函数称为闭包函数,一般用于装饰器或者网络爬取内容

判断闭包函数的方法__closure__

例如:

def func():
name = 'eva'
def inner():
print(name)
     print(inner.__closure__) #结果中函数含有cell元素,否则为none
return inner
f = func()
f()

闭包函数一个例子

    def line_conf(a, b):
def line(x):
return a * x + b
return line

四 装饰器

装饰器的本质是一个python函数,基于闭包函数,让其他的函数在不改变源码和调用方式的前提下,增加新的功能

  装饰器的应用场景:比如插入日志,性能测试,事务处理,缓存等等场景。

下面看看装饰器的形成过程:

原始的代码

import time
# print(time.time()) # 1527326532.2688255 # def func1():
#   time.sleep(0.3)
#    print('非常复杂......')
#
# start_time = time.time()
# func1()
# end_time = time.time()
# print('此函数的执行效率%s' %(end_time-start_time))

# 改版1:我要封装到一个函数中

# def func1():
#    time.sleep(0.3)
#    print('非常复杂......')
#
# def func2():
#    time.sleep(0.3)
#    print('特别复杂......')
#
# func1()
# func2()

# # 改版2:被测试函数当参数传入,可以测试多个函数的执行效率

# def timmer(f):
#    start_time = time.time()
#   f()
#    end_time = time.time()
#    print('此函数的执行效率%s' %(end_time-start_time))
#
# timmer(func1)
# timmer(func2)

# 改版3::测试函数执行效率的同时,不要改变原函数的调用方式。

# def func1():
#   time.sleep(0.3)
#   print('非常复杂......')
# def func2():
#    time.sleep(0.3)
#    print('特别复杂......')
# # func1()
# # func2()
# def timmer(f):
#    start_time = time.time()
#   f()
#   end_time = time.time()
#    print('此函数的执行效率%s' % (end_time - start_time))
# f1 = func1
# func1 = timmer #
# func1(f1) # timmer(func1)

# 改版4::改版3虽然大体上满足了我的要求,但是增加两行代码,
# 而且多了参数,不好,继续改,尽量不添加其他代码,而且做到调用时一模一样
# 最简单的装饰器。

# def func1():
#   time.sleep(0.3)
#    print('非常复杂......')
# def func2():
#    time.sleep(0.3)
#    print('特别复杂......')
# # func1()
# # func2()
#
# def timmer(f): # f = func1 函数名
#    def inner():
#     start_time = time.time()
#      f()
#      end_time = time.time()
#     print('此函数的执行效率%s' % (end_time - start_time))
#    return inner
#
# func1 = timmer(func1) # inner
# func2 = timmer(func2) # inner
# func1() # inner()
# func2()

# 改版5::改版4每次测试一个函数的执行效率时,都需要加一行 func1 = timmer(func1)代码,麻烦
# python提出了一个语法糖 @。

# def timmer(f): # f = func1 函数名
#    def inner():
#       start_time = time.time()
#       f()
#       end_time = time.time()
#       print('此函数的执行效率%s' % (end_time - start_time))
#    return inner
#
# @timmer # func1 = timmer(func1) inner
# def func1():
#    time.sleep(0.3)
#    print('非常复杂......')
#
# func1() # inner()

# 改版6:被装饰的函数肯定要有参数的,你现在不能满足,解决这个问题。
# 被装饰的函数带参数的装饰器

# def timmer(f): # f = func1 函数名
#    def inner(*args,**kwargs): # args = (1,2),kwargs {sex:'nv',name:'alex'}
#       start_time = time.time()
#     f(*args,**kwargs) # f(1,2,,sex='nv',name='alex')
#      end_time = time.time()
#       print('此函数的执行效率%s' % (end_time - start_time))
#    return inner
#
# @timmer # func1 = timmer(func1) inner
# def func1(a,b):
#    time.sleep(0.3)
#    print(a,b)
#    print('非常复杂......')
#
#
# @timmer # func1 = timmer(func1) inner
# def func2(a,b,name,sex='man'): # f(1,2,,sex='nv',name='alex')
#    time.sleep(0.3)
#    print(a,b,sex,name)
#    print('非常复杂......')
#
# func2(1,2,sex='nv',name='alex') # inner()

# 改版7:被装饰的函数肯定要有返回值的,解决这个问题。
# 被装饰的函数带参数且有返回值的装饰器

# def timmer(f): # f = func2 函数名
#    def inner(*args,**kwargs): # args = (1,2),kwargs {sex:'nv',name:'alex'}
#       start_time = time.time()
#     ret = f(*args,**kwargs) # f(1,2,,sex='nv',name='alex')
#       end_time = time.time()
#       print('此函数的执行效率%s' % (end_time - start_time))
#      return ret
#   return inner
# @timmer # func1 = timmer(func1) inner
# def func2(a,b,name,sex='man'): # f(1,2,,sex='nv',name='alex')
#    time.sleep(0.3)
#   print(a,b,sex,name)
#    print('非常复杂......')
#    return 666
#
# print(func2(1,2,sex='nv',name='alex')) # inner() def timmer(f):
  def inner(*args,**kwargs):
    start_time = time.time()
    ret = f(*args,**kwargs)
    end_time = time.time()
    print('此函数的执行效率%s' % (end_time - start_time))
    return ret
  return inner
@timmer
# def func2(a,b,name,sex='man'):
#    time.sleep(0.3)
#    print(a,b,sex,name)
#    print('非常复杂......')
#    return 666
#
# ret1 = func2(1,2,sex='nv',name='alex')
# print(ret1)
至此装饰器的固定结构如下
def timer(func):
def inner(*args,**kwargs):
'''执行函数之前要做的'''
re = func(*args,**kwargs)
'''执行函数之后要做的'''
return re
return inner

但是如何函数有很多,如何取消他们呢,以后如果又加上呢---带参数的装饰器模型

def outer(flag):
def timer(func):
def inner(*args,**kwargs):
if flag:
print('''执行函数之前要做的''')
re = func(*args,**kwargs)
if flag:
print('''执行函数之后要做的''')
return re
return inner
return timer @outer(False) #改为false是不执行装饰器内的内容
def func():
print(111) func()

如果多个装饰器装饰一个函数呢

def wrapper1(func):
def inner():
print('wrapper1 ,before func')
func()
print('wrapper1 ,after func')
return inner def wrapper2(func):
def inner():
print('wrapper2 ,before func')
func()
print('wrapper2 ,after func')
return inner @wrapper1
@wrapper2
def f():
print('in f')
f()

其结果为:

wrapper1 ,before func
wrapper2 ,before func
in f
wrapper2 ,after func
wrapper1 ,after func

装饰器的另外一种方法:

import functools
def wrapper(func):
@functools.wraps(func)
def inner(*args, **kwargs):
print('我是装饰器')
return func(*args,**kwargs)
print('--------')
return inner @wrapper
def index():
print('我是被装饰函数')
return None index()

---------------------------------------------------------------------------------回顶部----------------------------------------------------------------------------------------------------------------------------

day4----函数-闭包-装饰器的更多相关文章

  1. python函数闭包-装饰器-03

    可调用对象 callable()  # 可调用的(这个东西加括号可以执行特定的功能,类和函数) 可调用对象即  callable(对象)  返回为  True  的对象 x = 1 print(cal ...

  2. 【Python3的命名空间与作用域,闭包函数,装饰器】

    一.命名空间与作用域 命名空间是名字和对象的映射,就像是字典,key是变量名,value是变量的值 1.命名空间的定义 name='egon' #定义变量 def func(): #定义函数 pass ...

  3. python学习笔记-day4笔记 常用内置函数与装饰器

    1.常用的python函数 abs             求绝对值 all               判断迭代器中所有的数据是否为真或者可迭代数据为空,返回真,否则返回假 any          ...

  4. Python之函数对象、函数嵌套、名称空间与作用域、闭包函数、装饰器

    目录 一 函数对象 二 函数的嵌套 三 名称空间和作用域 四 闭合函数 五 装饰器 一.函数对象 1.函数是第一类对象 #第一类对象的特性:# 可以被引用 # 可以当做参数传递 # 返回值是函数 # ...

  5. day11 闭包函数和装饰器

    1.函数不是新知识点 主要是学习函数的用法 在面向对象编程中,一切皆对象,函数也不例外 具体的表现 1.函数可以引用 2.函数可以作为函数的参数 3.函数可以作为函数的返回值 4.可以被存储到容器类型 ...

  6. python基础-闭包函数和装饰器

    闭包函数和装饰器 闭包函数 概念:在函数中(嵌套)定义另一个函数时,内部函数引用了外层函数的名字. 特性 闭包函数必须在函数内部定义 闭包函数可引用外层函数的名字 闭包函数是函数嵌套.函数对象.名称空 ...

  7. day11_7.11 闭包函数与装饰器

    补充: callable 代表可调用的,加括号可以执行.(函数或者类) import this  查看python之禅 一.闭包函数 所谓闭包函数,就是定义在函数内部的函数,也就是函数定义的嵌套.而在 ...

  8. CSIC_716_20191112【闭包函数和装饰器】

    闭包函数 什么是闭包函数:闭包函数是函数嵌套.函数对象.名称空间和作用域的集合体. 闭包函数必须在函数内部定义,闭包函数可以引用外层函数的名字. # _*_ coding: gbk _*_ # @Au ...

  9. Python_oldboy_自动化运维之路_函数,装饰器,模块,包(六)

    本节内容 上节内容回顾(函数) 装饰器 模块 包 1.上节内容回顾(函数) 函数 1.为什么要用函数? 使用函数之模块化程序设计,定义一个函数就相当于定义了一个工具,需要用的话直接拿过来调用.不使用模 ...

  10. python学习之路-4 内置函数和装饰器

    本篇涉及内容 内置函数 装饰器 内置函数 callable()   判断对象是否可以被调用,返回一个布尔值 1 2 3 4 5 6 7 8 9 10 11 num = 10 print(callabl ...

随机推荐

  1. 教你用CMD命令查询域名的DNS解析记录:A,NS,MX,CNAME,TXT

    1.查询域名的A记录 nslookup -qt=A qqgzs.com 当然查询A记录你直接用ping命令来ping域名也可以获得A记录. 2.查询域名的NS记录 nslookup -qt=NS qq ...

  2. dom实例,模态框,全选,反选,取消

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. Action<T> Delegate

    来源:https://docs.microsoft.com/zh-cn/dotnet/api/system.action-1?view=netframework-4.7.2 Action<T&g ...

  4. windows服务命令 转载

    OnCustomCommand executes when the Service Control Manager (SCM) passes a custom command to the servi ...

  5. SET FMTONLY ON

    有时候在执行SQL查询语句时,仅仅需要知道检索的元数据,而不是具体的数据行,可以设置SET FMTONLY ON. SET FMTONLY只将元数据返回给客户端. 语法SET FMTONLY { ON ...

  6. 《剑指offer(第二版)》——面试题36:二叉搜索树与双向链表

    具体的题目大意和参考思路在此处不详述(见<剑指offer>),实质就是在中序遍历的过程中调整指针的指向,关于中序遍历有递归和非递归两种操作,所以此处也用了两种方法. 方法1(递归法): 代 ...

  7. gitlab ssh clone问题解决

    公司搭建的gitlab,通过http协议可以clone: [sisi@pre-srv24 gitlab]$ git clone http://gitlab.test.mycompany.com/dev ...

  8. Lucene 4.0 正式版发布,亮点特性中文解读[转]

    http://blog.csdn.net/accesine960/article/details/8066877 2012年10月12日,Lucene 4.0正式发布了(点击这里下载最新版),这个版本 ...

  9. zuul网关Filter处理流程及异常处理

    本文转载自:https://blog.csdn.net/tianyaleixiaowu/article/details/77893822 上一篇介绍了java网关Zuul的简单使用,进行请求路由转发和 ...

  10. Android开发教程之【环境搭建及HelloWorld】(转载)

    引言 本系列适合0基础的人员,因为我就是从0开始的,此系列记录我步入Android开发的一些经验分享,望与君共勉!作为Android队伍中的一个新人的我,如果有什么不对的地方,还望不吝赐教. 在开始A ...