Python函数的陷阱 函数名的运用 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.局部作用域的陷阱

'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:778463939
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
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()  # 太白金星

功能二:对已经声明的全局变量进行修改

'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:778463939
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
# 对已经声明的全局变量进行修改
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.函数名可以赋值给其他变量

'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:778463939
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
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.函数名可以作为函数的返回值

'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:778463939
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
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.结合函数

'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:778463939
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
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

利用 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
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值