day4

1.1   名称空间和作用域:
        名称空间:存放名字的地方,三种名称空间,(之前遗留的问题x=1,1存放于内存中,那名字x存放在哪里呢?名称空间正是存放名字x与1绑定关系的地方)
        加载顺序是?
        名字的查找顺序?(在全局无法查看局部的,在局部可以查看全局的)

        # max=1
        def f1():
            # max=2
            def f2():
                # max=3
                print(max)
            f2()
        f1()
        print(max)


 作用域即范围
- 全局范围:全局存活,全局有效
- 局部范围:临时存活,局部有效
- 作用域关系是在函数定义阶段就已经固定的,与函数的调用位置无关,如下
      x=1
      def f1():
          def f2():
              print(x)
          return f2

      def f3(func):
          x=2
          func()

      f3(f1())


        查看作用域:globals(),locals()

        global
        nonlocal


        LEGB 代表名字查找顺序: locals -> enclosing function -> globals -> __builtins__
        locals 是函数内的名字空间,包括局部变量和形参
        enclosing 外部嵌套函数的名字空间(闭包中常见)
        globals 全局变量,函数定义所在模块的名字空间
        builtins 内置模块的名字空间

装饰器:

定义 本质是函数,(装饰其他函数)就是为其他函数添加附加功能

原则:

1,不能修改被装饰的函数的源代码

2,不能修改被装饰的函数的调用方式

门牌号都没有的时候(没有引用的时候) 内存存的值就会被释放回收  这就是垃圾回收

del x 删除的是变量名 不是变量值

函数先定义 再调用

没定义 调用就会报错

1.2 高阶函数

1.2.1 a:把一个函数名当做实参传给另外一个函数(在不修改被装饰函数源代码的情况下为其添加功能)但是改变了调用方式

1.函数接收的参数是一个函数名
  作用:在不修改函数源代码的前提下,为函数添加新功能,
  不足:会改变函数的调用方式

实例1-1   

import time
def bar():
    time.sleep(3)
    print('in the bar')
def test(func):
    start_time=time.time()
    func()
    stop_time=time.time()
    print('the func run time is %s' %(stop_time -  start_time))
test(bar)

1.2.2 b:返回值中包含函数名(不修改函数的调用方式)但不能添加新功能

函数的返回值是一个函数名
  作用:不修改函数的调用方式
  不足:不能添加新功能

import time

def bar():

    time.sleep(3)

    print('in the bar')

def test2(func):

    print(func)

    return func

# print(test2(bar))

bar=test2(bar)#把bar的内存地址传给bar

bar()  #run bar




1.3 嵌套函数

函数的嵌套定义:在一个函数的内部,又定义另外一个函数

def foo():

    print('in the foo')

    def bar():

        print('in the bar')

    bar()

foo()

1.4 闭包函数:

#1. 定义在函数内部的函数

#2. 包含对外部作用域名字的引用,而不是对全局作用域名字的引用

#那么该内部函数就称为闭包函数

 # x=1
# def  f1():
#     x=11111111111
#     def f2():
#         print(x)
#     return f2
# func=f1()
#
# x=1000
# func()
#
# def foo():
#     x=12312312312312312312312312312312312313123
#     func()
#
#
# foo()


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

func()

第2章 高阶函数+嵌套函数=》》装饰器

'''import time
def deco(func):
    start_time=time.time()
    func()
    stop_time=time.time()
    print(stop_time-start_time)
def test1():
    time.sleep(3)
    print('in the test1')
def test2():
    time.sleep(3)
    print('in the test2')
deco(test1)
deco(test2)
''' 
#利用高阶函数把函数名当做传参的方式
实现增加了功能没改变源代码 也就是函数的定义没变 但是 改变了原函数的调用方式


#接下来我们加一层嵌套函数 看能否不改变调用方式能否实现新加功能
import time
def timer(func):  #   timer(test1)  func=test1
   
def deco():
        start_time=time.time()
        func()  #  run test1()
       
stop_time=time.time()
        print('run time is %s'%(stop_time-start_time))
    return deco
@timer  # test1=timer(test1)
def test1():   
   
time.sleep(3)
    print('in the test1')
@timer # test2=timer(test2)
def test2():  
   
time.sleep(3)
    print('in the test2')
#print(timer(test1))
# test1=timer(test1)
# test2=timer(test2)
test1()
test2()
# deco(test1)
# deco(test2)

2.1 装饰器高潮版

import time

def timmer(func):

    def wrapper(*args,**kwargs):

        start=time.time()

        res=func(*args,**kwargs)

        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

@timmer # home=timmer(home)

def home(name):

    time.sleep(2)

    print('welcome %s to home page' %name)

# res=index() #res=wrapper()

# print(res)

res1=home('egon') #wrapper('egon')

print(res1)

2.2 装饰器语法:
        被装饰函数的正上方,单独一行
        @deco1
        @deco2
        @deco3
        def foo():
            pass

        foo=deco1(deco2(deco3(foo)))

2.3 升级版装饰器 支持原函数各类参数的传入

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 time is %s' %(stop-start))

        return res

    return wrapper

@timmer # index=timmer(index)

def index():

    '''这是index函数'''

    time.sleep(3)

    print('welcome to index')

    return 123

print(index.__doc__)

# print(help(index))

2.4 补充二:一个函数头顶上可以多个装饰器

时间装饰器,认证装饰器

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 time is %s' %(stop-start))

        return res

    return wrapper

