• Python基础学习笔记(11)函数的陷阱 函数名的运用 f-string 迭代器


    Python基础学习(11)函数的陷阱 函数名的运用 f-string 迭代器

    一、今日内容大纲

    • 函数的陷阱

    • 关键字:global、nonlocal

    • 函数名的运用

    • Python 3.6 新特性:f-string

    • 迭代器

    二、函数的陷阱

    1. 默认参数的陷阱

      针对默认参数是可变数据类型。无论你调用多少次这个默认参数,所调用的都是同意地址下的数据。

      def func(name, list=[]):
          list.append(name)
          return list
      
      ret = func('alex')
      print(ret, id(ret))  # ['alex'] 2636141462472
      ret2 = func('太白金星')
      print(ret2, id(ret2))  # ['alex', '太白金星'] 2636141462472
      
      # Exercise 1:
      def func(a, list=[]):
          list.append(a)
          return list
      print(func(10, ))  # [10]
      print(func(20, []))  # [20] (This call passes in another list)
      print(func(100, ))  # [10, 100]
      
    2. 局部作用域的陷阱

      count = 1
      def func():
          print(count)  # error: local variable 'count' referenced before assignment
          count = 3
      func()
      
      count = 1
      def func():
          print(count)  # No error, function can find global variable 'count'
      func()
      

    二、关键字 global nonlocal

    1. global

      • 功能一:在局部作用域声明一个全局变量。

        # 在局部作用域声明一个全局变量,
        name = 'alex'
        def func():
            global name
            name = '太白金星'
            print(name)
        func()  # 太白金星
        print(name)  # 太白金星
        
        # tip:
        name = 'alex'
        def func():
            global name
            name = '太白金星'
            print(name)
        print(name)  # 'alex', The function has not declared a global variable
        func()  # 太白金星
        
      • 功能二:对已经声明的全局变量进行修改

        # 对已经声明的全局变量进行修改
        count = 1
        def func():
            global count
            count += 1
        print(count)  # 1
        func()
        print(count)  # 2
        
    2. nonlocal(Python 3x)

      用于局部作用域,不能操作全局变量, 支持内层函数对外层函数的局部变量进行修改。

      def wrapper():
          count = 1
          def inner():
              nonlocal count
              count += 1
          print(count)  # 1
          inner()
          print(count)  # 2
      wrapper()
      

    四、函数名的运用

    1. 函数名指代的是函数的内存地址

      def func():
          pass
      print(func, type(func))  # <function func at 0x000002B8B3E41F28> <class 'NoneType'>
      
    2. 函数名可以赋值给其他变量

      def func():
          pass
      f = func
      print(f, type(f))  # <function func at 0x000002B8B3E41F28> <class 'function'>
      
    3. 函数名可以作为容器型数据类型的元素

      def func1():
          print('in func1')
      def func2():
          print('in func2')
      def func3():
          print('in func3')
      l1 = [func1, func2, func3]
      for i in l1:
          i()
          
      # result:
      # in func1
      # in func2
      # in func3
      
    4. 函数名可以作为函数的参数

      def func():
          print('in func')
      
      def func1(x):
          x()
      
      func1(func)  # in func
      
    5. 函数名可以作为函数的返回值

      def func():
          print('in func')
      
      def func1(x):
          print('in func1')
          return x
      
      ret = func1(func)  # func1()
      ret()  # func()
      

    五、Python 3.6 新特性:f-string

    1. 基本用法

      name = 'taibai'
      age = 18
      msg = f'my name is {name}, {age} years old.'
      print(msg)  # my name is taibai, 18 years old.
      
    2. 加入表达式

      dic = {'name': 'alex', 'age': 73}
      msg = f'my name is {dic["name"]}, {dic["age"]} years old.'
      print(msg) # my name is alex, 73 years old.
      
    3. 结合函数

      def _sum(a, b):
          return a + b
      
      msg = f'result is {_sum(10, 20)}'
      print(msg)  # result is 30
      
      # tips:
      # ! , : { } 不可以出现在{}里面,会出现报错
      
    4. 优点

      • 结构更加简化
      • 可以结合表达式、函数进行使用
      • 效率提升

    六、迭代器

    1. 可迭代对象 iterate

      根据字面意思可以理解为:"可以重复取值,更新迭代的对象“。在python中,但凡内部含有“__iter__”方法的对象,都是可迭代对象。str list tuple dic set range file_handler 等都是可迭代对象。

    2. 查看对象内部方法 dic()

      dic() 是 directory 的缩写,会返回一个列表,这个列表中含有该对象的以字符串形式表示的所有方法名称,我们可以通过寻找返回列表内部是否具有'_iter_'来判断该对象是否是可迭代对象。

      s1 = 'asdf'
      s2 = 199
      attributes_s1 = dir(s1)
      attributes_s2 = dir(s2)
      print('__iter__' in attributes_s1)  # True
      print('__iter__' in attributes_s2)  # False
      
    3. iterate 的特点

      • 存储的数据可以直接显示,比较直观
      • 拥有方法比较多
      • 占用内存
      • 不能直接通过for循环,不能直接取值(索引,key除外),日常使用中for循环取值其实是依赖迭代器实现的
    4. 迭代器 iterator

      在python中,内部含有'_iter_'方法并且含有'__next__'方法的对象就是迭代器,现如今学习到的内容中,只有 file_handler 是迭代器。

      with open(r'file_handler.txt', encoding='utf-8', mode='w') as file_handler:
          print(('__iter__' and '__next__') in dir(file_handler))  # True
      
    5. 利用 iter() 将可迭代对象转化为迭代器

      s1 = 'dasd'
      obj = iter(s1)  # s1.__iter__() 是内置函数,两者都可生成迭代器
      # print(obj)  # <str_iterator object at 0x000001E9BA8B8828>
      print(next(obj))  # d 也可写作 print(obj.__next__())
      print(next(obj))  # a
      print(next(obj))  # s
      print(next(obj))  # d
      # print(next(obj))  # 警告: StopIteration
      
      # Exercise:
      l1 = [11, 22, 33, 44, 55, 66]
      obj = iter(l1)
      print(obj)  # <list_iterator object at 0x00000212C17286D8>
      print(next(obj))  # 11
      print(next(obj))  # 22
      print(next(obj))  # 33
      print(next(obj))  # 44
      print(next(obj))  # 55
      print(next(obj))  # 66
      
    6. iterator 的特点

      优点:

      • 节省内存
      • 惰性机制,next()一次只取一个值

      缺点:

      • 不能直观的查看里面的数据
      • 不走回头路,只能想下取值
    7. iterator 和 iterate 的对比

      • 可迭代对象 iterate:可迭代对象是一个操作方法比较多,比较直观,存储数据相对少的一个数据集。

        应用:当你侧重于数据可以灵活处理,并且内存空间足够,将数据集设置为可迭代对象是明确的选择。

      • 迭代器 iterator:可迭代器是一个非常节省内存,可以记录取值位置,可以通过循环+next方法取值,但是不直观,操作方法比较单一的数据集(一个迭代器一定是可迭代对象)。

        应用:当你的数据量过大,大到足以撑爆你的内存或者你以节省内存为首选因素时,将数据集设置为迭代器是一个不错的选择(可参考为什么Python把文件句柄设置为迭代器)

    8. while 模拟 for 循环

      list = [1, 2, 3, 4]
      # for i in list:
      #     pass
      iterator = iter(list)  # list.__iter__()
      while 1:
          try:
              i = next(iterator)  # iterator.__next__()
          except StopIteration:
              break
      
  • 相关阅读:
    Vue $nextTick的一个使用场景
    Vue 使用v-for对Object进行遍历
    JavaScript 回调函数的简单示例
    VSCode 自定义Vue snippets, 快速生成Vue模板
    git将一个分支完全覆盖另外一个分支如:dev分支代码完全覆盖某一个开发分支
    解决bootstrap时间输入框总被浏览器记住的记录遮挡住的问题
    Fiddler 屏蔽JS、抓WebSocket协议、查看接口响应时间、模拟并发请求
    细说MySQL的时间戳(Timestamp)类型
    网站建设之域名注册和域名备案
    日常项目测试用例检查点(来自一线测试人员的吐血总结)
  • 原文地址:https://www.cnblogs.com/raygor/p/13273055.html
Copyright © 2020-2023  润新知