2.2-函数名使用,格式化输出,迭代器


函数名的运用,新版格式化输出,迭代器

函数名的作用

函数名的定义和变量的定义几乎一致,在变量的角度,函数名就是一个变量,具有变量的功能;可以赋值;但是作为函数名加上()就会执行对应的函数,所以函数是一个特殊的变量;

函数的内存地址

函数名指向的其实是函数的内存地址;

def func():
    print('hello')
print(func)
# <function func at 0x00000284733F1E18>

函数名可以赋值给其他变量

def func():
    print('hello')
print(func)
# # <function func at 0x00000284733F1E18>
a = func        # 把函数当成一个变量赋值给另一个变量
a()     # 函数调用func()
# hello
# 通过变量的赋值,变量a和变量func都指向这个函数的内存地址,所以a()也可以执行这个函数;

函数名当做容器类的元素

a = 1
b = 'heisei'
c = '利穆'
l = [a, b, c]
for i in l:
    print(i)
# 1
# heisei
# 利穆


def func1():
    print('in func1: haha')
def func2():
    print('in func2: hehe')
def func3():
    print('in func3: lala')
def func4():
    print('in func4: didi')
lst = [func1, func2, func3, func4]
for i in lst:
    i()
# in func1: haha
# in func2: hehe
# in func3: lala
# in func4: didi

函数名当做函数的参数

def func1():
    print('in func1')
def func2(f):
    print('in func2')
    f()
func2(func1)
# in func2
# in func1

函数名作为函数的返回值

def func1():
    print('in func1')
def func2(f):
    print('in func2')
    return f
ret = func2(func1)
ret()       # ret, f, func1 都是指向func1这个函数的内存地址
# in func2
# in func1

f-strings格式化输出

f-strings是python3.6开始加入标准库的格式化输出新写法,比%s更加高效且简化;

结构:F(f)+ str的形式,在字符串中想替换的位置用{}占位,与format类似;

# 简单举例
name = '黑色利穆'
age = 25
sex = '男'
msg = f'姓名:{name}, 性别:{sex}, 年龄:{age}'
print(msg)
msg = F'姓名:{name}, 性别:{sex}, 年龄:{age}'
print(msg)
# 姓名:黑色利穆, 性别:男, 年龄:25


# 任意表达式
print(f'{3 * 4}')       # 12

name = 'heiselimu'
print(f'大写:{name.upper()}')     # 大写:HEISELIMU

# 字典
ops = {'name': '黑色利穆', 'age': 25}
msg = f"the people is {ops['name']}, age {ops['age']}"
print(msg)      # the people is 黑色利穆, age 25

# 列表
l1 = ['黑色利穆', 25]
msg = f'姓名: {l1[0]}, 年龄: {l1[1]}'
print(msg)          # 姓名: 黑色利穆, 年龄: 25

插入表达式

可以用函数完成相应的功能,然后将返回值返回到字符串相应的位置:

def sum_a_b(a, b):
    return a + b
a = 1
b = 2
print('求和的结果为:' + f'{sum_a_b(a, b)}')
# 求和的结果为:3

多行f

name = '黑色利穆'
age = 25
job = 'OPS'
say = f'Hi {name}.'\
    f'you are {age} years old.'\
    f'you job is {job}.'
print(say)
# Hi 黑色利穆.you are 25 years old.you job is OPS.

其他细节

print(f"{{73}}")  # {73}
print(f"{{{73}}}")  # {73}
print(f"{{{{73}}}}")  # {{73}}
# ! , : { } ;这些标点不能出现在{} 这里面。
# print(f'{;12}')  # 报错
# 所以使用lambda 表达式会出现一些问题。
# 解决方式:可将lambda嵌套在圆括号里面解决此问题。
x = 5
print(f'{(lambda x: x*2) (x)}')  # 10

迭代器

可迭代对象

可迭代对象定义:

​ 可迭代对象:str,list,tuple,dict,set,range,文件句柄等;

​ python中,只要内部含有iter方法的对象,都是可迭代对象;

name = '黑色利穆'
print('__iter__' in dir(name))      # True
a = 100
print('__iter__' in dir(a))         # False

总结:

  1. 可迭代对象就是一个可以重复取值的东西;
  2. 内部含有iter方法的对象,都是可迭代对象;
  3. 优点:可以直观的看到里面的数据;
  4. 缺点:占用内存,可迭代对象不能迭代取值(除去索引,key以外);

迭代器

迭代器定义:

迭代器就是可以迭代取值的工具;

