美文网首页
函数变量,装饰器

函数变量,装饰器

作者: 戈羽殇雪 | 来源:发表于2019-10-30 15:47 被阅读0次

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()

最外层的嵌套实际的作用就是接收装饰器的参数,这样可以提供更多选择

相关文章

  • 装饰器

    1.装饰器的概念 装饰器是一个闭包:内层函数引用外层函数的变量(参数也算变量),然后返回内层函数,就是闭包。装饰器...

  • 浅析装饰器的那些事儿

    一、装饰器的简单定义 外层函数返回里层函数的引用,里层函数引用外层函数的变量。 二、装饰器的作用 通俗来讲装饰器的...

  • 函数变量,装饰器

    python作为解释型语言,变量如何存放在内存中?将内存作为一个大房子,如何将变量安排在大房子中的一个个小房子中x...

  • 解析Python中的装饰器

    python中的函数也是对象,函数可以被当作变量传递。 装饰器在python中功能非常强大,装饰器允许对原有函数行...

  • python 装饰器decorator

    闭包函数:函数内部定义的函数,引用了外部变量但非全局变量。 装饰器 decorator 实质: 是一个函数 参数:...

  • 区别普通嵌套函数、闭包、装饰器

    1.普通嵌套函数: 2.闭包: 闭包,本质是个函数,即调用了自由变量x的函数inner 3.装饰器: 装饰器是一个...

  • python笔记11:装饰器

    1. 什么是装饰器 函数也是一个对象,并且可以赋值给变量==>通过变量调用该函数 期望:增强main()函数功能,...

  • Python装饰器

    在Python里面,函数可以作为参数传入一个函数,函数也可以复制给变量,通过变量调用函数。装饰器可以扩展一个函数的...

  • 了解女朋友的心还不如去了解Python之Python装饰器

    在Python里面,函数可以作为参数传入一个函数,函数也可以复制给变量,通过变量调用函数。装饰器可以扩展一个函数的...

  • 装饰器

    [TOC] 函数 函数定义 函数调用 高阶函数 嵌套函数 装饰器 装饰器=高阶函数+嵌套函数 基础装饰器 假设有一...

网友评论

      本文标题:函数变量,装饰器

      本文链接:https://www.haomeiwen.com/subject/egmgvctx.html