Python三大器有迭代器,生成器,装饰器,这三个中使用最多,最重要的就是装饰器。本篇将重要从函数嵌套开始讲起,从而引入闭包,装饰器的各种用法等。

python中的一切都是一个对象(函数也是)

1.首先让我们来了解python中的函数嵌套

1.1

# -*- coding:utf-8 -*-
def outter(): print("outter()函数里面") def inner1():
return "现在在inner1()函数里面" def inner2():
return "现在在inner2()里面" print (inner1())
print (inner2())
print ("outter执行结束")
# outter()
# outter()函数里面
# 现在在inner1()函数里面
# 现在在inner2()里面
# outter执行结束

如果像上面写的inner1和inner2将没有什么意义,没有必要在另一个函数中执行一个函数,因为完全可以用过程化实现,所以看下面

1.2.从函数内返回函数

# -*- coding:utf-8 -*-
def outter(name="inner1"): print("outter()函数里面") def inner1():
return "现在在inner1()函数里面" def inner2():
return "现在在inner2()里面"
if name == "inner1":
return inner1
else:
return inner2 inner = outter() print(inner())
# outter()函数里面
# 现在在inner1()函数里面

1.3.函数作为参数

# -*- coding:utf-8 -*-
def inner():
return "现在在inner()函数里面"
def outter(func):
print("outter()函数里面")
print(func())
outter(inner)
# outter()函数里面
# 现在在inner()函数里面

2.闭包:在函数内部再定义一个函数,并且这个函数用到了外边函数的变量,并返回这个函数,那么将这个函数以及用到的一些变量称之为闭包。

2.1

def outter(num):
def inner(a):
print(a + num) return inner fun = outter(100) # fun == inner
fun(1) #
fun2 = outter(200)
fun2(1) #
fun(2) #

2.2闭包的实际用例,控制一条直线:y=ax+b,确定直线的斜率后,改变x的值获得不同的y值。

def line_slope(a, b):
def line(x):
return a * x + b return line line1 = line_slope(1, 1)
line2 = line_slope(4, 5)
print(line1(2))
print(line1(-1))
print(line2(-3))
print(line2(6))
#
#
# -7
# # 这个例子中,函数line与变量a,b构成闭包。在创建闭包的时候,
# 我们通过line_slope的参数a,b说明了这两个变量的取值,这样,
# 我们就确定了函数的最终形式(y = x + 1和y = 4x + 5)。
# 我们只需要变换参数a,b,就可以获得不同的直线表达函数。由此,
# 我们可以看到,闭包也具有提高代码可复用性的作用。
# 如果没有闭包,我们需要每次创建直线函数的时候同时说明a,b,x。
# 这样,我们就需要更多的参数传递,也减少了代码的可移植性。
# 1.闭包似优化了变量,原来需要类对象完成的工作,闭包也可以完成
# 2.由于闭包引用了外部函数的局部变量,则外部函数的局部变量没有及时释放,消耗内存
2.3修改闭包变量。说明:Python3通过nonlocal关键字修改闭包变量,Python2通过list来修改
python3中
def outter(start=0):
def inner():
nonlocal start
start += 1
return start return inner o1 = outter(5)
print(o1())
print(o1()) o2 = outter(20)
print(o2())
print(o2()) print(o1())
print(o1()) print(o2())
print(o2()) #
#
#
#
#
#
#
#

python2中

def outter(start=0):
list1 = [start] def inner():
nonlocal start
list1[0] += 1
return list1[0] return inner o1 = outter(5)
print(o1())
print(o1()) o2 = outter(20)
print(o2())
print(o2()) print(o1())
print(o1()) print(o2())
print(o2()) #
#
#
#
#
#
#
#

2.4LEGB 规则

# locals -> enclosing function -> globals -> builtins
a = 1 # 全局变量 globals def outter():
a = 2 # 闭包变量 enclosing def inner():
a = 3 # 局部变量 locals
print("a=%d" % a) return inner o = outter()
o() # a=3 # locals,当前所在命名空间(如函数、模块),函数的参数也属于命名空间内的变量
# enclosing,外部嵌套函数的命名空间(闭包中常见)
# globals,全局变量,函数定义所在模块的命名空间
# builtins,内建模块的命名空间。
# 在Python中,有一个内建模块,该模块中有一些常用函数;在Python启动后,
# 且没有执行程序员所写的任何代码前,Python会首先加载该内建模块到内存。
# 另外,该内建模块中的功能可以直接使用,不用在其前添加内建模块前缀,
# 其原因是对函数、变量、类等标识符的查找是按LEGB法则,其中B即代表内建模块

