函数(四)

一、迭代器

  1.迭代:更新换代(重复)的过程,每次的迭代都必须基于上一次的结果

    迭代器:迭代取值的工具

    迭代器给你提供了一种不依赖于索引取值的方法

  2.重复+每次迭代都是基于上一次的结果而来的

l = [1,2,3,4]
a = 'hello'
n = 0
while n < len(a):
    print(a[n])
    n += 1

  3.需要迭代取值的数据类型:

    字符串、列表、元组、字典、集合

二、可迭代对象

   1.只有内置有__iter__方法的都叫做可迭代对象

  ps:针对双下划线开头双下划线结尾的方法,推荐读双下+方法名

  2.基本数据类型中是可迭代对象的有:

    str、list、tuple、dict、set

    文件对象(执行内置的__iter__之后还是本身,没有任何变化):文件对象本身就是迭代器对象

三、迭代器对象

  1.内置有__iter__方法

  2.内置有__next__方法

  ps:迭代器一定是可迭代对象,而可迭代对象不一定是迭代器对象

  3.例子:

    生成一个迭代器对象,将可迭代对象l转换成迭代器对象

l = [1,2,3,4]
iter_l = l.__iter__()

    迭代器取值,调用__next__,如果取完了,直接报错StopIteration

l = [1,2,3,4]
iter_l = l.__iter__()

print(iter_l.__next__())
print(iter_l.__next__())
print(iter_l.__next__())
print(iter_l.__next__())  # 如果取完了 直接报错

    迭代器对象无论执行多少次__iter__方法得到的还是迭代器对象本身

f1 = open('test','r',encoding='utf-8')
# 调用f1内置的__iter__方法
iter_f = f1.__iter__()
print(iter_f is f1)

    迭代器初始化

d = {'name':'jason','password':'123','hobby':'泡m'}
iter_d = d.__iter__()
print(d.__iter__().__next__())  # 迭代器初始化
print(d.__iter__().__next__())  # 迭代器初始化

    异常处理

d = {'name':'jason','password':'123','hobby':'泡m'}
iter_d = d.__iter__()
while True:
    try:
        print(iter_d.__next__())
    except StopIteration:
        break

  4.迭代器取值特点:只能往后依次取,不能往回取

    优点:

      (1)不依赖于索引取值

      (2)内存中永远只占一份空间,不会导致内存溢出

    缺点:

      (1)不能够获取指定的元素

      (2)取完之后会报StopIteration错

四、for循环内部原理

  1.将in后面的可迭代对象调用__iter__转换成迭代器对象

  2.调用__next__迭代取值

  3.内部有异常捕获Stopiteration,当__next__报这个错,自动结束循环

五、生成器

  1.生成器:用户自定义的迭代器,本质就是迭代器

  2.函数内如果有yield关键字,那么加括号执行函数的时候并不会触发函数体代码的运行

def func():
    print('first')
    yield  666
    print('second')
    yield  777

g = func()  # 生成器初始化:将函数变成迭代器
print(g)  # <generator object func at 0x000002BF65103678>
print(g.__next__())  # first 666
print(g.__next__())  # second 777

    yield后面跟的值就是调用迭代器__next__方法你能得到的值

    yield既可以返回一个值也可以返回多个值,并且多个值也是按照元组的形式返回

  3.取范围内的值:

    方法一:for循环

for i in range(1,10,2):
    print(i)

    方法二:函数

def my_range(start,end,step):
    while start < end:
        yield start
        start += step

for j in my_range(1,100,2):
    print(j)

  4.yield表达式形式(了解):

    yield支持外界为其传参

    当函数内有yield关键字的时候,调用该函数不会执行函数体代码,而是将函数变成生成器

def dog(name):
    print('%s 准备开吃'%name)
    while True:
        food = yield
        print('%s 吃了 %s'%(name,food))
g = dog('egon')
g.__next__()  # 必须先将代码运行至yield 才能够为其传值
g.send('饺子')  # 给yield左边的变量传参  触发了__next__方法

  yield作用:

    (1)帮你提供了一种自定义生成器方式

    (2)会帮你将函数的运行状态暂停住

    (3)可以返回值

  与return之间的异同点:

    相同点:都可以返回值,并且都可以返回多个

    不同点:

      yield可以返回多次值,而return只能返回一次函数立即结束

      yield还可以接受外部传入的值

  自定义range功能

 

def my_range(start,end,step=1):
    while start < end:
        yield start
        start += step

for i in my_range(1,10,2):
    print(i)

 

六、面试题

def add(n,i):
    return n+i
def test():
    for i in range(4):
        yield i
g=test()

for n in [1,10]:
    g=(add(n,i) for i in g)  # 10

print(n)
res=list(g)
#A. res=[10,11,12,13]
#B. res=[11,12,13,14]
#C. res=[20,21,22,23] 答案
#D. res=[21,22,23,24]

  第一次for循环g=(add(n,i) for i in test())

  第二次for循环g=(add(n,i) for i in (add(n,i) for i in test()))

  for i in (add(10,i) for i in test()):  会执行所有的生成器内部的代码

  add(n,1)

def multipliers():
    return [lambda x, i=i: i*x for i in range(4)]
    # 0, 1, 2, 3
    # [func(x): return 0*x, func(x): return 1*x,
    # func(x): return 2*x, func(x): return 3*x, ]

print([m(2) for m in multipliers()])  # [0, 2, 4, 6]

# [func(x): return 0*2, func(x): return 1*2,
# func(x): return 2*2, func(x): return 3*2, ]
# [0, 2, 4, 6]
# [6, 6, 6, 6]

