• python之装饰器、生成器、内置函数、JSON


    一、装饰器:

    装饰器,器在这里的意思是函数,也就是装饰函数。作用是给其他函数添加新功能,它可以不改变原有的函数,原来的函数和原来一模一样,什么都不需要改变,只需要在函数外部加上调用哪个装饰器就可以了,装饰器的作用就是不改变原来函数的调用方式,不改变原来函数的代码,给它增加了一个新功能。但是不改变函数,给它增加新功能,那是不可能的,装饰器只不过是偷偷改变了原来的函数而已,而原来的函数不知不觉。

    学习装饰器前的知识储备:

    1、函数即变量,在python里面函数就是一个变量,函数名就是变量名,函数名里存着函数内存地址。它把函数体存在内存里,在调用的时候从函数名里面的内存地址来函数体运行这个函数。函数名后面加上小括号就是调用,只有函数名就是打印函数的内存地址。

    def test():
        int(input('please enter you age:'))
    test()
    print(test)

    运行结果:

    please enter you age:20
    <function test at 0x02A84270>

    2、高阶函数,如果函数的入参为函数的话,那么这个函数就是一个高阶函数。

    3、函数嵌套,函数嵌套就是在函数里再定义一个函数,而不是调用一个函数。

    def A(a):
        
        print("I am A")
        
        def B(b):
            
            print("a+b=", a+b)
            
            print("I am B")
            
        B(2)
        
        print("Over!!!")
        
    A(3)

    了解以上知识后,我们来写一个简单的装饰器,用来统计函数运行时间。

    
    
    import time


    def fun():
    time.sleep(3)
    print('in the fun')


    def test(func):
    start_time = time.time()
    func()
    stop_time = time.time()
    print('the func run time is %s' % (stop_time - start_time))


    test(fun)
     

    运行结果:

    1 in the fun
    2 the func run time is 3.007230520248413

    但是这样的话,我们每次都要将一个函数作为参数传递给test1函数。改变了函数调用方式,之前执行业务逻辑时,执行运行bar(),但是现在不得不改成test1(bar)。此时就要用到装饰器。我们就来想想办法不修改调用的代码;如果不修改调用代码,也就意味着调用bar()需要产生调用test1(bar)的效果。我们可以想到将test1赋值给bar,但是test1似乎带有一个参数……想办法把参数统一吧!如果test1(bar)不是直接产生调用效果,而是返回一个与foo参数列表一致的函数的话……就很好办了,将test1(bar)的返回值赋值给bar,然后,调用bar()的代码完全不用修改!

    import time
    
    def Time(fun):
    
        def deco():
    
            start_time = time.time()
    
            fun()
    
            stop_time = time.time()
    
            print('the func run time is :%s'%(stop_time - start_time))
    
        return deco
    @Time
    def dos():
    
        time.sleep(2)
    
        print('in the dos')
    
    dos()

    运行结果:

    in the dos
    the func run time is :2.0002448558807373

    这样,我们就提高了程序的可重复利用性,当其他函数需要调用装饰器时,可以直接调用。装饰器在Python使用如此方便都要归因于Python的函数能像普通的对象一样能作为参数传递给其他函数,可以被赋值给其他变量,可以作为返回值,可以被定义在另外一个函数内。

     1 import time
     2 
     3 def Timing(fun):
     4 
     5     def deco(*arg, **kwarg):
     6 
     7         start_time = time.time()
     8 
     9         fun(*arg, **kwarg)
    10 
    11         stop_time = time.time()
    12 
    13         print('the func run time is :%s'%(stop_time - start_time))
    14 
    15     return deco
    16 
    17 @Timing
    18 def tar(name, age):
    19 
    20     time.sleep(2)
    21 
    22     print('in the tar :', name, age)
    23 
    24 tar('hk', 18)

    运行结果:

    1 in the tar : hk 18
    2 the func run time is :2.000657081604004

     下面是用装饰器写的一个实例,逻辑是运行程序,打印菜单,如果选择后台管理和添加商品就判断是否登录,如果用户为登录就让用户登录;查看商品就不需要判断是否登录。

     1 import os
     2 def login():
     3     '''
     4     如果成功登录,就写入到user文件中
     5     :return:
     6     '''
     7     print('login')
     8     username = input('请输入账号:')
     9     password = input('请输入密码:')
    10     if username == 'admin' and password == '123456':
    11         print('登录成功!')
    12         with open('user', 'a+') as fw:
    13             fw.write(username)
    14     else:
    15         print('账号密码错误')
    16 
    17 def auth(func):
    18     def check(*args, **kwargs):
    19         if os.path.exists('user'):
    20             func(*args, **kwargs)
    21         else:
    22             print('未登录')
    23             login()
    24     return check
    25 @auth
    26 def admin():
    27     print('welcome!')
    28 
    29 def show():
    30     print('show!')
    31 
    32 @auth
    33 def add():
    34     print('add product')
    35 
    36 def menu():
    37     msg = '''
    38     1 : 后台管理
    39     2 : 查看商品
    40     3 : 添加商品
    41     '''
    42     print(msg)
    43     m = {
    44         "1": admin,
    45         "2": show,
    46         "3": add
    47     }
    48     choice = input('请输入你的选择:').strip()
    49     if choice in m:
    50         m[choice]()
    51     else:
    52         print('输入错误!')
    53         menu()
    54 if __name__ == '__main__':
    55     menu()

     二、生成器

    生成器是个什么东东?大概可以理解为一个迭代的对象,和list类似,不过生成器是用到这个里面的数据时它才会生成。生成器是按照某种规则生成的一个列表。所以不能像list那样,直接索引取值,必须知道前一个值,才能知道后面一个值。

    1、列表生成式

     list = [x*x for x in range(1,11)]
         
     print(list) 
    [1, 4, 6, 9, 25, 36, 49, 64, 81, 100]

    2、生成器(generator):要创建一个generator,只要把一个列表生成式的[]改成(),就创建了一个generator。

    g=(x*x for x in range(1,11))
    
    print(g)
    
    <generator object fib at 0x033FFE10>

    创建list和generator的区别就是外层的[]和(),打印generator需要使用next方法。

    g = (x*x for x in range(1,11))
    
    print(next(g))
    print(next(g))
    print(next(g))
    print(next(g))

    运行结果:

    1
    4
    9
    16

    generator保存的是算法,每次调用next(g),就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。可以使用for循环来迭代。而且不会担心Stopiteration错误。

    g = (x*x for x in rang(1, 11))
    
    for i in g:
    
        print(i)

    运行结果:

    1
    4
    9
    16
    25
    36
    49
    64
    81
    100

    对于比较复杂的算法,用类似列表生成式的for循环无法完成,这个时候可以使用函数来实现。

    def fib(num):
    
        n, a, b = 0, 0, 1
    
        while n < num:
        
            print(b)
    
            a, b = b, a+b
    
            n = n+1
    
        return 'done'
    
    f = fib(8)

    运行结果:

    1
    1
    2
    3
    5
    8
    13
    21

    上面函数和generator仅有的区别就是把print(b)变成yield b。

    def fib(num):
    
        n, a, b = 0, 0, 1
    
        while n < num:
    
            yield b
    
            a, b = b, a+b
    
            n = n+1
    
        return 'done'
    
    f = fib(8)
    
    for i in f:
         
        print(i)

    三、内置函数

    print(any([1, 'n', 3, 4, 0]))  # 判断可迭代的对象里面是否有一个为真
    print(all([1, 2, 3]))  # 判断可迭代对象里面的值知否都为真
    print(bin(108))  # 十进制转为二进制
    print(bool(0))  # 把一个对象转为布尔类型
    print(bool(1))   # 把一个对象转为布尔类型
    print(bytearray('ade', encoding='utf-8'))  # 把字符串变成一个可修改的bytes
    print(callable('s'))  # 判断传入的对象是否可调用
    print(chr(2))  # 数字对应的ASCII码
    print(ord('A'))  # 字符串对应的ASCII码
    print(dict(a=1, b=2))  # 转为字典
    print(dir(2))  # 打印传入对象的调用方法
    print(eval('[]'))
    print(exec('def a():pass'))
    print(filter(lambda x: x > 5, [12, 3, 12, 2, 1, 2, 25]))  # list里面迭代对象筛选方法为 x > 5
    print(map(lambda x: x > 5, [1, 2, 3, 4, 5, 6]))
    print(frozenset({1, 2, 3, 4}))  # 定义一个不可修改的集合
    print(globals())  # 返回程序内的全局变量
    print(locals())  # 返回程序的局部变量
    print(hash('abc'))  # 把一个字符串哈希成数字
    print(hex(123))  # 数字装换成16进制
    print(max(111, 222))  # 取最大值
    print(oct(12))  # 转换成8进制
    print(round(12.345, 2))   # 取2位小数
    print(sorted([1, 3, 4, 5, 2, 2, 10, 0, 23, 15]))  # 排序
    dic = {1: 2, 3: 5, 4: 4, 8: 3, 6: 2}
    print(sorted(dic.items()))  # 按字典key排序
    print(sorted(dic.items(), key=lambda x: x[1]))  # 按字典value排序
    __import__('os')

    运行结果:

    True
    True
    0b1101100
    False
    True
    bytearray(b'ade')
    False
    
    65
    {'a': 1, 'b': 2}
    ['__abs__', '__add__', '__and__', '__bool__', '__ceil__', '__class__', '__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__floor__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getnewargs__', '__gt__', '__hash__', '__index__', '__init__', '__init_subclass__', '__int__', '__invert__', '__le__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__round__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag', 'numerator', 'real', 'to_bytes']
    []
    None
    <filter object at 0x008028B0>
    <map object at 0x00802910>
    frozenset({1, 2, 3, 4})
    {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x006FA470>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'C:/Users/wgx/PycharmProjects/titled/group.py', '__cached__': None, 'a': <function a at 0x008042B8>}
    {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x006FA470>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'C:/Users/wgx/PycharmProjects/titled/group.py', '__cached__': None, 'a': <function a at 0x008042B8>}
    9703036
    0x7b
    222
    0o14
    12.35
    [0, 1, 2, 2, 3, 4, 5, 10, 15, 23]
    [(1, 2), (3, 5), (4, 4), (6, 2), (8, 3)]
    [(1, 2), (6, 2), (8, 3), (4, 4), (3, 5)]

    四、匿名函数

    匿名函数只可以执行一次,匿名函数只能处理简单的逻辑,不能写循环判断。匿名函数定义使用lambda关键字

    d = lambda x,y:x+y
    print(s(1,3)

    五、Json处理

    import json
    
    dic = {'name': '白夜行', 'author': '东野圭吾'}
    
    print(json.dumps(dic))  # 将字典转换成json串
    
    fw = open('a.json', 'w')
    
    json.dump(dic, fw)  # 将字典转换成json串病写到一个文件里
    
    s_json = '{"name": "hk", "age": 20, "status": true}'
    
    print(json.loads(s_json))  # 将json串转换成字典
    
    fr = open('b.json', 'r')
    
    print(json.load(fr))  # 从文件中读取json串并转换成字典

    运行结果:

    {"name": "u767du591cu884c", "author": "u4e1cu91ceu572du543e"}
    {'name': 'hk', 'age': 20, 'status': True}
    {'name': '白夜行', 'author': '东野圭吾'}
  • 相关阅读:
    pow()函数结果强制转化为int造成误差的分析
    warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
    博客园鼠标点击特效代码
    codeblocks更改颜色主题
    codeblocks1712设置中文
    SQl
    项目中nodejs包高效升级插件npm-check-updates
    正则表达式的整理(将金钱数变成带有千分位)
    从一个数组中过滤出另外一个数组中相关字段相等的数据
    IONIC3 打包安卓apk详细过程(大量图文)
  • 原文地址:https://www.cnblogs.com/wuxiaoyu-1537/p/7498796.html
Copyright © 2020-2023  润新知