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
原文地址:https://www.cnblogs.com/west-yang/p/12596167.html