• 函数对象、函数嵌套、名称空间与作用域、装饰器


    ---恢复内容开始---

    一、函数对象

    1. 函数是第一类对象,即函数可以当作数据传递
      #1 可以被引用
      #2 可以当作参数传递
      #3 返回值可以是函数
      #3 可以当作容器类型的元素
    2. 利用该特性,优雅的取代多分支的if 

    二、函数嵌套

    1. 函数的嵌套调用
      def max(x,y):
          return x if x > y else y
      
      def max4(a,b,c,d):
          res1=max(a,b)
          res2=max(res1,c)
          res3=max(res2,d)
          return res3
      print(max4(1,2,3,4))
    2. 函数的嵌套定义
      def f1():
          def f2():
              def f3():
                  print('from f3')
              f3()
          f2()
      
      f1()

    三、命名空间与作用域

    1. 什么是命名空间
      #命名空间:存放名字的地方,三种命名空间,(之前遗留的问题x=1,1存放于内存中,那名字x存放在哪里呢?命名空间正是存放名字x与1绑定关系的地方)
    2. 命名空间的加载顺序
      python test.py
      #1、python解释器先启动,因而首先加载的是:内置命名空间
      #2、执行test.py文件,然后以文件为基础,加载全局命名空间
      #3、在执行文件的过程中如果调用函数,则临时产生局部命名空间
    3. 名字的查找顺序
      局部命名空间--->全局命名空间--->内置命名空间
      
      #需要注意的是:在全局无法查看局部的,在局部可以查看全局的,如下示例
      
      # max=1
      def f1():
          # max=2
          def f2():
              # max=3
              print(max)
          f2()
      f1()
      print(max) 
    4. 作用域
      #1、作用域即范围
              - 全局范围(内置名称空间与全局名称空间属于该范围):全局存活,全局有效
            - 局部范围(局部名称空间属于该范围):临时存活,局部有效
      #2、作用域关系是在函数定义阶段就已经固定的,与函数的调用位置无关,如下
      x=1
      def f1():
          def f2():
              print(x)
          return f2
      x=100
      def f3(func):
          x=2
          func()
      x=10000
      f3(f1())
      
      #3、查看作用域:globals(),locals()
      
      
      LEGB 代表名字查找顺序: locals -> enclosing function -> globals -> __builtins__
      locals 是函数内的名字空间,包括局部变量和形参
      enclosing 外部嵌套函数的名字空间(闭包中常见)
      globals 全局变量,函数定义所在模块的名字空间
      builtins 内置模块的名字空间
    5. global与nonlocal关键字

    四、闭包函数

    1. 什么是闭包
      #内部函数包含对外部作用域而非全局作用域的引用
      
      #提示:之前我们都是通过参数将外部的值传给函数,闭包提供了另外一种思路,包起来喽,包起呦,包起来哇
      
              def counter():
                  n=0
                  def incr():
                      nonlocal n
                      x=n
                      n+=1
                      return x
                  return incr
      
              c=counter()
              print(c())
              print(c())
              print(c())
              print(c.__closure__[0].cell_contents) #查看闭包的元素
    2. 闭包的意义与应用
      #闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域
      #应用领域:延迟计算(原来我们是传参,现在我们是包起来)
          from urllib.request import urlopen
      
          def index(url):
              def get():
                  return urlopen(url).read()
              return get
      
          baidu=index('http://www.baidu.com')
          print(baidu().decode('utf-8'))

    五、装饰器

    装饰器就是闭包函数的一种应用场景

    1. 为何要用装饰器
      #开放封闭原则:对修改封闭,对扩展开放
    2. 什么是装饰器
      装饰器他人的器具,本身可以是任意可调用对象,被装饰者也可以是任意可调用对象。
      强调装饰器的原则:1 不修改被装饰对象的源代码 2 不修改被装饰对象的调用方式
      装饰器的目标:在遵循1和2的前提下,为被装饰对象添加上新功能
    3. 装饰器的使用
      import time
      def timmer(func):
          def wrapper(*args,**kwargs):
              start_time=time.time()
              res=func(*args,**kwargs)
              stop_time=time.time()
              print('run time is %s' %(stop_time-start_time))
              return res
          return wrapper
      
      @timmer
      def foo():
          time.sleep(3)
          print('from foo')
      foo()
      def auth(driver='file'):
          def auth2(func):
              def wrapper(*args,**kwargs):
                  name=input("user: ")
                  pwd=input("pwd: ")
      
                  if driver == 'file':
                      if name == 'egon' and pwd == '123':
                          print('login successful')
                          res=func(*args,**kwargs)
                          return res
                  elif driver == 'ldap':
                      print('ldap')
              return wrapper
          return auth2
      
      @auth(driver='file')
      def foo(name):
          print(name)
      
      foo('egon')
    4. 装饰器的语法
      被装饰函数的正上方,单独一行
              @deco1
              @deco2
              @deco3
              def foo():
                  pass
      
              foo=deco1(deco2(deco3(foo)))
    5. 装饰器补充:wraps
      from functools import wraps
      
      def deco(func):
          @wraps(func) #加在最内层函数正上方
          def wrapper(*args,**kwargs):
              return func(*args,**kwargs)
          return wrapper
      
      @deco
      def index():
          '''哈哈哈哈'''
          print('from index')
      
      print(index.__doc__)

     

    ---恢复内容结束---

  • 相关阅读:
    js类型转换的坑
    JS自动填写分号导致的坑
    tomcat+javaWeb+spring的一个都市供求管理系统
    java学习笔记--java中的基本数组[5]
    mysql基础语法及拓展到web中的sql注入
    angular指令大全
    在chrome下-webkit-box布局的一个bug
    use redis instance in docker hub
    centos yum install oracle java
    认识Debian
  • 原文地址:https://www.cnblogs.com/lurches/p/8681115.html
Copyright © 2020-2023  润新知