3.装饰器

3.1被装饰的函数无参数

import time

# 定义装饰器
def log(fun):
def inner():
print(time.time())
fun()
print(time.time()) return inner # 使用装饰器 @加函数名 是一种语法糖,即简写
# 真正的执行过程:send_mail = log(send_mail) => send_mail = inner
@log
def send_mail():
print("发送邮件") send_mail() # 1503492456.2909923
# 发送邮件
# 1503492456.2909923

3.2被装饰的函数有参数

def outter(fun):
def inner(a, b):
fun(a, b) return inner @outter
def add(a, b):
print("a+b:%d" % (a + b)) add(1, 2)
add(3, 4)
# a+b:3
# a+b:7

3.3被装饰的函数有不定长参数。

说明:把装饰器做成能装饰任何函数的装饰器,所以对于装饰器来说被装饰的函数的参数是不定长的。这样就应该用*args和**kwargs来当参数。

def outter(fun):
def inner(*args, **kwargs):
fun(*args, **kwargs) return inner @outter
def add(a, b, c):
print("a+b+c:%d" % (a + b + c)) t = (1, 2, 3)
add(*t) # a+b+c:6
d = {"a": 1, "b": 2, "c": 10}
add(**d) # a+b+c:13

3.4被装饰的函数有返回值。说明:一般情况下为了让装饰器更通用,可以有return。

def outter(fun):
def inner(*args, **kwargs):
temp = fun(*args, **kwargs)
return temp return inner @outter
def add(a, b, c):
return a + b + c t = (1, 2, 3)
ret = add(*t)
print(ret) #
ret = d = {"a": 1, "b": 2, "c": 10}
print(add(**d)) #
3.5装饰器带参数,在原有装饰器的基础上,设置外部变量。说明:装饰器带参数的执行过程是:首先将@ 和 arg_outter(arg)分离,将arg_outter(arg)的执行结果和@结合。
def arg_outter(arg):
def outter(fun):
def inner():
print("装饰器的参数是:%s" % arg)
if arg:
fun()
print("我是True,我会唱歌")
else:
fun() return inner return outter @arg_outter(True)
def song():
print("song") @arg_outter(False)
def listen():
print("listen") song()
listen()
3.6多层装饰器的使用。说明:多层装饰器,先看第一层的装饰器,把第一层当做函数调用,函数的参数是下一层的执行结果。
 具体分析:当遇到@tag1时,发现它是一个装饰器,所以开始函数调用,即装饰谁就传谁,但是发现装饰的不是一个函数,而是一个函数外面加了一个装饰
器,意味着把tag2以及下面作为一个整体形成的结果当做参数当做tag1的参数。返回结果即第一层里面的inner函数名字。用最终装饰器的函数名字进行
接收。即link_a。所以调用link_a的时候就是调用的tag1里面的inner函数。 使用装饰器的顺序很重要,如果未按预定的顺序执行,可以更改装饰功能的整体行为。
def tag1(fun):
def inner():
print("<li>", end="")
fun()
print("</li>", end="") return inner def tag2(f):
def inner():
print("<a>", end="")
f()
print("</a>", end="") return inner # 多层装饰器的使用
@tag1 # link_a = tag1( tag2(link_a) )
@tag2
def link_a():
print("我是一个超链接", end="") link_a() # tag1->inner() # <li><a>我是一个超链接</a></li>

3.7类装饰器(不常用)。说明:装饰器,log(say_hello),相当于一个类构造一个对象,所以把log构造成类,对象()即调用__call__()方法.

import time

class log(object):
def __init__(self, fun):
self.fun = fun def __call__(self):
"""当把对象当作函数进行调用时,被调用"""
print(time.time())
self.fun()
print(time.time()) @log
def say_hello():
print("say_hello") say_hello()
# 1503495467.9418454
# say_hello
# 1503495467.9418454

4.装饰器的主要作用:

引入日志

函数执行时间统计

执行函数前预备处理

执行函数后清理功能

权限校验等场景缓存

