Table of Contents
03总结
目的:在不修改函数内部的前提下修改函数功能
01 基本功能的实现方法
#问题:初中学过函数(y=kx+b, y=ax^2+bx+c)
#以y=kx+b为例,计算一条线上多个点:给x得y
#法1 不能重用 k=1 b=2 y=k*x+b #法2同线多点时,k b不能保存 def line_2(k,b,x): print(k*x+b) line_2(1,2,0) |
#希望不会随着函数的调用而结束 #法3 全局变量 换线需要每次对全局变量修改,代码增多 k=1 b=2 def line_3(x): print(k*x+b)#使用全局变量不用加global,修改指向才需要 line_3(0) k=1 b=1 line_3(0) #法4 关键字参数配合缺省参数(缺省参数必须放最后) #优点:封装,kb不可任意修改 #缺点:多线需要传递 def line_4(x,k=1,b=2): print(k*x+b) line_4(0) line_4(0,k=2,b=1) |
02使用类实现功能
只要创建完self实例,就随着对象的存在而存在,而不会随着方法的结束而结束
类中有__call__方法,则可对象后加括号触发执行
#使用类(面向对象)可以保存重复使用的kb值 #法5:实例对象 缺点:每条线保存实例对象,使用空间较多 class Line5(object): def __init__(self,k,b): self.k=k#只要创建完self实例,就随着对象的存在而存在,而不会随着方法的结束而结束 self.b=b def __call__(self,x): print(self.k*x+self.b)
line_5_1=Line5(1,2) line_5_1(1) line_5_2=Line5(2,1) line_5_2(1) |
闭包:多层函数嵌套的定义,主要需要的是内部的函数,一般内部函数需要用到外部函数的变量
#法6 闭包(一个函数中套着另一个函数的定义,主要需要的是内部的函数,一般需要用到外部函数的变量) #核心需要的就是k、b、计算函数 def line_6(k,b):#带着1,2调用函数 def create_y(x): print(k*x+b) return create_y#将函数指针返回
line_6_1=line_6(1,2)#调用函数,获得计算y的函数的指针 line_6_1(1)#调用create_y,输入形参x,b内部没有定义,向外部找 |
闭包相对于面向对象,比较省空间,比较干净,只有所需的变量和方法的整体,没有那么多魔法属性魔法方法
03
使用面向对象时的目的为:全局变量可直接用,但暴露于其他函数
所以创立一个内存空间,其中有变量和函数
闭包也是有变量和函数,但没有其他魔法属性、方法
def line(k,b): num=100#也可拥有一个外部函数的变量 def create_y(x): print(k*x+b) return create_y |
将函数名作为实参传递,得到引用,可以使用函数的代码和变量
函数、匿名函数、闭包、对象区别:
函数将代码封装
匿名函数也可封装代码,但当作实参,完成小部分代码时更方便
闭包不仅可给功能代码,还可带数据
实例对象的引用,可调用其中任何方法和属性
04修改数据
修改外部函数变量的值,就像修改全局变量时加global一样
x=3 def test1(): x=2 def test2(): print("x=%d" %x)#内部后面有定义,则外部不可用 x=1#定义了内部函数的局部变量 print("x=%d" %x)#1 return text2#不写括号才返回引用,写括号则得其返回值 t1=test() t1() |
def test1(): x=2 def test2(): nonlocal x#py3修改外部函数的局部变量 print("x=%d" %x) x=1#定义了内部函数的局部变量 print("x=%d" %x)#1 return text2#不写括号才返回引用,写括号则得其返回值 |
它闭包可以实现装饰器