zoukankan      html  css  js  c++  java
  • python基础 day11 默认参数和局部作用域的坑、global和nonlocal方法、函数名的应用、格式化输出的另一种方式、可迭代对象和迭代器

    一、默认参数的陷阱

    • 陷阱只针对于默认参数时可变的数据类型
    def func(name, list1=[]):
        list1.append(name)
        return list1
    
    ret1 = func('jason')
    print(ret1, id(ret1))  # ['jason'] 2246045611720
    ret2 = func('carly')
    print(ret2, id(ret2))  # ['jason', 'carly'] 2246045611720
    

    由结果可知,如果默认参数是一个可变的数据类型,无论调用多少次这个默认函数,这个默认参数在内存中地址不变的。

    练习1

    def func(a, list1=[]):
        list1.append(a)
        return list1
    
    print(func(10))  # [10]
    print(func(20, []))  # [20]  # 没有调用默认参数
    print(func(30))  # [10, 100]  # 再一次调用默认参数,而之前调用默认参数之后,list1 = [10]
    

    练习2

    def func(a, list1=[]):
        list1.append(a)
        return list1
    ret1 = func(10)
    ret2 = func(20, [])
    ret3 = func(30)
    print(ret1)  # [10, 30]
    print(ret2)  # [20]
    print(ret3)  # [10, 30]
    print(id(ret1) == id(ret3))  # True # ret1 和ret3 共用一个内存地址
    

    二、局部作用域的坑

    在函数中,如果定义了一个变量,但是在定义这个变量之前对其引用,python解释器会认为这是语法问题

    比如:

    count = 1
    def func():
        print(count)
        count = 2
    func()
    # 程序报错
    # UnboundLocalError: local variable 'count' referenced before assignment
    

    三、global

    1.可以在局部声明一个全局变量

    def func():
        global name
        name = 'jason'
    func()
    print(name)
    print(globals())
    

    2.可以在局部修改一个全局变量

    count = 1
    def func():
        global count
        count += 1
    func()
    print(count)
    

    四、nonlocal

    1.不能操作全局变量

    count = 1
    def func():
        nonlocal count
    func()
    

    2.局部作用域:内层函数对外层函数的局部变量进行修改

    def func1():
        count = 1
        def func2():
            nonlocal count
            count += 1
        func2()
        print(count)
    func1()
    

    五、函数名的应用

    1.函数名+()就能运行此函数

    def func():
        print(123)
    func()
    print(func, type(func))
    

    2.函数名就是一个变量

    def func():
        print(123)
    f = func
    f()  # 123
    
    def func1():
        print('this is func1')
    def func2():
        print('this is func2')
    func2 = func1
    func2()  # this is func1
    

    3.函数名可以作为容器类数据类型的元素

    def func1():
        print('this is func1')
    def func2():
        print('this is func2')
    def func3():
        print('this is func3')
    li = [func1, func2, func3]
    for i in li:
        i()
    

    4.函数名可以作为函数的参数

    def func1(a):
        a()
        print('this is func1', end='')
    def func2():
        print('this is func2', end='
    ')
    func1(func2)  # this is func2 this is func1
    

    5.函数名可以作为函数的返回值

    def func1():
        print('this is func1')
    def func2(a):
        print('this is func2')
        return a
    ret = func2(func1)
    ret()
    

    六、格式化输出

    之前已经学习过的格式化输入%s formate

    name = 'jason'
    age = 24
    msg1 = '我叫%s, 今年%s' % (name, age)
    mgs2 = '我叫{}, 今年{}'.
    

    新特性

    name= 'jason'
    age = 24
    msg = f'我叫{name}, 今年{age}'
    

    可以加表达式

    dic = {'name': 'jason', 'age': 24}
    msg = f"我叫{dic.get('name')}, 今年{dic['age']}"
    print(msg)
    
    count = 2
    print(f'>>>{count**3}')
    
    name = 'jason'
    print(f'我的名字是{name.upper()}')
    

    结合函数写

    def _sum(a, b):
        return a + b
    print(f'结果为{_sum(2, 4)}')
    

    七、迭代器

    • 可迭代对象
      对象:python中一切皆对象。
      可迭代:更新迭代。重复的,循环的一个过程。
      可迭代对象:内部含有'__iter__'方法的对象
    s = 'sdfsdf'
    print(dir(s))
    print('__iter__' in dir(s))
    
    • 迭代器

      可更新迭代的工具
      内部含有'__iter__'方法,并且含有'__next__'方法的对象就是迭代器

      with open('test.txt', 'w', encoding='utf-8') as f1:
          print('__iter__' in dir(f1) and '__next__' in dir(f1))  # True
      
    • 可迭代对象可以转化成迭代器

    s = 'abc'
    obj = iter(s)  # 或者s.__iter__()
    print(obj)
    
    print(next(obj))  # a  # 或者s1.__next__()
    print(next(obj))  # b
    print(next(obj))  # c
    
    • 迭代器的优缺点

      1.节省内存

      2.惰性机制,next一次,只取一个值

      3.速度慢

      4.迭代器永远记住上此取值的位置

    • 可迭代对象和迭代器的对比

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

      • 当侧重与对数据的灵活处理,并且内存空间足够,可将数据集设置为可迭代对象

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

      • 当数据量过大,内存不够处理这么多数据量,或者以节省内存为首选因素时,应将数据集设置为迭代器

    • while 循环模拟for 循环机制

    li = [1, 2, 3, 4, 5, 6, 7, 8, 9]
    obj = iter(li)
    while 1:
        try:
            print(next(obj))
        except StopIteration:
            break
    
  • 相关阅读:
    CSS定位
    使用开源框架进行get,post提交
    使用httpclient框架分别用post,get方式提交
    C++ const_cast
    C++ 类继承 常量对象调用函数
    C++ 类继承 子类调用父类
    C++ explicit关键字
    C++ class入门
    C#检测耗时操作
    面向对象编程入门
  • 原文地址:https://www.cnblogs.com/west-yang/p/12596167.html
Copyright © 2011-2022 走看看