第六章 Python装饰器、迭代器、生成器

 

第1章 函数对象

一 函数是第一类对象,即函数可以当作数据传递
#1 可以被引用
#2 可以当作参数传递
#3 返回值可以是函数
#3 可以当作容器类型的元素

 

def select(sql):
    print('执行select:',sql)

def insert(sql):
    print('执行insert: ',sql)

def update(sql):
    print('执行update',sql)

def delete(sql):
    print('执行delete',sql)

cmd_dict={
    'select':select,
    'insert':insert,
    'update':update,
    'delete':delete
}

def main():
    while True:
        sql=input('>>>: ').strip()
        if not sql:continue
       
cmd_info=sql.split()      ### 截取sql
        cmd=cmd_info[0]           ### 获得sql语句中索引0的内容即select、insert、delete、update
        if cmd in cmd_dict:
            cmd_dict[cmd](cmd_info)    ### 判断匹配cmd的值存在字典中的key 那么就可以执行调用,并且对应一个value方法
        else:                         ### 随着方法功能的增多,这段逻辑不需要改动
            print('命令不存在')
main()

 

 

1.1 优雅的取代多分支if...else

 

def boo(str):
    print('执行boo',str)

def main():
    dict={
        'foo':foo,
        'boo':boo
    }
    while True:
        cmd=input('cmd>>>: ').strip()
        if not cmd:continue
        if
cmd in dict:
            dict[cmd](cmd)
main()

 

第2章 嵌套函数

### 函数的嵌套调用:在调用一个函数的过程中,又调用了其他函数
### 执行顺序是: 先执行 foo里的 print('from foo') 然后在函数中调用了bar函数,执行bar的 int('from bar')

def bar():
    print('from bar')

def foo():
    print('from foo')
    bar()

foo()

### 调用自己就是递归

 

### 嵌套的用法实例 求四个值的最大值
### 求两个值的最大值
def max2(x,y):
    if x > y:
        return x
    else:
        return y

### 求四个值的最大值,就可以调用2个最大值的方法
### 分解操作,先求两个 再往后走
def max4(a,b,c,d):
    res1=max2(a,b)
    res2=max2(res1,c)
    res3=max2(res2,d)
    return res3             ### 最后返回最终结果

print(max4(1,2,3,-1))

 

### 函数的嵌套定义:在一个函数的内部,又定义了另外一个函数
### 为什么外部无法直接找到f2函数? 因为外部只有在调用f1的时候f2才生效,这涉及到 名称空间 知识点
def f1():
    x=1                        ### 定义一个变量,属于f1函数,只在函数的时候生效
    def f2():                  ### 在函数的内部定义了一个f2函数,把他看成一个变量 加括号可以调用~
        print('from f2')
    print(x)
    f2()                        ### 调用时才有效 先找到f2,然后加括号运行
f1()

#print(x)  ### 无法打印到这个x 因为x在函数中定义的,调用函数结束后就失效了

 

 

第3章 名称空间

### 名称空间:存放名字的地方,
### 准确的说,名称空间是存放名字与变量值绑定关系的地方

# 名称空间
# - 分三种
# 内置名称空间:python解释器启动则生效
# 全局名称空间:执行python文件时生效
# 局部名称空间:调用函数时,临时生效,函调用结束则失效

# - 加载顺序:先内置,再全局,最后有可能产生局部
# - 查找名字的顺序:先局部,再全局,最后内置

 

 

# 强调:作用关系在函数定义阶段就已经固定,与调用位置无关

x=0
def f1():
    x=1
    def f2():
        x=2
        def f3():
            x=3
            print(x)
        f3()
    f2()
f1()

 

 

 

第4章 作用域

### 作用域:作用的范围
# 1、全局作用域:全局存活,全局有效

max=111
def f1():
    def f2():
        def f3():
            def f4():
                print(max)
            f4()
        f3()
    f2()
f1()

                                                    

# 2、局部作用域:临时存活,局部有效,只能在函数内访问

max=111
def f1():
    def f2():
        def f3():
            def f4():
                max=444
                print(max)
            f4()
        f3()
    f2()
f1()

 

 

4.1 查看局部作用域名字 locals

def f1():
    x=1
    y=2
    def f2():pass
   
print(locals())
f1()

 

{'f2': <function f1.<locals>.f2 at 0x000000A3D14698C8>, 'y': 2, 'x': 1}

 

4.2 查看全局作用域的名字 globals

