zoukankan      html  css  js  c++  java
  • python之函数深入探测

    第一:命名空间与作用域

    命名空间:

    局部命名空间:

    def foo():

      x=1

      def func():

        pass

    全局命名空间:

    import time

    class ClassName:pass

    def foo():pass

    内键命名空间:

    sum,max,min 等

    python加载三个命名空间的顺序:

    1.内键命名空间

    2.全局命名空间:文件级别的或叫做模块级别的

    3.局部命名空间:只有调用函数的时候才会加载,函数调用结束就被释放掉

    作用域: 

    全局作用域:

    同时x=1为全局变量
    x=1
    def func1():
        def func2():
            def func3():
                print(x)
            func3()
        func2()
    func1()
    
    输出结果
    1

    局部作用域:

    x=1
    def func1():
        def func2():
            def func3():
                x=100
                print(x)
            func3()
        func2()
    func1()
    
    
    输出结果:
    100

    第二:闭包

    闭包:本质就是一个内部函数

    特点:这个内部函数必须包含对外部函数作用域(非全局作用)名字的引用

    示例:

    def f1():
        x=1
        y=2
        def f2():
            print(x)
            print(y)
        return f2
    
    func=f1()
    #func()
    print(func.__closure__[0].cell_contents)#查看闭包函数的方法
    print(func.__closure__[1].cell_contents)
    
    #f2为闭包函数
    
    输出结果:
    1
    2

    惰性计算:啥时候用啥时候调用

    from urllib.request import urlopen
    
    def page(url): 
        def get():
            return urlopen(url).read()
        return get
    
    baidu=page('http://www.baidu.com')
    python=page('http://www.python.org')
    
    print(baidu)
    print(python)
    
    输出结果:
    <function page.<locals>.get at 0x0000000002DE6BF8>
    <function page.<locals>.get at 0x0000000002DE6C80>
    
    函数没有执行,已经传了一个参数

    第三:装饰器

    开放封闭原则

    装饰器需要遵循的原则:1,不改变被修饰对象的源代码;2,不改变被修饰对象的调用方式

              装饰器是在遵守1和2的前提下,为被装饰的对象添加新功能

    装饰器无参基本框架:
    #这就是一个实现一个装饰器最基本的架子
    def timer(func):
        def wrapper():
            func()
        return wrapper

    装饰器有参基本框架:

    def timer(func):
        def wrapper(*args,**kwargs):
             func(*args,**kwargs)
        return wrapper

    无参装饰器:

    import time
    def timer(func): #func=最原始的index
        def warpper():
            start_time=time.time()
            func()
            end_time=time.time()
            print('run time is %s' % (end_time - start_time))
        return warpper
    
    #无参装饰器
    @timer #index=timer(index) 此时的index就是warpper
    def index():
        time.sleep(1)
        print("welcome to index")
    
    index()#就是在调用warpper()
    
    原来的index的函数只会输出welcome to index
    加上装饰器后;
    输出内容为:
    welcome to index
    run time is 1.0060575008392334

    有参数装饰器:

    import time
    def timer(func): #func=最原始的index
        def warpper(user):
            start_time=time.time()
            func(user)
            end_time=time.time()
            print('run time is %s' % (end_time - start_time))
        return warpper
    
    @timer #index=timer(index) 此时的index就是warpper
    def home(user):
        time.sleep(1)
        print("home %s"% user)
    
    home('cy')#就是在调用warpper()
    
    输出结果:
    home cy
    run time is 1.0000574588775635

    如果传入的参数是关键字类型或者其他的

    import time
    def timer(func): #func=最原始的index
        def warpper(*args,**kwargs):
            start_time=time.time()
            func(*args,**kwargs)
            end_time=time.time()
            print('run time is %s' % (end_time - start_time))
        return warpper
    
    @timer #index=timer(index) 此时的index就是warpper
    def home(user):
        time.sleep(1)
        print("home %s"% user)
    
    home('cy')#就是在调用warpper()
    home(user="zzl")
    #输出结果:
    home cy
    run time is 1.0000574588775635
    home zzl
    run time is 1.0000569820404053

    如果原函数有返回值:

    import time
    def timer(func): #func=最原始的index
        def warpper(*args,**kwargs):
            start_time=time.time()
            res=func(*args,**kwargs)
            end_time=time.time()
            print('run time is %s' % (end_time - start_time))
            return res
        return warpper
    
    @timer #index=timer(index) 此时的index就是warpper
    def home(user):
        time.sleep(1)
        return user + ' is student'
    
    res=home('cy')#就是在调用warpper()
    print(res)
    #输出结果:
    run time is 1.0000574588775635
    cy is student

    装饰器的应用:

    无参装饰器的应用:

    user_info

    name:zzl,passwd:123
    name:cyy,passwd:123
    name:cy,passwd:123
    name:zl,passwd:123

    code:

    def user_info():
        file = open('user_info')
        data=file.readlines()
        list_info=[]
        for i in data:
            lis=[i.strip()]
            for s in lis:
                result = [ele.strip() for ele in s.split(",")]
                dict_info={}
                for x in result:
                    res = [ele.strip() for ele in x.split(':')]
                    dict_info.update(dict([res]))
                list_info.append(dict_info)
        return list_info
    
    user_list=user_info()
    
    def help():
        print(user_list)
    
    current_user={'username':None,'login':False}
    
    def auth_deco(func):
        def wrapper(*args,**kwargs):
            if current_user['username'] and current_user['login']:
                res=func(*args,**kwargs)
                return res
            username=input('用户名: ').strip()
            passwd=input('密码: ').strip()
            for index,user_dic in enumerate(user_list):
                if username == user_dic['name'] and passwd == user_dic['passwd']:
                    current_user['username']=username
    
                    current_user['login']=True
                    res=func(*args,**kwargs)
                    return res
                    break
            else:
                print('用户名或者密码错误,重新登录')
    
        return wrapper
    
    help()
    
    #无参函数
    @auth_deco
    def home():
        print('这里是你家')
    home()

    有参装饰器的应用:

    user_info

    name:zzl,passwd:123
    name:cyy,passwd:123
    name:cy,passwd:123
    name:zl,passwd:123

    code:

    def user_info():
        file = open('user_info')
        data=file.readlines()
        list_info=[]
        for i in data:
            lis=[i.strip()]
            for s in lis:
                result = [ele.strip() for ele in s.split(",")]
                dict_info={}
                for x in result:
                    res = [ele.strip() for ele in x.split(':')]
                    dict_info.update(dict([res]))
                list_info.append(dict_info)
        return list_info
    
    user_list=user_info()
    
    def help():
        print(user_list)
    
    current_user={'username':None,'login':False}
    def auth(auth_type='file'):
        def auth_deco(func):
            def wrapper(*args,**kwargs):
                if auth_type == 'file':
                    if current_user['username'] and current_user['login']:
                        res=func(*args,**kwargs)
                        return res
                    username=input('用户名: ').strip()
                    passwd=input('密码: ').strip()
    
                    for index,user_dic in enumerate(user_list):
                        if username == user_dic['name'] and passwd == user_dic['passwd']:
                            current_user['username']=username
                            current_user['login']=True
                            res=func(*args,**kwargs)
                            return res
                            break
                    else:
                        print('用户名或者密码错误,重新登录')
                elif auth_type == 'ldap':
                    print('我是ldap')
                    res=func(*args,**kwargs)
                    return res
            return wrapper
        return auth_deco
    
    
    #auth(auth_type='file')就是在运行一个函数,然后返回auth_deco,所以@auth(auth_type='file')
    #就相当于@auth_deco,只不过现在,我们的auth_deco作为一个闭包的应用,外层的包auth给它留了一个auth_type='file'参数
    @auth(auth_type='ldap')
    def index():
        print('欢迎来到主页面')
    
    @auth(auth_type='file')
    def home():
        print('到家了')
    
    index()
    
    print(user_list)
    home()

    第四:迭代器

    #迭代:更新换代 描述的是一个重复的过程 for while

    lis=[4,5,6]
    i=0
    while i<len(lis):
        print(lis[i])
        i+=1
    
    for i in range(len(lis)):
        print(lis[i])
    
    #输出结果:
    4
    5
    6
    4
    5
    6

    针对没有下标的数据类型,我们在想迭代他们的话,就必须提供一种不按照下标取值的方式,python针对这种情况,已经为很多很多的数据类型内置了一个__iter__的方法。

    d={'a':1,'b':2}
    print(d.__iter__())
    print([].__iter__())
    #输出结果:
    <dict_keyiterator object at 0x000000000214B728>
    <list_iterator object at 0x0000000002859400>

     数据类型凡是有__iter__方法的都是可迭代的iterable,执行这个方法得到结果就是迭代器iterator,凡是iterator都内置一个__next__方法

    d={'a':1,'b':2}
    i=d.__iter__()
    print(i)
    print(i.__next__())
    print(i.__next__())
    print(i.__next__())
    
    输出结果:
    <dict_keyiterator object at 0x000000000220B778>
    a
    b
        print(i.__next__())
    StopIteration               #这个不是报错是字典没有值了

     迭代的认识(针对列表)

    l=[1,2,3,4,5]
    i=iter(l)
    while l:
        try:
            print(next(i)) #i.__next__()
        except StopIteration as e:
            break
    
    for i in l:#l.__iter__()
        print(i)
        
    #输出结果:
    1
    2
    3
    4
    5
    1
    2
    3
    4
    5

    迭代器牛逼之处:针对没有下边的数据类型:(字典,文件等) 

    字典:

    dic={'a':1,'b':2,'c':3}
    d=iter(dic)
    while d:
        try:
            print(dic[next(d)])
        except StopIteration:
            break
    
    for i in dic:
        print(dic[i])
    
    # 输出结果:
    1
    2
    3
    1
    2
    3

    文件:

    f=open('text','r')
    print(f)
    for i in f: #i=f.__iter__()
        print(i)
    
    输出结果:
    <_io.TextIOWrapper name='text' mode='r' encoding='cp936'>
    zzl
    cyy

    for,while之所以能够循环字典,文件,是因为内置用了迭代器的方法

    迭代器的优点:

    1.提供了一种统一的迭代方式

    2.惰性计算,省内存

    迭代器的缺点:

    1.迭代器看起来就像是一个序列,但是你永远无法预知迭代器的长度

    2.不能倒着走,而且是一次性的,只能走一遍

    迭代器(Iterator),可迭代的(Iterable)

    from collections import Iterator,Iterable
    print(isinstance('zzl',Iterable))
    print(isinstance({},Iterable))
    print(isinstance((),Iterable))
    
    print(isinstance({}.__iter__(),Iterator))
    f=open('text','r')
    print(isinstance(f,Iterator))
    print(isinstance(f,Iterable))
    
    输出结果:
    True
    True
    True
    True
    True
    True

    第五:生成器

    #凡是在函数内部有关键字yield,那么这个函数就是一个生成器。 特别指数在于:函数名+()不再执行,而是得到一个生成器。

    from collections import Iterator
    def foo():
        print('我是老大')
        yield 1
        print('我是老二')
        yield 2
        print('我是老三')
        yield 3
        print('我是老四')
        yield 4
        print('我是老五')
        yield 5
        print('我是老六')
        yield 6
    
    g=foo() #调用以后把它当成迭代器来看
    print(g)
    print(isinstance(g,Iterator))
    print(next(g))
    print(next(g))
    print(next(g))
    print(next(g))
    print(next(g))
    print(next(g))
    print(next(g))
    
    输出结果:
    <generator object foo at 0x0000000002160620>
    True
    我是老大
    1
    我是老二
    2
    我是老三
    3
    我是老四
    4
    我是老五
    5
    我是老六
    6
    
     File "D:/my/python script/untitled/生成器.py", line 30, in <module>
        print(next(g))
    StopIteration  #这不是报错,而是没有值了,怎么解决呢,请往下看
    def foo():
        print('我是老大')
        yield 1
        print('我是老二')
        yield 2
        print('我是老三')
        yield 3
        print('我是老四')
        yield 4
        print('我是老五')
        yield 5
        print('我是老六')
        yield 6
    
    g=foo() #调用以后把它当成迭代器来看
    for i in g: #i=next(g)
        print(i)
    
    输出结果:
    我是老大
    1
    我是老二
    2
    我是老三
    3
    我是老四
    4
    我是老五
    5
    我是老六
    6

     总结:yield的功能是什么?

    1.yield是为函数定制__iter__和__next__方法,就是提供一种自定义迭代器的优雅的方法

    2.就相当于return,但是可以返回多次

    3.生成器本质就是一个数据流,next(生成器)才触发生成器函数的一次执行,下一次next会从上一次暂停的位置继续执行,直到重新遇到一个新的yield。

    实现tail -f one.txt |  grep ‘cy’的功能:

    import time
    def tail(file_path):
        with open(file_path) as f:
            f.seek(0,2)
            while True:
                line=f.readline()
                if not line:
                    time.sleep(0.1)
                else:
                    yield line
    
    def grep(lines,pattern):
        for line in lines:
            if pattern in line:
                yield line
    
    pattern_line=grep(tail(r'C:/one.txt'),'cy')
    for i in pattern_line:
        print(i)
    
    输出结果:
    cyy
  • 相关阅读:
    Mysql --学习:大量数据快速导入导出
    Mybatis 学习---${ }与#{ }获取输入参数的区别、Foreach的用法
    SSM 框架 ---项目整合
    SMM框架--maven创建web项目
    SSM框架—环境搭建(MyEclipse+Tomcat+MAVEN+SVN)
    Java中 try--catch-- finally、throw、throws 的用法
    Java集合:List、Set和Map的区别,ArrayList和LinkedList有何区别..........
    java中 this() 和super()的作用及用法
    Thread和Runnable的区别和联系、多次start一个线程会怎么样
    vue-devtools google扩展插件安装
  • 原文地址:https://www.cnblogs.com/ylqh/p/6417698.html
Copyright © 2011-2022 走看看