Python迭代器

1,函数名的运用

1,函数的内存地址

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

def func():
    print(‘hh‘)

print(func)  #结果:<function func at 0x1101e4ea0>

通过以上的例子可以知道,函数名是指向这个函数的内存地址,与其说函数名()可以执行这个函数,不如说是函数的内存地址()才是执行这个函数的关键,比如

a = 1
b = 2
c = a + b
print(c)  #  3

a + b 并不是变量相加,而是两个变量指向的int对象的相加

2,函数名可以赋值给其它变量

def func():
    print(‘hh‘)

print(func)
a = func  # 把函数当成一个变量赋值给另外一个变量
a()  # 函数调用func()

通过变量的赋值,变量a,和变量func都指向的这个函数的内存地址,那么a()就当然可以执行这个函数

3,函数名可以当作容器类的元素

其实函数名就是一个变量,变量是可以当作容器类类型的元素:

a = 1
b = ‘alex‘
c = ‘sir‘
l1 = [a, b, c]

for i in l1:
    print(i)

# 结果:
1
alex
sir

那么函数名也可以是

def func1():
    print("in func1: aa")
def func2():
    print("in func2: bb")
def func3():
    print("in func3: cc")
def func4():
    print("in func4: dd")
lst = [func1, func2, func3, func4]
for i in lst:
    i()

4,函数名可以当作函数的参数

变量可以做的,函数名也可以做

def func1():
    print(‘in func1‘)

def func2(f):
    print(‘in func2‘)
    f()

func2(func1)

5,函数名可以当作函数的返回值

def func1():
    print(‘in func1‘)

def func2(f):
    print(‘in func2‘)
    return f

ret = func2(func1)
ret()  # ret, f, func1 都是指向的func1这个函数的内存地址

View Codex

小结:函数名是一个特殊的变量,他除了具有变量的功能,还有最主要的特点就是加上()就执行,其实还有一个学名是叫第一类对象

2,f-strings格式化输出

f-strings是python3.6的标准库的格式化输出新的写法,这个格式化比%s或者format效率高并且更加简化。

1,举个栗子

它的结构就是F(f)+str的形式,在字符串中想替换的位置用{}展位,与format类似,但是用在字符串后面写入替换的内容,二他可以直接识别

name = ‘xzc‘
age = 18
sex = ‘男‘
msg = F‘姓名:{name},性别:{age},年龄:{sex}‘  # 大写字母也可以
msg = f‘姓名:{name},性别:{age},年龄:{sex}‘  
print(msg)
‘‘‘
输出结果:
姓名:xzc,性别:18,年龄:男
‘‘‘

2,任意表达式

它可以加任意的表达式

print(f‘{3*21}‘)  # 63

name = ‘barry‘
print(f"全部大写:{name.upper()}")  # 全部大写:BARRY

# 字典也可以
teacher = {‘name‘: ‘xzc‘, ‘age‘: 18}
msg = f"The teacher is {teacher[‘name‘]}, aged {teacher[‘age‘]}"
print(msg)  # The comedian is xzc, aged 18

# 列表也行
l1 = [‘xzc‘, 18]
msg = f‘姓名:{l1[0]},年龄:{l1[1]}.‘
print(msg)  # 姓名:xzc,年龄:18.

3,插入表达式

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

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

4,多行f

name = ‘barry‘
age = 18
ajd = ‘handsome‘

# speaker = f‘‘‘Hi {name}.
# You are {age} years old.
# You are a {ajd} guy!‘‘‘

speaker = f‘Hi {name}.‘          f‘You are {age} years old.‘          f‘You are a {ajd} guy!‘
print(speaker)

5,其他

注意细节

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

3,迭代器

1,可迭代对象

1)可迭代对象定义

什么叫对象?在python中所有的一切都可以是对象;什么叫迭代?迭代就是一个重复的过程,但是不能单纯的重复,每一次迭代都是基于上一次的结果而来,就像游戏更新,这就叫迭代。

在python中现在学的有str  list  tuple  dic  set  range 文件句柄等都是可迭代对象,在python中但凡内部含有_iter_方法的对象,都是可迭代对象