z=1
def f1():
    x=1
    y=2
    def f2():pass
    #
print(locals())
    print(globals())
f1()

 

...'z': 1, 'f1': <function f1 at 0x0000008567283E18>

 

 

### 全局的局部 依然是全局

print(locals() is globals())

True

 

4.3 内置名称空间在作用域

'__builtins__': <module 'builtins' (built-in)>,

print(globals()['__builtins__'])

<module 'builtins' (built-in)>                  ### 模块

 

### 查看模块下的内置方法 dir
print(dir(globals()['__builtins__']))

 

['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FileExistsError', 'FileNotFoundError', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError', 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'ModuleNotFoundError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError', 'RecursionError', 'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning', 'StopAsyncIteration', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'WindowsError', 'ZeroDivisionError', '__build_class__', '__debug__', '__doc__', '__import__', '__loader__', '__name__', '__package__', '__spec__', 'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type',

'vars', 'zip']

 

4.4 关键字 golbal nonlocal

 

x=1
def f1():
    global ### 使用全局变量 尽量避免局部修改全局的变量名
   
x=2

f1()
print(x)

 

>>> 2

 

l=[]
def f2():
    l.append('f2')          ### 因为列表是可变类型,所以直接修改了全局的l列表

f2()
print(l)

### 针对全局的不可变类型 修改的话要加 golbal ,针对可变类型直接修改即可

 

### 修改局部

x=0
def f1():
    x=1
    def f2():
        x=2
        def f3():
            global x
            x=3

        f3()
    f2()
f1()

print(x)

 

 

x=0
def f1():
    x=1
    def f2():
        x=2
        def f3():
            global x
            x=3
        print(x)

        f3()
    f2()
f1()

 

>>> 2

 

### 跳出当前这一层函数 修改上一层函数的变量nonlocal 不能修改全局的

x=0
def f1():
    x=1
    def f2():
        # x=2
       
def f3():
            # global x
           
nonlocal x
            x=3
        # print(x)
       
f3()
    f2()
    print(x)
f1()

4.5 优先掌握: 作用域关系在函数定义时就已经固定

 

# 优先掌握:作用域关系 在函数定义时 就已经固定
# 与调用位置无关

### 打破了层级 原本f2只能在f1下使用,但是这样 可以放到外层使用了
x=1
def f1():
    def f2():
        print(x)
    return f2           ### 这个函数被返回出来 打破了层级

func=f1()
# print(func)
x=1000
func()                  ### func执行的就是f2 在函数里没有x,所以这里引用了执行全局中前最新的1000

 

>>> 1000

 

### 回到定义阶段找关系

x=1
def f1():
    def f2():
        print(x)
    return f2           ### 注意 这里返回的是f2 返回的不是结果而是 f2这个函数本身

def foo(func):
    x=3000
    func()              ### f2

foo(f1())               ### 在这里执行f1 实际上是 调用了 上面的f2 那么只运行f2 中的x找不到 找到全局的x=1 所以打印1

 

第5章 闭包

### 加载顺序:先内置,再全局,最后有可能产生局部
### 查找名字的顺序:先局部,再全局,最后内置
### 作用关系在函数定义阶段就已经固定,与调用位置无关

### 闭包函数:
# 1、定义在函数内部的函数,
# 2、包含对外部作用域名字的引用,而不是对全局作用域名字的引用 那么该内部函数就成为 闭包函数
x=1
def f1():
    x=111               ### 如果存在 优先访问
    def f2():           ### 内部函数 函数对象的概念 把函数当做返回值返回 打破层级限制
        print(x)
    return f2

func=f1()
func()

 

 

### 原始的传参形式
def wrapper(x):
    print(x)

wrapper(123)

 

### 使用闭包,今后调用都包裹着x=123 和 prinx(x)这些内容

### 闭包形式 给一个函数捆绑一个值

def deco():
    x=123
    def wrapper():
        print(x)
    return wrapper
func=deco()
func()

 

 

5.1 闭包函数的应用

### 每次执行都需要手动输入函数,比较麻烦,可以使用闭包 就不用每次都传值
import requests #pip3 install requests

# def get(url):
#     return requests.get(url).text
# print(get('https://www.python.org'))

 

### 写成一个专门爬取python的函数方法,定义好直接调用
def index():
    url='https://www.python.org'    ### 被包含的捆绑参数
    def get():              ### 闭包函数
        return requests.get(url).text
    return get
