PYTHON_DAY_04

馋奶兔 提交于 2020-03-23 06:02:11

目录

一.函数对象

二.函数的嵌套

三.函数名称空间与作用域

四.闭包函数

五.无惨装饰器简单实现

六.装饰器的流程分析及修订

七.有参装饰器的实现及附加多个装饰器流程分析

八.叠加多个装饰器

九.迭代器

十.生成器

十一.内置函数


一:函数对象:函数是第一类对象,即函数可以当作数据传递1. 可以被引用
def foo():
    print('from foo')

func=foo

print(foo)
print(func)
func()

  

2. 可以当作参数传递
def foo():
    print('from foo')

def bar(func):
    print(func)
    func()      # 这里在执行foo() 并打印结果

bar(foo)            # 这里执行函数bar() 传入的参数func就是foo地址

  

3. 返回值可以是函数
def foo():
    print('from foo')

def bar(func):
    return func

f=bar(foo)

print(f)

f()

  

4. 可以当作容器类型的元素
def foo():
    print('from foo')

dic={'func':foo}    #这里的value-foo就是函数的地址

print(dic['func'])

dic['func']()    
#利用该特性,优雅的取代多分支的ifdef foo():   print('foo')def bar():   print('bar')dic={        'foo':foo,        'bar':bar,    }while True:    choice=input('>>: ').strip()    if choice in dic:        dic[choice]()
#应用def select(sql):    print('========>select')def insert(sql):    print('========>add')def delete(sql):    print('=======>delete')def update(sql):    print('-=---->update')func_dic={    'select':select,    'update':update,    'insert':insert,    'delete':delete}def main():    while True:        sql = input('>>: ').strip()        if not sql:continue        l = sql.split()        cmd=l[0]        if cmd in func_dic:            func_dic[cmd](l)main()# 这是上面的复杂版def main():    sql = input('>>: ')    l = sql.split()    print(l)    if l[0] == 'select':        select(l)    elif l[0] == 'insert':        insert(l)    elif l[0] == 'delete':        delete(l)    elif l[0] == 'update':        update(l)
main()

 

二:函数的嵌套 1 函数的嵌套调用
def max(x,y):
  return x if x > y else y

def max4(a,b,c,d):
  res1=max(a,b)
  res2=max(res1,c)
  res3=max(res2,d)
  return res3
print(max4(1,2,3,4))

  

 2 函数的嵌套定义
def f1():
        def f2():
              def f3():
                    print('from f3')
                f3()
            f2()

f1()
f3() #报错 f2和f3是被包含在里边的 无法找到

  

  

三 名称空间和作用域: A.名称空间定义:名字与值的绑定关系   3种名称空间:  1.内置名称空间:随着python解释器启动而产生  print(sum) #sum就是解释器内置的名称  2.全局名称空间:文件执行会产生全局名称空间,指的是文件级别定义的名字都会放入该空间  
x=1
def func():
    money=2000
    x=2
    print('func')

func()
print(x)        # x = 1
print(money)    # money找不到值

  

  3.局部名称空间:调用函数时会产生局部命名空间,只在函数调用时绑定,调用结束解绑定  
x=10000
def func():
    x=1
    def f1():
        pass

  

     B.作用域即范围(作用域关系是在函数定义阶段就已经固定的,与函数的调用位置无关)  1.全局作用域( 查看使用 gloabls() ):内置名称空间,全局名称空间  2.局部作用域( 查看使用 locals()  ):局部名称空间      LEGB 代表名字查找顺序: locals -> enclosing function -> globals -> __builtins__    locals 是函数内的名字空间,包括局部变量和形参    enclosing 外部嵌套函数的名字空间(闭包中常见)    globals 全局变量,函数定义所在模块的名字空间    builtins 内置模块的名字空间名字查找顺序:局部--》全局--》内置空间
#  反例  这里的变量就找不到 最终报错
def func():
    x=2

func()

print(x)  # 所处位置就是全局

  

#全局作用域:全局有效,在任何位置都能被访问到,除非del删掉,否则会一直存活到文件执行完毕#局部作用域的名字:局部有效,只能在局部范围调用,只在函数调用时才有效,调用结束就失效
x=1

def f1():
    print(x)

def foo():
    print(x)

def f(x):
    # x=4
    def f2():
        # x=3
        def f3():
            # x=2
            print(x)

        f3()
    f2()

f(4)

  

四:闭包:内部函数包含对外部作用域而非全局作用域的引用    def counter():        n=0        def incr():            nonlocal n            x=n            n+=1            return x        return incr    c=counter()    print(c())    print(c())    print(c())    print(c.__closure__[0].cell_contents) #查看闭包的元素闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域应用领域:延迟计算from urllib.request import urlopendef index(url):    def get():        return urlopen(url).read()    return getbaidu=index('http://www.baidu.com')print(baidu().decode('utf-8'))五: 装饰器1 为何要用装饰器:    开放封闭原则:对修改封闭,对扩展开放2 什么是装饰器   装饰器他人的器具,本身可以是任意可调用对象,被装饰者也可以是任意可调用对象。3. 先看简单示范
import time
    def timmer(func):
        def wrapper(*args,**kwargs):
            start_time=time.time()
            res=func(*args,**kwargs)
            stop_time=time.time()
            print('run time is %s' %(stop_time-start_time))
            return res
        return wrapper

    @timmer
    def foo():
        time.sleep(3)
        print('from foo')
    foo()

  

