• 周末学习笔记——day01(函数,函数对象,嵌套调用,名称空间,作用域,闭包,装饰器)


    一,复习

    字符编码
    
        文件头:py2—ASCII,py3—UTF-8
    
        三种字符串:u' '   b ' '  r ' '
    
        u' ' .endcode(' utf-8 ')
    
        b' '.deconde(' utf-8 ')
    
        str(b' ' , encode=' utf-8 ' )
    
        bytes( u' ' , encode=' utf-8 ')
    
    文件操作:
    
        三步骤:
            1,打开文件
            2,操作文件(读写)
            3,关闭
        简写:
            with open => 可以自动关闭文件流
        操作模式:
            主 :r  w  a   x
            从:t  b   +
        seek:游标(偏移量,游标操作位置)与b模式结合
    函数基础:
        函数的定义:def 函数名():函数体     函数调用:函数名()     函数的返回值:省略 空return return一个值 return多个值 =》本质返回一个装有多个值得元组

     

    二,今日内容:

        1,函数的参数:实参与形参
        2,函数对象:函数名
        3,名称空间与作用域:LEGB
        4,闭包:函数的嵌套定义
        5,装饰器:闭包的一种应用场景
        6,迭代器对象:迭代器,生成器,for迭代
        7,匿名函数
        8,内置函数
        9,三元表达式,列表,字典生成式
        10,模块

     

    三,如何定义函数:

        1,功能的单一化
        2,函数内部需要外部的资源:通过函数的参数来实现
        3,函数执行后的结果需要告诉外界:通过返回值告诉给外界

     

    四,函数的参数:


    形参与实参:     形参:在函数定义时()里出现的参数       ——形参本身没有实际值(意义),在函数调用时,传入什么实参,形参就装有什么值     实参:在函数调用时()里出现的参数       ——实参有实际值(意义)     重点:函数调用传参:将实参的值赋值给形参 | 形参要获取外界的值只能通过实参进行获取     def fn(a,b):   #a , b :形参       pass     a = 10     fn(a , 20)     #a , 20 实参

     两种实参:
        1,位置实参:

          a,传参两种方式:实参名|实参具体值

          b,必须按位置对形参进行传值

        2,关键字实参:

          a,传参两种方式:形参名=实参名 | 形参名=实参值

          b,可以指名道姓对形参进行传值,所以可以不用按位置进行传参

        '''

          def func(a,b,c):

             print(a,b,c)

          #func(10,b=20,200)  #报错:SyntaxError: positional argument follows keyword argument

        '''

        #重点:两种实参在一起进行传参时:必须位置在前,关键字在后

     

     两大形参分类:

        形参种类:

          1,位置形参:

            ——普通位置形参

            ——默认值形参

            ——可变长位置形参

          2,关键字形参:

            ——有默认值关键字形参

            ——无默认值关键字形参

            ——可变长关键字

        '''

          def fn(a,b,*,x,y):  #位置形参:a,b  关键字形参:x,y

            pass

        '''

        重点:

          1,*为分水岭

          2,位置实参只能给位置形参进行传值

          3,关键字实参可以给位置形参与关键字形参进行传值

        

     两个带默认值的形参:

        '''

          def fn2(a=10,*,x=20):

            print(a,x)

          fn2(100,x=200)

        '''

        总结:

          1,有默认值的参数可以不用传值

          2,*前有默认值的叫默认值参数,属于位置形参,可以被位置及关键字实参进行传值

          3,*后有默认值的叫有默认值的关键字形参,属于关键字形参,只能被关键字实参进行传值

          4,如果省略*,有默认值的形参都是默认值参数

     

     不带默认值与带默认值形参结合使用:  

    def fn3(a, b=10, *, x, y=20, z):
    print(a, b, x, y, z)
    fn3(100, x=200, z=300)
    # 总结:
    # 1.没有默认值的必须传参,有默认值的可以传也可以不传
    # 2.位置有值的必须出现在无值之后,关键字顺序不做要求

     

     可变长位置形参与可变长关键字形参:

    def fn4(a, b=10, *args, x, **kwargs):
       print(a, b, x)
       print(args)
       print(kwargs)
    fn4(10, 20, 30, x=100, y=200, z=300)

      总结:
    1.可变长是用来接收未接收完的值(接收0到n个):
         -- *args用来接收所有没有接收完的位置(只能接收位置实参)
         -- **kwargs用来接收所有没有接收完的关键字(只能接收关键字实参)
      2.*args必须出现在所以位置参数之后,**kwargs必须出现在所以参数之后

     

    # 常见应用场景
      假设第一个位置永远是参数name

      def func4(*args, **kwargs):
         name = args[0]  # 将name抽出来

      def func44(name, *args, **kwargs):
         # name 可以直接接收,省了抽出来的过程
         pass

     

      总结:

    1.位置实参只能给位置形参传值
    2.关键字实参可以给位置及关键字形参传值
    3.有默认值的可以不用传参
    4.可变长位置形参只能接受位置实参,接受位置形参没有接收完的位置实参,存放到元组中
    5.可变长关键字形参只能接受关键字实参,接受关键字形参没有接收完的关键字实参,存放到字典中
    6.*args必须出现在所有位置形参之后,**kwargs必须在所有形参之后

     

     可变长整体传参:打散传值

          '''

    def fn(*args, **kwargs):
    print(args, kwargs)

    fn([1, 2, 3], {'a':1 , 'b': 2}) # =>接收到的 ([1, 2, 3], {'a':1 , 'b': 2}) {}
    fn(*[1, 2, 3], **{'a':1 , 'b': 2}) # =>接收到的 (1, 2, 3) {'a':1 , 'b': 2}

     

    # 注:字符串也可以作为单列集合进行打散传递
    fn(*'abc') # => ('a', 'b', 'c') {}

          '''

     

     

    五,函数对象:

    #函数名就是存放了函数的内存地址,存放了内存地址的变量都是对象,即 函数名 就是 函数对象
    
    #函数对象的应用场景
      1 可以直接被引用
      2 可以当作函数参数传递
      3 可以作为函数的返回值
      4 可以作为容器类型的元素

    '''
      #功能体:
       def add(n1,n2):
          return n1 + n2

       def low(n1,n2):
          return n1 - n2

       def jump(n1,n2):
          return n1 * n2

      #完成功能:
       def computed(n1,n2,fn):  #fn = add|low|jump
          res = fn(n1,n2)    #调用具体的功能
          return res

      #功能对应关系:
       method_map = {       #指令与函数对象的对应关系
          '1':add,
          '2':low,
          '3':jump
        }
      
      #获取功能:
       def get_method(cmd):
          if cmd in method_map:
            return method_map[cmd]  #返回 add|low|jump
          return add           #当指令错误,add作为默认功能
       while True:
        cmd = input('cmd')
        res = get_method(cmd)(10,20)  #根据指令获取功能并调用得到结果
        print(res)
    '''

     

    六:函数的嵌套调用

    # 函数的嵌套调用:在一个函数内部调用另一个函数
    # 求两个数最大值
    '''
      def max_tow(n1,n2):
        if n1 > n2:
          return n1
        return n2

      #求三个数的最大值
      def max_three(n1,n2,n3):
        max = max_tow(n1,n2)
        return max_tow(max,n3)

      #求四个数的最大值
      def max_four(n1,n2,n3,n4)
        max = max_three(n1,n2,n3)
        return max_tow(max,n4)
      print(max_four(20,90,30,10))
    '''

     

    七:名称空间:

    # 名称空间:存放名字与内存空间地址对应关系的容器
    # 作用:解决由于名字有限,导致名字重复发送冲突的问题 - 内置全局局部可以同时使用一个名字存放不同地址

    # 三种名称空间
    # Built-in:内置名称空间;系统级,一个;随解释器执行而产生,解释器停止而销毁
    # Global:全局名称空间;文件级,多个;随所属文件加载而产生,文件运行完毕而销毁
    # Local:局部名称空间;函数级,多个;随所属函数执行而产生,函数执行完毕而销毁

    # 加载顺序:Built-in > Global > Loca
    # -- 采用堆栈存储数据的方式(压栈),导致内置最后被访问

     

    八,函数的嵌套定义:

    # 函数的嵌套定义:在函数内部定义函数
    # 诞生的理由:一个函数想使用另一个函数内部的变量,可以定义在其内部

    '''
      def func():
        a = 10
        def fn():
          print(a)
        return fn

      new_fn = func()
      new_fn()
    '''

    #两个与函数有关的关键字:global nonlocal
    '''
      #global :统一局部与全局的变量名
      num = 10
      def outer():
        #global num
        #num = 100
        def inner():
          global num
          num = 1000

      #nonlcal:统一局部与嵌套局部的变量名
      def outer():
        num = 100
        def inner():
          nonlcal num
          num = 1000
    '''

     

    九,作用域:

    # 作用域:名字起作用的范围
    # 作用:解决同名字可以共存问题 - 不同作用域相同名字的值都能在其作用域范围下进行使用
    '''
    四种作用域: LEGB
    Built-in:内置作用域 - 所有文件所有地方都可以被访问
    Global:全局作用域 - 在当前文件的所有位置
    Enclosing:嵌套作用域 - 自身内部与内部的子函数
    Local:局部作用域 - 只有自身内部
    '''
    # 加载顺序:Built-in > Global > Enclosing > Local
    # 访问(查找)顺序:报错 < Built-in < Global < Enclosing < Local
    # 作用范围:Built-in > Global > Enclosing > Local

     

     十,闭包

    # 闭包:定义在函数内部的函数,这个内部的函数就是闭包

    #应用场景:

      1,可以去使用其他函数的内部变量,且还可以保证调用位置不变(闭包的函数对象作为那个函数的返回值)
      '''
        def outer():
          count = 3000
          def fn():
            print(count) #能使用outer内部的变量count
          return fn

        #还是在外界调用
        outer()() #outer()()=>fn()=>调用fn
      '''

      2,延迟执行(外层函数可以为内部函数传递参数)
      '''
        import requests
        def outer(url):
          def show_html():
            response = requests.get(url)
            print(response.text)
          return show_html

        #制作 爬百度与新浪的 函数对象
        show_baidu = outer('https://www.baidu.com')
        show_sina = outer('https://www.sina.com.cn')

        #延迟的需求来了,需要爬百度,就用百度函数对象,需要爬新浪,就用新浪函数对象
        show_baidu()
        show_sina()
        show_baidu()

      '''

     

    十一,装饰器

    # 装饰器:装饰器就是闭包的一个应用场景
    #       -- 外层函数与内层函数形成的闭包结构的一种综合使用
    
    # 重点:开放封闭原则
    # 开放:拓展功能的点是开放的 - 可以为之前的函数添加新功能
    # 封闭:1.不能改变原函数的源代码  2.还有通过原函数的函数对象来调用函数

    '''
      def huaping():
        print('插花功能')

      temp = huaping

      def my_huaping():
        temp()
        print('观赏功能')

      huaping = my_huaping

      huaping()
    '''  
    #------------------------------------------------------
    '''
      def huaping():
        print('插花功能')

      def outer(temp):       #temp = huaping
        def my_huaping():
          temp()
          print('观赏功能')
        return my_huaping
      huaping = outer(huaping) #huaping = my_huaping

      huaping()
    '''
    #------------------------------------------------------
    '''
      def outer(temp):    #temp = huaping
        def my_huaping():
          temp()
          print('观赏功能')
        return my_huaping
      
      @outer   #huaping = outer(huaping)
      def huaping():
         print('插花功能')

      huaping()
    '''
    #-----------------------------------------------------
    #被装饰的函数可能有参有返回:装饰器模板,可以满足所有参数,且能装饰原函数返回值
    '''
    def outer(func):  #temp = huaping
       def inner(*args , **kwargs):
          pass
          res = func(*args,**kwargs)
          pass
          return res
       return inner

    @outer
    def any_method():
       pass
    '''

     

    十二:装饰器案例


    #为登录功能添加账号检验功能:必须是3个及以上英文字母组成
    '''
      def check_user(func):
        def inner(user,pwd):
          if not(user.isalpha() and len(user) >= 3):
            return '账号不合法'
          res = func(user,pwd)
          return res
        return inner
    '''

    #为登录功能添加密码检验功能:必须是3个及以上英文字母或数字组成
    '''
      def check_pwd(func):
        def inner(*args,**kwargs):
          pwd = args[1]
          if not(pwd.isalnum() and len(pwd) >= 3):
            return '密码不合法'
          res = func(*args,**kwargs)
          return res
        return inner
    '''

    #为登录结果的修饰装饰器:True => 登陆成功 ,False => 登录失败
    '''
      def change_res(func):
        def inner(*args,**kwargs):
          res = func(*args,**kwargs)
          if res = True:
            return '登陆成功'
          return '登陆失败'
        return inner
    '''

    #装饰器被执行的过程是从上至下
    '''
      @check_user        #login = check_user(func=login)=inner
      @check_pwd
      @chang_res
      def login(user,pwd):  #被装饰的函数对象
        if user == 'Owen' and pwd == '123':
          return True
        return False
      user = input('user: ')
      pwd = input('pwd: ')
      res = login(user,pwd)
      
      print(res)
    '''

     

  • 相关阅读:
    BZOJ3105: [cqoi2013]新Nim游戏 博弈论+线性基
    BZOJ3759: Hungergame 博弈论+线性基
    NOI模拟赛Day2
    期望dp BZOJ3450+BZOJ4318
    NOI模拟赛 Day1
    NOI模拟 热身赛T1
    【BZOJ4260】 Codechef REBXOR 可持久化Trie
    【BZOJ3673】&&【BZOJ3674】: 可持久化并查集 by zky 可持久化线段树
    【BZOJ3207】花神的嘲讽计划I 可持久化线段树/莫队
    【bzoj3527】[Zjoi2014]力 FFT
  • 原文地址:https://www.cnblogs.com/HZLS/p/10707553.html
Copyright © 2020-2023  润新知