python_web=index()
python_web()                ### 以后就可以随意调用,延迟(惰性)计算

 

### 上面的闭包函数的url其实是写死了 其实也可以传值 写活
def index(url):
    # url='https://www.python.org'    ### 被包含的捆绑参数
    def get():              ### 闭包函数
        return requests.get(url).text          #print(requests.get(url).text)
    return get
python_web=index('https://www.python.org') ### 传值
baidu_web=index('https://www.baidu.com') ### 传值

python_web()
baidu_web()

 

第6章 装饰器

### 1、开放封闭原则:对扩展是开放的,对修改是封闭的
### 2、装饰器:装饰他人的工具,装饰器的目的是为其他人添加新功能
### 3、装饰器本身是任意可调用对象,被装饰的对象本身也可以是任意可调用对象

### 装饰器遵循的原则:
# 1、不修改被装饰对象的源代码
# 2、不修改被装饰对象的调用方式

### 装饰器的目的:
# 1、在遵循1和2原则的前提下,为其他新功能函数添加新功能

 

 

6.1 模拟打开网页 加装饰器

 

### 源码就是模拟访问一个页面

import time
def index():
    time.sleep(3)
    print('welcome to index')
index()

 

 

### 现在要加上一个统计打开时间的方法 这样就修改了源码

import time
def index():
    start=time.time()
    time.sleep(3)
    print('welcome to index')
    stop=time.time()
    print('run time is %s' %(stop-start))
index()

 

 

### 如果在写一个统计时间的函数  就修改了调用方法

import time
def index():
    time.sleep(3)
    print('welcome to index')

def wrapper(func):
    start=time.time()
    func()
    stop=time.time()
    print('run time is %s' %(stop-start))

wrapper(index)

 

 

import time
def index():
    time.sleep(3)
    print('welcome to index')

def home():
    time.sleep(3)
    print('welcome to home')

def timmer(func):
    # func=index
   
def wrapper():
        start=time.time()
        func()
        stop=time.time()
        print('run time is %s' %(stop-start))
    return wrapper

index=timmer(index)
home=timmer(home)

index()
home()

 

6.2 简洁的实现装饰器 @装饰器名

### @装饰器名,必须写在被装饰对象的正上方,并且是单独一行
import time
def timmer(func):
    # func=index
    def wrapper():
        start=time.time()
        func()
        stop=time.time()
        print('run time is %s' %(stop-start))
    return wrapper

### 把@timmer正下方函数名 当做参数传给timmer函数,把返回值赋值给这个函数
@timmer # index=timmer(index)
def index():
    time.sleep(3)
    print('welcome to index')

@timmer # home=timmer(home)
def home():
    time.sleep(3)
    print('welcome to home')

index()
home()

 

 

 

 

6.3 有参装饰器

### 有参函数装饰器
import time
def timmer(func):
    # func=index
    def wrapper(*args,**kwargs):          ### 没有要求传参,但是下面调用的时候要求传参,如果这里加上name 传给func(home)
                                            ### 但是index又不要求你有参数,如何适应各种形式传参,*args,**kwargs 接收任意长度格式的参数
        start=time.time()
        func(*args,**kwargs)                ### 怎么收到 怎么给func
        stop=time.time()
        print('run time is %s' %(stop-start))
    return wrapper

@timmer # index=timmer(index)
def index():
    time.sleep(3)
    print('welcome to index')

@timmer # home=timmer(home)
def home(name):
    time.sleep(3)
    print('welcome to home %s' %name)

index()
home('leo') # 其实就是wrapper('name')

 

 

 

6.4 返回值装饰器

### 返回值
### 要在原始方法里增加返回值,然后在闭包调用时候使用
import time
def timmer(func):
    # func=index            ### 这样就写死了
    def wrapper(*args,**kwargs):
        start=time.time()
        res=func(*args,**kwargs)            ### 针对这个函数有返回值 保存给res 然后在执行完成后返回 原始方法里返回什么在这里得到什么
        stop=time.time()
        print('run time is %s' %(stop-start))
        return res
    return wrapper

@timmer # index=timmer(index)
def index():
    time.sleep(3)
    print('welcome to index')
    return 123      ### 在index中设置一个返回值

@timmer # home=timmer(home)
def home(name):
    time.sleep(3)
    print('welcome to home %s' %name)
    return 456

