函数“变量”(或“变量”函数)
x = 1
y = x
def test1():
print("Do something")
test2 = lambda x:x*2
函数和变量是一样的,都是“一个名字对应内存地址中的一些内容”
那么根据这样的原则,我们就可以理解两个事情:
1.test1表示的是函数的内存地址
2.test1()就是调用对在test1这个地址的内容,即函数
高阶函数
对于高阶函数的形式可以有两种:
1.把一个函数名当作实参传给另外一个函数(“实参高阶函数”)
2.返回值中包含函数名(“返回值高阶函数”)
import time
def test():
time.sleep(5)
print('test is running')
def deco(func):
start=time.time()
func() #將所有的func换为test #2
stop=time.time()
print(stop-start)
deco(test) #1
在#1处,我们把test当作实参传递给形参func,即func=test。注意,这里传递的是地址,也就是此时func也指向了之前test所定义的那个函数体,可以说在deco()内部,func就是test。在#2处,把函数名后面加上括号,就是对函数的调用(执行它)
import time
def test():
time.sleep(2)
print("test is running!")
def deco(func):
print(func) #<function test at 0x00000270E6524D90>;输出函数地址
return func #会返回一个test出来,func=test
t = deco(test) #3
t()#4
在#3处,将test传入deco(),在deco()里面操作之后,最后返回了func,并赋值给t。因此这里test => func => t,都是一样的函数体。最后在#4处保留了原来的函数调用方式。
看到这里显然会有些困惑,我们的需求不是要计算函数的运行时间么,怎么改成输出函数地址了。是因为,单独采用第二张高阶函数(返回值中包含函数名)的方式,并且保留原函数调用方式,是无法计时的。如果在deco()里计时,显然会执行一次,而外面已经调用了test(),会重复执行。这里只是为了说明第二种高阶函数的思想
嵌套函数
嵌套函数指的是在函数内部定义一个函数,而不是调用
def fun1():
def fun2():
pass
而不是
def fun1():
fun2()
函数只能调用和它同级别以及上级的变量或函数。也就是说:里面的能调用和它缩进一样的和他外部的,而内部的是无法调用的
import time
def timer(func): #5
def deco():
start = time.time()
func()
stop = time.time()
print(stop-start)
return deco
def test():
time.sleep(2)
print("test is running!")
test = timer(test) #6
test() #7
在#6处,把test作为参数传递给了timer(),此时,在timer()内部,func = test,接下来,定义了一个deco()函数,当并未调用,只是在内存中保存了,并且标签为deco。在timer()函数的最后返回deco()的地址deco。
然后再把deco赋值给了test,那么此时test已经不是原来的test了,也就是test原来的那些函数体的标签换掉了,换成了deco。那么在#7处调用的实际上是deco()。
那么这段代码在本质上是修改了调用函数,但在表面上并未修改调用方式,而且实现了附加功能
真正的装饰器
根据以上分析,装饰器在装饰时,需要在每个函数前面加上:
test = timer(test)
显然有些麻烦,Python提供了一种语法糖,即:
@timer
这两句是等价的,只要在函数前加上这句,就可以实现装饰作用
装饰有参函数
- 转载
Python中变量在内存的存储与地址变化详解(深浅拷贝,值/引用传递、可变不可变数据类型)
- 转载
def sum(a):
a+=1
a=6
sum(a)
print(a) #6
为什么在这里形参的数值并不改变实参的数值?
这里需要给大家普及一个Python中的基础,在python中,string(字符串), tuples(元组),
和number(数值)是不可更改的对象,而list(列表),dict(字典)等则是可以修改的对象。也就是说,这里形参的数值对于外部的实参的数值(number类型,不可变)来说是没有任何关系的,他们虽然是同一个名字,但是其指向对象是不一样的。所以当在程序最后进行打印a输出值的时候,其输出仍然是6
list=[1,2,3,4]
temp=list[2]
print(temp) #3;Temp=m[A:B] %表示将m列表里从索引号位置为A开始的元素到B-1处元素之间的列表获取赋给temp
def swap(list):
temp=list[0] #1
list[0]=list[1] #list[2,2]; [1,2]的第一位1等于[1,2]的第二位2等于[2,2]
list[1]=temp #2;[2,2]的第二位等于temp,而temp等于1,所以list=[2,1]
list=[1,2]
swap(list)
print(list) # [2,1]
与第一个栗子刚刚相反,这里形参的数值调用把实参改变了。因为本例中参数传递的是列表,其是可更改的对象,在函数内部经过系列赋值变化之后,所以在程序运行之后其输出值产生了变化