2)查看对象内部的方法

查看对象内部的方法除了看源码意外还有通过dir()去判断一个对象具有什么样的方法

s1 = ‘alex‘
print(dir(s1))

dir()会返回一个列表,这个列表中含有该对象的以字符形式所有方法名这样就可以判断python中的一个对象是不是可迭代对象

s1 = ‘alex‘
i = 100
print(‘__iter__‘ in dir(i))  # False
print(‘__iter__‘ in dir(s1))  # True

3)小结:

从字面角度:可迭代对象是一个可以重复取值的实实在在的东西

从专业角度:但凡内部含有_iter_方法的对象,都是可迭代对象

可迭代对象可以通过判断该对象是否有‘_iter_‘方法来判断

可迭代对象的优点:

可以直观的查看里面的数据

可迭代对象的缺点:

1,占用内存

2,可迭代对象不能迭代取值(除去索引,key以外)

即使抛去索引,key以外,这些可迭代对象可以通过for循环进行取值,就是先将可迭代对象转化成迭代器,然后在进行取值

2,迭代器

1)迭代器的定义

从字面意思来说:迭代器,是一个可以迭代取值的工具

从专业角度来说:迭代器时这样的对象:实现了无参数_next_方法,返回序列中的下一个元素,如果没有元素,那么抛出Stoplteration异常,python中迭代器还实现了_iter_方法,因此迭代器也可以迭代

那么简单来说:在python中,内部含有_lter_方法并且含有_next_方法的对象就是迭代器

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

例:

o1 = ‘alex‘
o2 = [1, 2, 3]
o3 = (1, 2, 3)
o4 = {‘name‘: ‘太白‘,‘age‘: 18}
o5 = {1, 2, 3}
f = open(‘file‘,encoding=‘utf-8‘, mode=‘w‘)
print(‘__iter__‘ in dir(o1))  # True
print(‘__iter__‘ in dir(o2))  # True
print(‘__iter__‘ in dir(o3))  # True
print(‘__iter__‘ in dir(o4))  # True
print(‘__iter__‘ in dir(o5))  # True
print(‘__iter__‘ in dir(f))  # True
# hsagn
print(‘__next__‘ in dir(o1))  # False
print(‘__next__‘ in dir(o2))  # False
print(‘__next__‘ in dir(o3))  # False
print(‘__next__‘ in dir(o4))  # False
print(‘__next__‘ in dir(o5))  # False
print(‘__next__‘ in dir(f))  # True
f.close()

通过以上代码可以验证,以上对象中只有文件句柄时迭代器,剩下的数据类型都是可迭代对象

3)可迭代对象如何转化成迭代器

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

4)迭代器取值

可迭代对象时不可以一直迭代取值(出去索引,切片以及key),但是转化成迭代器就可以了,迭代器是使用_next_()方法进行取值

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

5)通过while模拟for的内部循环机制

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

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

6)小结:

从字面意思来说:迭代器是可迭代取值的工具

从专业角度来说:在python中,内部含有_iter_方法并且含有_next_方法的对象就是迭代器

迭代器的优点:

节省内存

迭代器在内存中相当于只占一个数据空间:因为每次取值都上一条数据会释放内存,加载当前的此条数据

惰性机制

next一次,取一次值,绝对不过多取值

有一个迭代器模式就i可以解释上面两条:迭代是数据处理的基石,扫描内存中放不下的数据集时,我们要找到一种惰性获取数据的方法,即按需一次取得一个数据,这就是迭代器的模式

迭代器的缺点:

不能直观的查看里面的数据

取值时不走回头路,只能一直向下取值

3,可迭代对象与迭代器的对比

可迭代对象

是一个私有方法比较多,操作比较灵活,比较直观,但是占用过多内存,而且不能直接通过循环迭代取值的一个数据集

应用

当侧重于对数据可以灵活处理,并且内存空间足够的情况下,将数据集设置为可迭代对象时明确的选择

迭代器

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

应用

当数据量过大,大到足以撑爆内存或者以节省内存为首选因素时,将数据集设置为迭代器是一个很好的选择

相关推荐