res=index()            ### 调用的是wrapper 并不是最原始的 所以要在wrapper里增加返回值
print(res)            ### 如果不在wrapper增加 那么这里输出返回值是None

res1=home('leo') # 其实就是wrapper('name')
print(res1)

 

 

6.5 实现认证功能装饰器

# ### 实现认证功能装饰器
# ### 判断用户名、密码 并且实现与文件中的用户名密码校验 {"leo":"123","lex":"456","rubin":"789"}

current_user={'user':None}      ### 记录登录状态

def auth(func):
    def wrapper(*args,**kwargs):
        if current_user['user']:             ### 下次判断user有没有值 有值直接进入页面
            return func(*args,**kwargs)
        name=input('Please input your name: ').strip()
        password=input('Please input your password: ').strip()
        with open('user.txt','r',encoding='utf-8') as  f:
            dic=eval(f.read())
            # print(dic,type(dic))
        if name in dic and password == dic[name]:
            res=func(*args,**kwargs)
            current_user['user']=name              ### 保存登录状态,保存用户名
            return res
        else:
            print('name or password error')

    return wrapper

@auth #index=auth(index)
def index():
    print('from index')

@auth
def home(name):
    print('welcome %s' %name)


index()
home('leo')

 

6.6 有参装饰器

### 有参装饰器版本 得有多种验证方式,比如sql、文件等

current_user={'user':None}
### 考虑 怎么把auth_type 传进去 可以再加一层闭包,使用到3层即可

def auth(auth_type='file'):             ### 默认参数 不传值走file验证
    def deco(func):
        def wrapper(*args,**kwargs):
            if auth_type =='file':            ### 如果验证类型是文件
                if current_user['user']:
                    return func(*args,**kwargs)
                name=input('Please input your name: ').strip()
                password=input('Please input your password: ').strip()
                with open('user.txt','r',encoding='utf-8') as  f:
                    dic=eval(f.read())
                    # print(dic,type(dic))
                if name in dic and password == dic[name]:
                    res=func(*args,**kwargs)
                    current_user['user']=name
                    return res
                else:
                    print('name or password error')
            elif auth_type == 'mysql':
                print('mysql')
            elif auth_type == 'ldap':
                print('ldap')
            else:
                print('not vlaid auth_type')
        return wrapper
    return deco

@auth(auth_type='mysql') #index=deco(index)
def index():
    print('from index')

@auth(auth_type='file')
def hoem(name):
    print('welcome %s' %name)

index()
hoem('leo')

 

6.7 装饰器补充

6.7.1 补充注释

import time
from functools import  wraps                ### 在装饰器最内层函数上
def timmer(func):
    @wraps(func)
    def wrapper(*args,**kwargs):
        start=time.time()
        res=func(*args,**kwargs)
        stop=time.time()
        print('run index is %s' %(stop - start))
        return res
    return wrapper

# @timmer #index=timmer(index)
def index():
    '''这是index函数'''
    time.sleep(3)
    print('welcome index')
    return 123
# index()
print(index.__doc__)   ### 查看注释  加上装饰器看不到只能是node 他看的是wrapper里的doc其实  要让wrapper的注释信息与index一样
# print(help(index))       ### 查看注释

 

6.7.2 多个装饰器

import time
from functools import  wraps                ### 在装饰器最内层函数上
current_user={'user':None}

def timmer(func):
    @wraps(func)
    def wrapper(*args,**kwargs):
        start=time.time()
        res=func(*args,**kwargs)
        stop=time.time()
        print('run index is %s' %(stop - start))
        return res
    return wrapper

def auth(auth_type='file'):             ### 默认参数 不传值走file验证
    def deco(func):
        def wrapper(*args,**kwargs):
            if auth_type =='file':            ### 如果验证类型是文件
                if current_user['user']:
                    return func(*args,**kwargs)
                name=input('Please input your name: ').strip()
                password=input('Please input your password: ').strip()
                with open('user.txt','r',encoding='utf-8') as  f:
                    dic=eval(f.read())
                    # print(dic,type(dic))
                if name in dic and password == dic[name]:
                    res=func(*args,**kwargs)
                    current_user['user']=name
                    return res
                else:
                    print('name or password error')
            elif auth_type == 'mysql':
                print('mysql')
            elif auth_type == 'ldap':
                print('ldap')
            else:
                print('not vlaid auth_type')
        return wrapper
    return deco