def multipliers():
    list1 = []
    for i in range(4):
        def func(x):
            return x * i
        list1.append(func)
    return list1
print([m(2) for m in multipliers()])  # [6, 6, 6, 6]

# 闭包函数的延迟绑定
# 在内层函数执行时才会绑定变量i
def multipliers2():
    list1 = []
    for i in range(4):
        def func(x, i=i):
            return x * i
        list1.append(func)
    return list1
print([m(2) for m in multipliers2()])  # [0, 2, 4, 6]

  读取一个文件并返回每行数据的长度

with open('test1.txt', 'w', encoding='utf-8') as f:
    for line in range(1000):
        f.write(f'www{line}aaa' * (line + 1) + '\n')


# 列表推导式: 处理数据量大的文件会导致内存溢出.
res = [len(line) for line in open('test1.txt', 'r', encoding='utf-8')]
# print(res)


# 生成器表达式: 处理数据量大的文件推荐使用.
res2 = (len(line) for line in open('test1.txt', 'r', encoding='utf-8'))
print(res2)  # <generator object <genexpr> at 0x000002B3748FD0A0>
print(next(res2))  # 8
print(next(res2))  * 15

 

def demo():
    for i in range(4):
        yield i

# <gen..>1 (0, 1, 2, 3)

g = demo()

g1 = (i for i in g)  # <gen..>2 (0, 1, 2, 3)
g2 = (i for i in list(g1)) # []

print(list(g))  # []
print(list(g1))  # []
print(list(g2))  # [0, 1, 2, 3]

'''值

# g,g1,g2里面的值都是指向同一个内存地址.

真实结果:
    [0, 1, 2, 3]
    []
'''

七、生成器表达式

  生成器不会主动执行任何一行代码,必须通过__next__触发代码的运行

  生成器表达式

res = (i for i in range(1,100000000) if i != 4)  # 生成器表达式
print(res)

  统计文件中内容的长度

  方法一:for循环

with open('test','r',encoding='utf-8') as f:
    n = 0
    for line in f:
        n += len(line)
    print(n)

  方法二:函数

with open('test','r',encoding='utf-8') as f:
    g = (len(line) for line in f)
    print(sum(g))

八、内置函数

  1.abs():求绝对值

print(abs(-11.11))  # 11.11

  2.all():只要有一个为False就返回False

l = [0,1,2]
print(all(l))  # False 因为0为False

  3.any():只要有一个为True就返回True

l = [0,1,2]
print(any(l))  # True

  4.globals():无论在哪,查看的都是全局名称空间

  5.locals():当前语句在哪个位置,就会返回哪个位置所存储的所有的变量值

  6.bin():十进制转二进制

  7.oct():十进制转八进制

  8.hex():十进制转十六进制

  9.int():二进制转其他进制,将一个字符串或数值转换为一个普通整数

  10.bool():测试一个对象是True还是False

  11.encode():编码

s = 'hello'
print(s.encode('utf-8'))  # b'hello
print(bytes(s,encoding='utf-8'))  # b'hello

  12.callable():可调用的(可以加括号执行相应功能的)

l = [1,2,3]
def index():
    pass
print(callable(l))  # False
print(callable(index))  # True

  13.chr():将数字转换成ascii码表对应的字符

  14.ord():将字符按照ascii码表转成对应的数字

  15.dir():获取当前对象名称空间里面的名字

  16.divmod:分别取商和余数,分页器

print(divmod(101,10))  # (10,1)
total_num,more = divmod(900,11)
if more:
    total_num += 1
print('总页数:',total_num)  # 总页数:82

  17.enumerate():枚举

l = ['a','b']
for i,j in enumerate(l,1):
    print(i,j)

  18.eval():不支持逻辑代码,只支持一些简单的python代码

  19.exec():执行字符串或complie方法编译过的字符串,没有返回值,可执行多行

 

  20.format:(1){}占位(2){index}索引(3){name}指名道姓

  21.help():返回对象的帮助文档

  22.isinstance:后面统一该方法判断对象是否属于某个数据类型

n = 1
print(type(n))  # <class 'int'>
print(isinstance(n,list))  # False

  23.pow():幂函数

print(pow(2,3))  # 8

  24.round():四舍五入

print(round(3.4))  # 3

九、面向过程编程

  1.面向过程编程就类似于设计一条流水线

    (1)好处:

      将复杂的问题流程化,从而简单化

    (2)坏处:

      可扩展性较差,一旦需要修改,整体都会受到影响

  2.例子

# 注册功能
# 1.获取用户输入
def get_info():
    while True:
        username = input(">>>:").strip()
        if not username.isalpha():  # 判断字符串不能包含数字
            print('不能包含数字')
            continue
        password = input('>>>:').strip()
        confirm_password = input("confirm>>>:").strip()
        if password == confirm_password:
            d = {
                '1':'user',
                '2':'admin'
            }
            while True:
                print("""
                    1 普通用户
                    2 管理员
                """)
                choice = input('please choice user type to register>>>:').strip()
                if choice not in d:continue
                user_type = d.get(choice)
                operate_data(username,password,user_type)
                break
        else:
            print('两次密码不一致')

# 2.处理用户信息
def operate_data(username,password,user_type):
    # jason|123
    res = '%s|%s|%s\n'%(username,password,user_type)
    save_data(res,'userinfo.txt')

# 3.存储到文件中
def save_data(res,file_name):
    with open(file_name,'a',encoding='utf-8') as f:
        f.write(res)

def register():
    get_info()

register()
posted @ 2019-07-15 19:21  静心学  阅读(132)  评论(0)    收藏  举报