python作为解释型语言,变量如何存放在内存中?
将内存作为一个大房子,如何将变量安排在大房子中的一个个小房子中
x=1,1存入内存中的一个小房间中,x 作为此房间的门牌号,只有有门牌号的内存才是可被访问的
若x=1,y=x,则是将1这个内存小房间上重新贴了1个门牌y
而在python中,函数也可以作为变量,也可以被调用
例如:
def bar():
print("in the bar")
def foo():
print("in the foo.")
bar()
foo()
bar()这个函数被foo函数调用,可以将bar()同样看做一个变量,函数名作为门牌号(内存标签),内存中实际存放的是函数体
另外需要注意的一点是,函数调用或者参数调用 不会因为定义位置而影响调用。
就是无论你是先声明,还是后声明,都会被正常调用。
上面的例子,bar和foo的先后位置,并不影响,最后的输出结果。
python内存回收实际就是门牌号被揭掉的时候,即内存标签被去掉后,内存会定期回收
这些没有门牌号的内存,或者在程序执行后都被回收
对于匿名函数lamda x:3*x 这种若没有参数接收匿名函数的值,同样的会被回收
只有变量接收匿名函数的值,等于给匿名函数贴上了门牌号,
calc=lamda x:x*3
高阶函数
1.将函数作为实参调用(在不修改被装饰函数源代码的情况下为其添加功能)
def test1(func):
print(func)
def test2():
print("in the test2")
test1(test2)
执行结果会返回test2的内存地址
<function test2 at 0x0000000002877840>
这其实与我们之前提到的,test2作为实参传入test1,test1调用打印test2函数的内存地址
import time
def test1(func):
start_time=time.time()
func()
stop_time=time.time()
print("The run time is %s" %(stop_time-start_time))
def bar():
time.sleep(3)
print("in the bar")
test1(bar)
bar()为函数调用,bar是之前我们提到的,函数的内存标签,将函数名bar传入test1函数,同时在执行过程中调用了bar()函数
将函数名作为返回值进行返回(用函数名调用函数体),不修改函数的调用方式
def test1(func):
return(func)
def test2():
print("in the test2")
t=test1(test2)
test1调用test2,同时将test2的内存标签传给t,其实t直接加括号就相当于了test2
t(),执行结果会打印in the test2。因为返回值,返回的是函数名,及内存标签,直接加括号就是函数体。但print的值是不可以的,显示类型为空
函数嵌套:在函数中定义函数,类似于函数中的局部变量,嵌套的函数只能在函数体内调用,不能在函数体外调用
def test1():
print("in the test1")
def test2():
print("in the test2")
test1()
通过高阶函数加嵌套函数 实现程序计时:
import time
def timmer(func):
start_time=time.time()
func()
stop_time=time.time()
print("The run time is %s" %(stop_time-start_time))
def test1():
time.sleep(3)
print("in the test1")
timmer(test1)
通过高阶函数的方式,这样实现了函数运行时间的计数,但这样改变了函数的调用方式
通过高阶函数+嵌套函数的方式去为test1 添加计数的功能同时不改变test1的调用方式
import time
def timmer(func):
def deco():
start_time=time.time()
func()
stop_time=time.time()
print("The run time is %s" %(stop_time-start_time))
return deco
def test1():
time.sleep(3)
print("in the test1")
test1=timmer(test1)
test1()
通过嵌套的方式,将嵌套函数的返回值赋给test1,实际获得是deco这个内部函数的标签,然后test1直接运行在实际没改变调用方式的情况下,获取了程序运行的时间,但这样需要声明与函数名相同的变量
python提供了装饰器的写法,只需要在需要处理的函数前面加上@装饰函数即可
import time
def timmer(func):
def deco():
start_time=time.time()
func()
stop_time=time.time()
print("The run time is %s" %(stop_time-start_time))
return deco
@timmer
def test1():
time.sleep(3)
print("in the test1")
@timmer
def test2():
time.sleep(3)
print("in the test2")
test1()
test2()
装饰器=高阶函数+函数嵌套
例子:使用用户名密码登录不同页面
简单实现:
user,passwd='dave','test123'
def login(func):
def wrapper(*args,**kwargs):
name=input("please input your username:")
password=input("please input your password:")
if name==user and password==passwd:
func()
print('login success')
else:
print("invalid username or password")
return wrapper
def index():
print("welcome to the index page")
@login
def home():
print("welcome to the homepage")
@login
def bbs():
print("welcome to bbs page")
加入需要选择不同的验证方式,例如本地验证或者LDAP验证,一般我们是在装饰器调用的位置加参数,而同样的我们则需要进一步构建装饰器函数,再加另外的一层嵌套函数。
name,passwd='dave','test123'
def login(auth_type):
def out_wrapper(func):
def wrapper(*args, **kwargs):
usrname = input("Please input username:")
password = input("please input your password:")
if auth_type == 'local':
if usrname == name and password == passwd:
res = func(*args, **kwargs)
print("login sucess,local login")
return res
else:
exit("invalid username or password")
elif auth_type == 'ldap':
exit('now cant use ldap')
return wrapper
return out_wrapper
def index():
print("welcome to index page")
@login(auth_type='local')
def home():
print("welcome to the homepage")
return "from home"
@login(auth_type='ldap')
def bbs():
print("welcome to bbs page")
index()
home()
bbs()
最外层的嵌套实际的作用就是接收装饰器的参数,这样可以提供更多选择
网友评论