### 装饰器是修饰最下方,如果先写time 就会修饰auth 所以要分清楚函数中的方法是否有执行时间 谁在上面谁生效
@auth()
@timmer #index=timmer(index)

def index():
    '''这是index函数'''
    time.sleep(3)
    print('welcome index')
    return 123
index()

 

 

第7章 迭代器

7.1 什么是迭代器

# 迭代:是一个重复的过程,每一次的重复都是基于上一次的结果而来

# 迭代器:不依赖索引的取值方式
# 可迭代对象iterable :凡是对象下有__iter__方法:(对象..__iter__),该对象就是可迭代对象

 

7.2 字典迭代

dic={'name':'leo','sex':'male','age':28}
i=dic.__iter__()
print(i)   

>>> <dict_keyiterator object at 0x0000005695807728>

# iterator  迭代器对象   

# <dict_keyiterator object at 0x0000009D419F7728> 这个结果称为  iterator 迭代器对象

 

dic={'name':'leo','sex':'male','age':28}
i=dic.__iter__()
print(i)    # iterator  迭代器对象   # <dict_keyiterator object at 0x0000009D419F7728> 这个结果称为  iterator 迭代器对象
# i.__next__() # next(i)  # 字典取值也是无序的 取到了字典的key
print(next(i))
print(next(i))
print(next(i))
# print(next(i)) # 出异常 StopIteration 迭代器没值了

 

>>> <dict_keyiterator object at 0x000000CE0EBC7728>

>>> name

>>> sex

>>> age

 

7.3 列表迭代

l=['a','b','c','d','e'] # 列表可迭代对象
i=l.__iter__()  # 迭代器对象
print(i)
i1=i.__iter__() # 再赋值一次 发现结果相同
print(i1)

 

>>> <list_iterator object at 0x000000358B768A90>
>>> <list_iterator object at 0x000000358B768A90>   

### 迭代器也有iter方法,本身也是可迭代对象,除了iter还有next方法

 

 

l=['a','b','c','d','e'] # 列表可迭代对象
i=l.__iter__()  # 迭代器对象
print(i)
i1=i.__iter__() #
print(i1)
# # <list_iterator object at 0x000000358B768A90>
# # <list_iterator object at 0x000000358B768A90>    迭代器也有iter方法,本身也是可迭代对象,除了iter还有next方法
# 列表是有序的 字典是无序的
print(next(i))
print(next(i))
print(next(i))
print(next(i))
print(next(i))
# print(next(i))          #StopIteration
# 依赖索引的适用于列表、元组、字符串,迭代器适用于所有可迭代的数据类型

 

7.4 迭代器 不依赖索引取值

# s='hello'
# l=['a','b','c','d','e']
# t=('a','b','c','d','e')
# dic={'name':'leo','sex':'male','age':28}
# set1={1,2,3,4,5}
# f=open('user.txt')

 

# 都是可迭代对象 都有__iter__这个方法
# s.__iter__()
# l.__iter__()
# t.__iter__()
# dic.__iter__()
# set1.__iter__()
# f.__iter__()

 

l=['a','b','c','d','e']
dic={'name':'leo','sex':'male','age':28}

iter_l=l.__iter__()
while True:
    #print(next(iter_l)) #
   
try:
        print(next(iter_l))     # iter_l.__next__()
   
except StopIteration:      # 捕捉异常,写好异常的名字
       
break                  # 碰到这个异常 终止循环

iter_dict=dic.__iter__()
while True:
    try:
        k=next(iter_dict)       ### 取得字典的key
       
print(k,dic[k])         ### 取字典的key和value
   
except StopIteration:
        break

 

7.5 迭代器总结

### 文件迭代:

with open('a.txt',encoding='utf-8') as f:
    # f.__iter__()    # 可迭代对象
    # f.__next__()    # 迭代器对象 说明可以直接next
   
print(next(f))
    print(next(f))
    print(next(f))

# f.read()          # 适用于较小文件

 

迭代器总结:
1、有_iter_ 可迭代对象
2、有_next_ 迭代器对象

迭代器对象的优点:
1、提供一种统一的(不依赖索引)迭代方式
2、迭代器本身,比起其他数据类型更省内存 自定义迭代器可以存无穷的值

迭代器对象的缺点:
1、一次性只能往后走next,不能回退,不如索引取值灵活
2、无法预知什么时候取值结束,即无法预知长度

 

