• Python学习week4


    装饰器:本质是函数,用来装饰其他的函数,为其它函数添加附加功能。

    原则:不能改变被装饰函数的源代码和调用方式。

    1、函数即‘变量’,定义一个函数相当于把函数体赋值给函数名,匿名函数相当于只有函数体没有函数名

    def func1():
        print('in the function')
    func2=func1     #和普通的整数赋值一样:a=2 b=a print(b)
    func2()
    

    2、高阶函数

    3、嵌套函数

    装饰器=高阶函数+嵌套函数


    高阶函数:

    1、把一个函数名当作实参传递给另外一个函数;(在不修改被装饰函数源代码的情况下为其添加功能)

    2、返回值中包含函数名。(不修改函数的调用方式)

    import time
    def bar():
        time.sleep(2)
        print('in the bar')
    def timer(func):
        start_time=time.time()
        func()
        stop_time=time.time()
        print('the time of running is %s'%(stop_time-start_time))
    timer(bar)
    输出:
    in the bar
    the time of running is 2.0002079010009766
    函数执行计时器
    import time
    def bar():
        time.sleep(2)
        print('in the bar')
    def test(func):
        print(func)     #如果参数是函数,则此处打印的是函数在内存中的位置信息
        func()
        return func
    test(bar)       #将函数名作为实参传递给调用函数
    #test(bar())     #错误用法,将函数返回值传递给调用函数,不符合高阶函数定义
    输出:
    <function bar at 0x000001717B027F28>
    in the bar
    调用函数返回被调用函数名

    嵌套函数:在一个函数的函数体内定义另一个函数,不是调用,是def定义

    def test():
        print('in the test')
        def inner():        #内部函数,相当于局部变量,只能在test()内部调用
            print('in the inner')
        inner()
    test()
    输出:
    in the test
    in the inner
    嵌套函数

    装饰器:

    import time
    def timer(func):        #嵌套函数
        def decorator(*args):
            start_time=time.time()
            func(*args)
            stop_time=time.time()
            print('the running time of this function is %s'%(stop_time-start_time))
        return decorator        #返回函数名,不能带有括号
    @timer      #相当于test=timer(test),timer(test)返回decorator()函数。
    def test1():
        time.sleep(2)
        print('in the test1')
    @timer
    def test2(name,age):
        print('in the test2:', name, age)
    test1()
    test2('刚田武',22)
    输出:
    in the test1
    the running time of this function is 2.000319242477417
    in the test2: 刚田武 22
    the running time of this function is 0.0
    为函数增加计时功能
    username,password='zhhy','123'
    def auth(auth_type):
        print('auth type:',auth_type)
        def outer_wrapper(func):
            def wrapper(*args, **kwargs):
                print('wrapper args:',*args,**kwargs)
                if auth_type == 'local':
                    user_name = input('please input your name:').strip()
                    pass_word = input('please input your password:').strip()
                    if username == user_name and password == pass_word:
                        print('33[32;1mUser pass authentication33[0m ')
                        result = func(*args, **kwargs)
                        print('after authentication')
                        return result
                    else:
                        exit('33[32;1mInvalid username or password33[0m ')
                elif auth_type=='ldap':
                    print('using ldap')
            return wrapper
        return outer_wrapper
    def index():
        print('welcome to index page')
    @auth(auth_type='local')
    def home():
        print('welcome to home page')
        return 'from home'
    @auth(auth_type='ldap')
    def bbs():
        print('welcome to bbs page')
    home()
    View Code

    列表生成式:生成列表的简便方法。

    print([i*2 for i in range(10)])
    输出:
    [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
    

     i*2可以换成func()。

    生成器:generator=(i*2 for i in range(10))

    1、数据较多并且有规律时,可以减少内存占用,要调用的数据才会产生;

    2、不支持切片操作;

    3、只有__next__()方法;

    4、只保存当前调用数据。

    generator=(i*2 for i in range(10))
    print(generator.__next__())
    print(generator.__next__())
    输出:
    0
    2
    生成器

    斐波那契数列:

    def fib(max):
        n,a,b=0,0,1
        while n<max:
            a,b=b,a+b
            n+=1
        return b
    print(fib(10))
    

     其中,a,b=b,a+b相当于:

    tuple=(b,a+b)
    a=tuple[0]
    b=tuple[1]
    

    改为生成器:yield b

    def fib():
        a,b=0,1
        while True:
            yield b
            a,b=b,a+b
    f=fib()
    print(f.__next__())
    

     含有yield的函数称为生成器,生成器的return语句和函数的不同,其return的值赋给异常StopIteration,用try可以捕获异常,避免程序出错。

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

    函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行;

    for循环调用generator时,发现拿不到generator的return语句的返回值。如果想要拿到返回值,必须捕获StopIteration错误,返回值包含在StopIterationvalue中。

    def fib(max):
        n,a,b=0,0,1
        while n<max:
            yield b
            a,b=b,a+b
            n+=1
        return '---------done---------'
    f=fib(5)
    while True:
        try:
            # x=next(f)
            # print('f:',x)
            print(f.__next__())
        except StopIteration as e:
            print('生成器返回值:',e.value)
            break
    输出:
    1
    1
    2
    3
    5
    生成器返回值: ---------done---------
    

     yield可以在单线程环境中进行类似并行计算,称为协程。

    import time
    def consumer(name):     #不断吃包子
        print('[%s]来吃包子,'%name)
        while True:
            baozi=yield     #baozi的值由send()方法传来
            print('[%s]包子被[%s]吃了'%(baozi,name))
    def producer(name):
        a=consumer('刚田武')       #consumer是生成器,不会执行
        b=consumer('胖虎')
        a.__next__()        #调用next()后才会执行,consumer运行到baozi=yield处退出此生成器,等待send()方法传值。
        b.__next__()
        print('[%s]开始做包子'%name)
        for i in range(5):
            time.sleep(2)
            print("做了2个包子")
            a.send('白菜馅')       #send()传值给baozi后,a运行print('[%s]包子被[%s]吃了'%(baozi,name)),然后循环运行到baozi=yield跳出
            b.send('番茄馅')
    producer("朱二娃")
    输出:
    [刚田武]来吃包子,
    [胖虎]来吃包子,
    [朱二娃]开始做包子
    做了2个包子
    [白菜馅]包子被[刚田武]吃了
    [番茄馅]包子被[胖虎]吃了
    

     迭代器:

     可以直接作用于for循环的数据类型有以下几种:一类是集合数据类型,如listtupledictsetstr等;一类是generator,包括生成器和带yield的generator function。

    这些可以直接作用于for循环的对象统称为可迭代对象:Iterable

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

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

    生成器都是Iterator对象,但listdictstr虽然是Iterable,却不是Iterator,可以通过iter()函数获得一个Iterator对象。[http://www.cnblogs.com/alex3714/articles/5765046.html]

    from collections import Iterator
    from collections import Iterable
    print(isinstance([],Iterator))        #列表不是迭代器对象,返回False
    print(isinstance([],Iterable))        #列表是可迭代对象,返回True
    print(isinstance(iter([]),Iterator))        #iter()后的列表是可迭代对象,返回True
    输出:
    False
    True
    True
    

    json序列化和反序列化:可以把内存中的数据存储到硬盘中,便于下次从硬盘中读取数据,相当于把程序暂停。

    只能进行简单的数据类型序列化,可以在不同编程语言或者程序之间交互数据。

    import json
    info={"name":"刚田武",'age':20}
    f=open('test.text','w')
    print(json.dumps(info))
    f.write(json.dumps(info))
    序列化json.dumps()
    import json
    f=open('test.text','r')
    data=json.loads(f.read())
    print(data['name'])
    反序列化json.loads()

     pickle和json类似,优点是可以序列化所有数据类型,包括函数。序列化函数时,反序列化只能得到函数名,没有函数体,需要把函数体复制到反序列化中。可以更改函数体。

    import pickle
    def hello(name):
        print('hello,',name)
    info={'name':'刚田武','age':20,'func':hello}
    f=open('test.text','wb')
    f.write(pickle.dumps(info)) #pickle.dump(info,f)效果相同
    序列化pickle.dumps()
    import pickle
    def hello(name):
        print('hello,',name)
    f=open('test.text','rb')
    data=pickle.loads(f.read())     #data=pickle.load(f)
    data['func']('刚田武')
    反序列化pickle.loads()

    软件目录结构规范:层次清晰的目录结构规范有助于提高程序的可读性和可维护性。

    Foo/
    |-- bin/
    |   |-- foo
    |
    |-- foo/
    |   |-- tests/
    |   |   |-- __init__.py
    |   |   |-- test_main.py
    |   |
    |   |-- __init__.py
    |   |-- main.py
    |
    |-- docs/
    |   |-- conf.py
    |   |-- abc.rst
    |
    |-- setup.py
    |-- requirements.txt
    |-- README
    

    简要解释一下:

    1. bin/: 存放项目的一些可执行文件,当然你可以起名script/之类的也行。
    2. foo/: 存放项目的所有源代码。(1) 源代码中的所有模块、包都应该放在此目录。不要置于顶层目录。(2) 其子目录tests/存放单元测试代码; (3) 程序的入口最好命名为main.py
    3. docs/: 存放一些文档。
    4. setup.py: 安装、部署、打包的脚本。
    5. requirements.txt: 存放软件依赖的外部Python包列表。
    6. README: 项目说明文件。[https://www.cnblogs.com/alex3714/articles/5765046.html]

    从atm文件夹下的atm.py文件中调用core文件夹下的main.py的方法:

    import os,sys
    BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))    #找到程序的根目录
    sys.path.append(BASE_DIR)       #添加环境变量,BASE_DIR是当前程序的根目录,便于调用其他文件夹下的程序文件。
    from core import main
    from conf import setting
    main.login('刚田武')

    其中main.py为:

    def login(name):
        print('welcome to atm ,',name)
    

     输出为:

    welcome to atm , 刚田武
    
  • 相关阅读:
    杂谈
    P1441 砝码称重
    P3159 [CQOI2012]交换棋子
    P5200 [USACO19JAN]Sleepy Cow Sorting
    P5201 [USACO19JAN]Shortcut
    P5196 [USACO19JAN]Cow Poetry
    20190922UVA测试
    P4014 分配问题
    P4012 深海机器人问题
    P2050 [NOI2012]美食节
  • 原文地址:https://www.cnblogs.com/zhhy236400/p/9670829.html
Copyright © 2020-2023  润新知