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
    
  • 相关阅读:
    pat 甲级 1065. A+B and C (64bit) (20)
    pat 甲级 1064. Complete Binary Search Tree (30)
    pat 甲级 1010. Radix (25)
    pat 甲级 1009. Product of Polynomials (25)
    pat 甲级 1056. Mice and Rice (25)
    pat 甲级 1078. Hashing (25)
    pat 甲级 1080. Graduate Admission (30)
    pat 甲级 团体天梯 L3-004. 肿瘤诊断
    pat 甲级 1099. Build A Binary Search Tree (30)
    Codeforce 672B. Different is Good
  • 原文地址:https://www.cnblogs.com/west-yang/p/12596167.html
Copyright © 2011-2022 走看看