# for循环原理:迭代器协议
l=['a','b','c','d','e']
for item in l: # iter_l=l._iter_() 只要有iter方法 都可以放在for循环后面
    print(item) # next(iter_l) for循环会捕捉异常并结束循环

 

7.6 判断可迭代对象与迭代器对象(了解)


from collections import Iterable,Iterator
s='hello'
l=['a','b','c','d','e']
t=('a','b','c','d','e')
dic={'name':'leo','sex':'male','age':28}
set1={1,2,3,4,5}
f=open('user.txt')

print(isinstance(s,Iterable))       ### 可迭代对象
print(isinstance(s,Iterator))       ### 迭代器对象
print(isinstance(f,Iterable))
print(isinstance(f,Iterable))       ### 文件即是可迭代对象,也是迭代器对象

 

第8章 生成器

# 生成器:在函数内部包含yield关键字,那么该函数执行的结果是生成器

def func():
    print('first')
    yield 111
    print('second')
    yield 222
    print('third')
    yield 333
# func()          # 含有yield关键字 代码并不会直接执行 而是得到了生成器
g=func()
print(g)          # <generator object func at 0x0000006F9032FE60> generator 生成器

from collections import Iterable,Iterator
#g.__iter__
#g.__next__
print(isinstance(g,Iterable))
print(isinstance(g,Iterator))

True

True
### 生成器就是迭代器

 

def func():
    print('first')
    yield 111
    print('second')
    yield 222
    print('third')
    yield 333

g=func()
# next(g)     # 要func函数执行 要使用next         # 得到first, next会从头到尾执行函数,碰到yield  相当于retrun
print(next(g))      # 得到yield的值 next会触发迭代器的运行函数的执行,碰到yield停下来 并且将后面的值返回

 

>>> first

>>> 111

 

#1、把函数做成迭代器

#2、对比return,可以返回多次值,可以挂起/保存函数的运行状态

 

 

def func():
    print('first')
    yield 111
    print('second')
    yield 222
    print('third')
    yield 333
    print('fourth')
# func()          # 含有yield关键字 代码并不会直接执行 而是得到了生成器
g=func()
# print(g)          # <generator object func at 0x0000006F9032FE60> generator 生成器
# from collections import Iterable,Iterator
#g.__iter__
#g.__next__
# print(isinstance(g,Iterable))
# print(isinstance(g,Iterator))
### 生成器就是迭代器
# next(g)     # 要func函数执行 要使用next         # 得到first, next会从头到尾执行函数,碰到yield  相当于retrun
print(next(g))      # 得到yield的值 next会触发迭代器的运行函数的执行,碰到yield停下来 并且将后面的值返回
print("=========")
print(next(g))      # yield帮忙暂停了函数的执行 下一次执行从暂停的位置继续
print("=========")
print(next(g))
print("=========")
print(next(g))      # 这一次没有yield 没有返回值了就报 StopIteration

 

 

def func():
    print('first')
    yield 111
    print('second')
    yield 222
    print('third')
    yield 333
    print('fourth')

g=func()
for i in g: # i=iter(g)     ### 函数也可以被循环 因为是迭代器 只要是迭代器对象就可以被for循环
   
print(i)

 

>>> first

>>> 111

>>> second

>>> 222

>>> third

>>> 333

>>> fourth

 

 

8.1 无穷值的类型

# 生成器
def func(n):
    print('我开动了')
    while True:
        yield n
        n+=1
g=func(0)
# print(next(g))
# print(next(g))
for i in g:
    print(i)

 

 

8.2 使用生成器写range

# x=range(10000)
# # print(x)    #range(0, 10000)
# print(x.__iter__()) # 可迭代对象
#
# for i in range(10000):
#     print(i)        # range得到的是可迭代对象 一次一个值 不要在python2里这么做

def my_range(start,stop):
    while True:
        if start == stop:
            raise StopIteration
        yield start
        start+=1

for i in my_range(1,3):
    print(i)
# g=my_range(1,3)
# print(next(g))
# print(next(g))
# print(next(g))  # StopAsyncIteration

 

 

8.3 使用生成器写tail-f|grep error

# tail -f  a.txt | grep 'error'
# 管道符号 | 一个程序 传给 另外一个程序
import time

def tail(filepath):
    with open(filepath,'r') as f:
        f.seek(0,2)
        while True:
            line=f.readline()
            if line:
                yield line
            else:
               time.sleep(0.2)

def grep(patten,lines):
    for line in lines:
        if patten in line:
            print(line,end='')