Java集合框架知识总结的更多相关文章

  1. java集合框架(一):HashMap

    有大半年没有写博客了,虽然一直有在看书学习,但现在回过来看读书基本都是一种知识“输入”,很多时候是水过无痕.而知识的“输出”会逼着自己去找出没有掌握或者了解不深刻的东西,你要把一个知识点表达出来,自己 ...

  2. Java集合框架的知识总结(1)

    说明:先从整体介绍了Java集合框架包含的接口和类,然后总结了集合框架中的一些基本知识和关键点,并结合实例进行简单分析. 1.综述 所有集合类都位于java.util包下.集合中只能保存对象(保存对象 ...

  3. Java集合框架的知识总结

    说明:面试准备,写的挺不错的. 转载地址: http://www.cnblogs.com/zhxxcq/archive/2012/03/11/2389611.html 1.综述 所有集合类都位于jav ...

  4. Java集合框架的总结

    本篇文章先从整体介绍了Java集合框架包含的接口和类,然后总结了集合框架中的一些基本知识和关键点,并结合实例进行简单分析.当我们把一个对象放入集合中后,系统会把所有集合元素都当成Object类的实例进 ...

  5. 【java集合框架源码剖析系列】java源码剖析之TreeSet

    本博客将从源码的角度带领大家学习TreeSet相关的知识. 一TreeSet类的定义: public class TreeSet<E> extends AbstractSet<E&g ...

  6. 【java集合框架源码剖析系列】java源码剖析之HashSet

    注:博主java集合框架源码剖析系列的源码全部基于JDK1.8.0版本.本博客将从源码角度带领大家学习关于HashSet的知识. 一HashSet的定义: public class HashSet&l ...

  7. 【java集合框架源码剖析系列】java源码剖析之TreeMap

    注:博主java集合框架源码剖析系列的源码全部基于JDK1.8.0版本.本博客将从源码角度带领大家学习关于TreeMap的知识. 一TreeMap的定义: public class TreeMap&l ...

  8. 【java集合框架源码剖析系列】java源码剖析之ArrayList

    注:博主java集合框架源码剖析系列的源码全部基于JDK1.8.0版本. 本博客将从源码角度带领大家学习关于ArrayList的知识. 一ArrayList类的定义: public class Arr ...

  9. 【java集合框架源码剖析系列】java源码剖析之LinkedList

    注:博主java集合框架源码剖析系列的源码全部基于JDK1.8.0版本. 在实际项目中LinkedList也是使用频率非常高的一种集合,本博客将从源码角度带领大家学习关于LinkedList的知识. ...

随机推荐

  1. Android中的桌面快捷方式

    一.判断是否已有快捷方式 private String getAuthorityFromPermission(Context context, String permission){ if (perm ...

  2. Windows 下 ffmpeg 转 mp4

    最近在研究所有视频格式转  mp4 因为html5 只支持mov MP4 等格式..查阅了 很多资料发现  转成flv  很简单.. 可是要转 mp4 就难了... 经过我不屑的努力..终于转换成功了 ...

  3. leetcode problem sum

    2. Add Two Numbers You are given two linked lists representing two non-negative numbers. The digits ...

  4. 分离式模型separation model

    1.关键字export 在头文件中定义模板,并且在模板的定义以及声明前添加关键字export. exported 模板可以直接使用,不需要看到该模板定义.模板的使用和定义可以分割于两个不同的编译单元. ...

  5. Centos7.2 yum配置

    一.yum 简介 yum,是Yellow dog Updater, Modified 的简称,是杜克大学为了提高RPM 软件包安装性而开发的一种软件包管理器.起初是由yellow dog 这一发行版的 ...

  6. Python socket (多线程)

    Server 端 code import SocketServer class MyTCPHandler(SocketServer.BaseRequestHandler): ""& ...

  7. Session管理解决方案笔记

    大型网站Session管理解决方案: 1. web服务器之间的session复制.    优点:方案成熟    缺点:复制的性能开销大 2. 减少session使用,使用客户端存储cookie     ...

  8. XPath使用示例

    1.查找空节点//*[not(text())]        表示内容为空的节点//*[count(*)=0]         表示没有子节点的节点"//*[count(*)=0 and n ...

  9. 学习django之构建Web是Meta嵌套类的几处使用

    Django中meta嵌套类的使用 1.模型中使用嵌套类 在定义抽象模型时如: class Meta : abstract=true 用来指明你创建的模型是一个抽象基础类的模型继承. 2.在一个对象对 ...

  10. Spring Batch 中文参考文档 V3.0.6 - 1 Spring Batch介绍

    1 Spring Batch介绍 企业领域中许多应用系统需要采用批处理的方式在特定环境中运行业务操作任务.这种业务作业包括自动化,大量信息的复杂操作,他们不需要人工干预,并能高效运行.这些典型作业包括 ...