4.
def auth(driver='file'):
    def auth2(func):
        def wrapper(*args,**kwargs):
            name=input("user: ")
            pwd=input("pwd: ")

            if driver == 'file':
                if name == 'egon' and pwd == '123':
                    print('login successful')
                    res=func(*args,**kwargs)
                    return res
            elif driver == 'ldap':
                print('ldap')
        return wrapper
    return auth2

@auth(driver='file')
def foo(name):
    print(name)

foo('egon')

  

5. 装饰器语法:    在被装饰函数的正上方,单独一行    @deco1    @deco2    @deco3    def foo():        pass    foo=deco1(deco2(deco3(foo)))六:迭代器    迭代的概念:重复的过程称为迭代,每次重复即一次迭代,并且每次迭代的结果是下一次迭代的初始值        # while True: #只满足重复,因而不是迭代        #     print('====>')        #迭代        l=[1,2,3]        count=0        while count < len(l): #只满足重复,因而不是迭代            print('====>',l[count])            count+=1    为何要有迭代器?     --对于没有索引的数据类型,必须提供一种不依赖索引的迭代器    可迭代的对象?     --内置__iter__方法的,都是可迭代的对象   迭代器?    --执行__iter__方法,得到的结果就是迭代器,迭代器对象有__next__方法              l={'a':1,'b':2,'c':3,'d':4,'e':5}        i=l.__iter__() #等于i=iter(l)        print(next(i))        print(next(i))        print(next(i))    StopIteration? 异常处理方法
while True:
    try:                     # 把可能异常的写到try里面
        k=next(i)
        print(k)
    except StopIteration:   # 捕捉异常 异常的话break
        break

  

 
i={'a':1,'b':2,'c':3}.__iter__()

print(i.__next__())
print(i.__next__())
print(i.__next__())
print(i.__next__())      # 这里取道的是字典的key


dic={'a':1,'b':2,'c':3}   # 用key来取字典的value
i=dic.__iter__()
while True:
    try:
        key=i.__next__()
        print(dic[key])
    except StopIteration:
        break

  

len(s) == s.len()s.__iter__ == iter(s)
dic={'name':'egon','age':18,'height':'180'}  # 迭代字典生成元素为元组
print(dic.items())

for k in dic.items():     # for循环就相当于一个迭代器 得到的值就是字典的key
    print(k)
 
# for循环的实现过程如下:
i=iter(dic)
while True:
    try:
        k=next(i)
        print(k)
    except StopIteration:
        break

  

 
    迭代器的优缺点:        优点:            1.提供统一的且不依赖于索引的迭代方式            2.惰性计算,就迭代器本身节省内存;使用时 next()方法取值        缺点:            1.无法获取迭代对象长度            2.不如序列类型灵活,一次性的,只能往后走,不能往前退
# 对一个列表
l=[10000,2,3,4,5]

i=iter(l)

print(i)
print(next(i))     # 要想使用这个值 就next()方法


# 对一个文件 文件本身就是一个好迭代器
f=open('a.txt',encoding='utf-8')

#for line in f.readlines():      这样的话都读到内存里边 占用内存
#   print(line)

print(next(f))

for line in f:          # 遍历文件内容使用这个for
    print(line)

  

  

  七 生成器  yield功能:    1.把函数做成迭代器,相当于为函数封装好__iter__和__next__    2.对比return,可以返回多次值,每次返回都会将函数暂停,下一次next会从上一次暂停的位置继续执行
# def foo():
#     return 1
#     return 2
#     return 3
#
# res=foo()
# print(res)


def foo():
    yield 1
    yield 2
    yield 3

res=foo()
print(res)

from collections import Iterable,Iterator
print(isinstance(res,Iterator))

print(next(res))
print(next(res))
print(next(res))

  

应用一:计数功能counter
 def counter(n):
        print('start')
        i=0
        while i < n:
            yield i
            i+=1
        print('end')

    c=counter(5)
    # print(next(c)) #0
    # print(next(c)) #1
    # print(next(c)) #2
    # print(next(c)) #3
    # print(next(c)) #4
    # print(next(c))  --->没有yield,抛出StopIteration


    for i in counter(5):
        print(i)

  

应用二: 模拟管道tail -f a.txt |grep 'python'
# 管道左边的输出结果给到右边的grep 并执行查找‘python’;# tail功能是多次返回值,所以这里使用yield实现import time
def tail(filepath): # filepath 文件路径
    with open(filepath,encoding='utf-8') as f:  
        f.seek(0,2)
        while True:
            line=f.readline()
            if line:
                yield line
            else:
                time.sleep(0.5)

def grep(pattern,lines):
    for line in lines:
        if pattern in line:
            yield line

for i in grep('python',tail('a.txt')):
    print(i)

  



 

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!