# lines=tail('access.log')
# for line in lines:
#     print(line)
grep('error',tail('access.log'))    # 只有error才会打印

### 文本追加内容
with open('access.log','a') as f:
    f.write('1234567error\n')

 

第9章 三元表达式

# def foo(x):
#     if x > 3:
#         return 'ok'
#     else:
#         return 'no'
# x=10
res='ok' if x > 3 else 'no' # 判断条件在中间 成立的值在左边 不成立在右边
print(res)

def max2(x,y):
    return x if x > y else y
#     # if x > y:
#     #     return x
#     # else:
#     #     return y
print(max(1,3))

name=input('>>: ')
# if name == 'alex':
#     print('SB')
# else:
#     print('NB')
res='SB' if name == 'alex' else 'NB'
print(res)

 

 

把最简单的if判断用一行来表达

 

第10章 列表解析

# # 10个鸡蛋列表
# l=[]
# for i in range(10):
#     l.append('egg%s' %i)
# print(l)

# 列表解析
l=['egg%s' %i for i in range(10) ]   # 会循环10次 产生的值会直接放在列表里去放到左边 当做第一个元素
print(l)

 

# 直接在列表里写for循环

 

# 10个鸡蛋列表 只要5个
l=[]
for i in range(10):
    if i >=5:
        l.append('egg%s' %i)
print(l)

# 列表解析
l=['egg%s' %i for i in range(10) if i >=5 ]
print(l)

 

 

# 新列表的值 是原来值的平方
# nums=[1,2,3,4,5,6]
# new_nums=[]
# for item in nums:
#     new_nums.append(item**2)
# print(new_nums)

nums=[1,2,3,4,5,6]
new_nums=[item**2 for item in nums]
print(new_nums)

new_nums=[item**2 for item in nums if item > 3 ]
print(new_nums)

 

# 把有结尾含有sb的加入到一个新列表
names=['alex_sb','wupeiqi_sb','egon','yuanhao_sb']
new_names=[ i for i in names if i.endswith('sb')]
print(new_names)

 

第11章 生成器表达式

# 生成器表达式
# 和列表解析一样 把[]换成()
g=('egg%s' %i for i in range(10000))        # <generator object <genexpr> at 0x0000008A7DDFFF10> 生成器
print(g)
print(next(g))                      # 一次取一个值
print(next(g))

 

数据量大的情况 就不用[],而用生成器

 

# 求文件中access.log 最长一行的内容的长度
with open('access.log','r',encoding='utf-8')as f:
    # new_l=[len(line) for line in f]
    # print(new_l)
    # print(max(new_l))           # \n换行算一个字符
# 如果内容非常大 要用生成器
    res=((len(line) for line in f))
    print(max(res))

 

# 求a.txt中的购物花了多少钱

# print(sum([1,2,3])) # sum求和函数
# print(sum((i for i in range(3)))) # 0 + 1 + 2 sum计算生成器表达式

# 这样取出文件中每一行花的钱


    # l=[]
    # for line in f:              # 循环读取文件内容
    #     goods=line.split()       # 先按照空格切分 获取内容
    #     price=int(goods[1])    # 1 2 是商品价格和购买数量
    #     count=int(goods[2])
    #     cost=price * count       # 计算一行的商品价格总和
    #     l.append(cost)              # 加入新列表
    #     # print(l)
    #
    # print(sum(l))                # 计算列表之和  196060

# [{'name':'apple','price':333,'count':3}]
with open('a.txt','r',encoding='utf-8') as f:
    # l=[ float(line.split()[1]) * int(line.split()[2]) for line in f ]            # 列表解析 文件内容过大时使用()生成器表达式
    # print(sum(l))               # 196060.0
    # info= [{ 'name':line.split()[0],'price':float(line.split()[1]),'count':line.split()[2]} for line in f ]
    # print(info)     #[{'name': 'apple', 'price': 10.0, 'count': '3'},...]
# 取出价格大于等于30000
    info = [{'name': line.split()[0], 'price': float(line.split()[1]), 'count': line.split()[2]} for line in f if float(line.split()[1]) >= 30000]
    print(info)     # [{'name': 'tesla', 'price': 100000.0, 'count': '1'}, {'name': 'lenovo', 'price': 30000.0, 'count': '3'}]

 

第12章 序列化

 

转载于:https://www.cnblogs.com/touchlixiang/p/7665739.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值