def auth(auth_type='file'):

    def deco(func):

        def wrapper(*args, **kwargs):

            if auth_type == 'file':

                if current_user['user']:

                    return func(*args, **kwargs)

                name = input('name: ').strip()

                password = input('password: ').strip()

                with open('db.txt', encoding='utf-8') as f:

                    user_dic = eval(f.read())

                if name in user_dic and password == user_dic[name]:

                    res = func(*args, **kwargs)

                    current_user['user'] = name

                    return res

                else:

                    print('user or password error')

            elif auth_type == 'mysql':

                print('mysql')

            elif auth_type == 'ldap':

                print('ldap')

            else:

                print('not valid auth_type')

        return wrapper

    return deco

@timmer #index=timmer(wrapper)

@auth() # @deco #index=deco(index) #wrapper

def index():

    '''这是index函数'''

    time.sleep(3)

    print('welcome to index')

    return 123

# print(index.__doc__)

# print(help(index))

index()

2.5 列表生成式

>>>L = [x * 2 for x in range(10)]

>>> L

[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

>>> g=(x * 2 for x in range(10))

>>> g

<generator object <genexpr> at 0x02CC5F80>

>>> for i in g:

   print(i)

  

0

2

4

6

8

10

12

14

16

18

>>> a= [ i for i in range(10)]

>>> a = map(lambda x:x+1, a)

>>> a

<map object at 0x02F66AD0>

>>> for i in a:print(i)

1

2

3

4

5

6

7

8

9

10

生成器只会在调用的时候才会生成相应的数据

只记录当前的位置只有一个__next__()方法。next()

[1,2,3,4,5,6,7,8,9]

2.6 斐波那契数列

 

def fib(max):
    n,a,b =0,0,1
    while n< max:
        yield b
        a,b =b,a+b
        n=n+1
    return '---done--' #异常的时候打印的消息
# fib(10)
# for n in fib(10):
#     print(n)
g=fib(10)
while True:
    try:
        x = next(g)
        print('g:',x)
    except StopIteration as e:
        print('Generator return value:',e)
        break
# print(g.__next__())
# print(g.__next__())
# print(g.__next__())
# print(g.__next__())
# print(g.__next__())
# print(g.__next__())
# print(g.__next__())
next 方法到没数据时会报错

如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator:

2.7 迭代对象

具有__iter__方法的都是可迭代对象

说着说可以直接用于for循环的对象统称为可迭代对象 Iterable

一类是集合数据类型,如list、tuple、dict、set、str等

一类是generator,包括生成器和带yield的generator function

可以使用isinstance()判断一个对象是否是Iterable对象:

>>> from collections import Iterable

>>> isinstance([],Iterable)

True

>>> isinstance({},Iterable)

True

>>> isinstance('abc',Iterable)

True

>>> isinstance((x for x in range(10)),Iterable)

True

>>> isinstance(100,Iterable)

False

2.8 迭代器

1具有__iter__方法

2可以被next()函数调用并不断返回下一个值的对象

跌对象转为迭代器的方法


x='asdfggf'
x1=iter(x)
print(next(x1))
print(next(x1))
print(next(x1))

 

而生成器不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了。

*可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator

可以使用isinstance()判断一个对象是否是Iterator对象:

>>> from collections import Iterator

>>> isinstance((x for x in range(10)), Iterator)

True

>>> isinstance([], Iterator)

False

>>> isinstance({}, Iterator)

False

>>> isinstance('abc', Iterator)

False

>>> 

生成器都是Iterator对象,但list、dict、str虽然是Iterable,却不是Iterator。

把list、dict、str等Iterable变成Iterator可以使用iter()函数:

>>> isinstance(iter([]), Iterator)

True

>>> isinstance(iter({}), Iterator)

True

>>> isinstance(iter('abc'), Iterator)

True

你可能会问,为什么list、dict、str等数据类型不是Iterator?

这是因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。

小结

凡是可作用于for循环的对象都是Iterable类型;

凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;

集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。

or甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。

Python的for循环本质上就是通过不断调用next()函数实现的,例如:

for x in [1, 2, 3, 4, 5]:

    pass

# 首先获得Iterator对象:
it = iter([1, 2, 3, 4, 5])
# 循环:
while True:
    try:
        # 获得下一个值:
        x = next(it)
    except StopIteration:
        # 遇到StopIteration就退出循环
        break

2.9 生成器也是迭代器

只不过他的值不是一下全部在内存的 在是一个一个的生成的,只能前进没法后退 无法知道什么时候结束知道遇到

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

#生成器就是迭代器

#yield的功能:

# 1 把函数的结果做生迭代器(以一种优雅的方式封装好__iter__,__next__)

# 2 函数暂停与再继续运行的状态是由yield

# def func():

#     print('first')

#     yield 11111111

#     print('second')

#     yield 2222222

#     print('third')

#     yield 33333333

#     print('fourth')

#

#

# g=func()

# print(g)

# from collections import Iterator

# print(isinstance(g,Iterator))

# print(next(g))

# print('======>')

# print(next(g))

# print('======>')

# print(next(g))

# print('======>')

# print(next(g))

# for i in g: #i=iter(g)

#     print(i)

# def func(n):

#     print('我开动啦')

#     while True:

#         yield n

#         n+=1

#

# g=func(0)

#

# # print(next(g))

# # print(next(g))

# # print(next(g))

# for i in g:

#     print(i)

#

# for i in range(10000):

#     print(i)

# def my_range(start,stop):

#     while True:

#         if start == stop:

#             raise StopIteration

#         yield start #2

#         start+=1 #3

#

# g=my_range(1,3)

# #

# print(next(g))

# print(next(g))

# print(next(g))

#

#

# for i in my_range(1,3):

#     print(i)

#yield与return的比较?

#相同:都有返回值的功能

#不同:return只能返回一次值,而yield可以返回多次值

# python3 tail.py -f access.log | 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(pattern,lines):

    for line in lines:

        if pattern in line:

            print(line,end='')

grep('error',tail('access.log'))

原文地址:https://www.cnblogs.com/lieying6011/p/7248263.html