实现了无参数的next方法,返回序列中的下一个元素,如果没有元素,就抛出StopIteration异常,python中的迭代器也实现了iter方法,因此迭代器也可以迭代。

在python中,内部含有iter方法并且含有next方法的对象就是迭代器;

如何判断该对象是否是迭代器:

a1 = 'heiselimu'
a2 = [1, 2, 3]
a3 = (1, 2, 3)
a4 = {'name': 'heiselimu', 'age': 25}
a5 = {1, 2, 3}
f = open('b.txt', encoding='utf-8', mode='w')

# 判断是否是可迭代对象
print('__iter__' in dir(a1))        # True
print('__iter__' in dir(a2))        # True
print('__iter__' in dir(a3))        # True
print('__iter__' in dir(a4))        # True
print('__iter__' in dir(a5))        # True
print('__iter__' in dir(f))        # True

# 判断是否是迭代器
print('__next__' in dir(a1))        # False
print('__next__' in dir(a2))        # False
print('__next__' in dir(a3))        # False
print('__next__' in dir(a4))        # False
print('__next__' in dir(a5))        # False
print('__next__' in dir(f))        # True
f.close()
# 综上所述,只有文件句柄是迭代器,剩下的数据类型都是可迭代对象

可迭代对象如何转化成迭代器:

l1 = [1, 2, 3, 4, 5, 6]
obj = l1.__iter__()     # 或者 iter(l1)
print(obj)      # <list_iterator object at 0x000001A9761672E8>

迭代器取值:

可迭代对象是不可以一直迭代取值的(除去索引,切片以及key),但是转化成迭代器就可以了。迭代器就是利用next进行取值;

l1 = [1, 2, 3]
obj = l1.__iter__()     # iter(l1)
print(obj)      # <list_iterator object at 0x00000250EE6D72E8>
ret = obj.__next__()
print(ret)      # 1
ret = obj.__next__()
print(ret)      # 2
ret = obj.__next__()
print(ret)      # 3
ret = obj.__next__()
print(ret)      # StopIteration
# 迭代器就是利用next取值,一个next取值对应一个值,如果迭代器里的值用完了,还要next。
# 那么就报StopIteration错误;

while模拟for的内部循环机制:

for循环的循环对象一定要是可迭代对象,但是并不意味着可迭代对象就可以取值,因为for循环的内部机制是:将可迭代对象转成迭代器,然后利用next进行取值,最后利用异常处理处理StopIteration抛出的异常;

l1 = [1, 2, 3, 4, 5, 6, 7]
# 将l1可迭代对象转化成迭代器
obj = iter(l1)
# 利用while循环,next进行取值
while 1:
    # 利用异常处理终止循环
    try:
        print(next(obj))
    except StopIteration:
        break

总结:

  1. 字面意思:迭代器就是可迭代取值的工具;
  2. 专业角度:内部含有iter方法并且含有next方法的对象就是迭代器;
    1. 迭代器的优点:
      1. 节省内存;迭代器在内存中相当于只占用一个数据的空间:因为每次取值上一条数据会在内存释放,加载当前的此条数据;
      2. 惰性机制;next一次,取一个值,绝不过多取值;
    2. 迭代器的缺点:
      1. 不能直观的查看里面的数据;
      2. 取值时不走回头路,只能一直向下取值;

迭代器模式:迭代是数据处理的基石。扫描内存中放不下的数据集时,要找到一种惰性获取数据项的方式,即按需一次获取一个数据项。这就是迭代器模式;

l1 = [1, 2, 3, 4, 5, 6]
obj = iter(l1)

for i in range(2):
    print(next(obj))

for i in range(2):
    print(next(obj)))

可迭代对象与迭代器对比

可迭代对象:

  1. 是一个私有的方法比较多,操作灵活(列表,字典的增删改查,字符串的常用操作方法),比较直观,但是占用内存,不能直接通过循环迭代取值的一个数据集;
  2. 应用:当侧重于对于数据的灵活处理,并且内存空间足够,将数据集设置为可迭代对象是明确的选择;

迭代器:

  1. 是一个非常节省内存,可以记录取值位置,可以直接通过循环+next方法取值,但是不直观,操作方法比较单一的数据集;
  2. 应用:当数据量过大,大到足以撑爆内存或者以节约内存为首选因素时,将数据集设置为迭代器是一个不错的选择;
posted @ 2020-12-03 18:48  黑色利穆  阅读(101)  评论(0编辑  收藏  举报