python学习之路-4 内置函数和装饰器

本篇涉及内容

内置函数

装饰器

内置函数

  • callable()   判断对象是否可以被调用,返回一个布尔值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    num = 10
    print(callable(num))   # num不能够被调用,返回False
                 
    def f1():
        print("name")
                 
    print(callable(f1))     # f1可以被调用,返回True
                 
    # 输出
    False
    True
  • chr()   将十进制整数转换为ascii编码中对应的字符

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    num = chr(69# 整数69在ascii编码表中对应的是字母E
    print(num)
                  
    # 输出
    E
                 
                 
    # 练习
    # 利用ascii编码随机生成6位验证码
    import random
    li = []
    for i in range(6):
        r = random.randrange(0, 3)   # 生成随机数用来选择数字,小写字母或大写字母
                 
        if r == 0# 随机数字
            num = random.randrange(0, 10)
            li.append(str(num))
        elif r == 1:    # 随机大写字母
            temp = random.randrange(65, 91)    # 65-91在ascii表中对应的字符是A-Z
            c = chr(temp)       # 将十进制整数转换成为ascii表中对应的字符
            li.append(str(c))
        elif r == 2:    # 随机小写字母
            temp = random.randrange(97, 123)   # 97-123在ascii表中对应的字符是a-z
            c = chr(temp)   # 将十进制整数转换成为ascii表中对应的字符
            li.append(str(c))
                 
    result = "".join(li)
    print(result)
                 
    # 输出
    814P8i
  • ord()   将字符转换成ascii编码表中对应的十进制整数

    1
    2
    3
    4
    5
    st = ord("E")   # 字符E在ascii编码表中对应的十进制整数是69
    print(st)
                 
    # 输出
    69
  • dir()  # 查看一个对象有哪些功能

    1
    2
    3
    4
    print(dir(dict))
                 
    # 输出
    ['__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']
  • help() 查看对象的使用方法

    1
    2
    3
    4
    print(help(list))
                 
    # 输出
    输出内容太长,自己去试
  • divmod()   # 通过除数和被除数返回一个元组(商, 余数)  做分页比较有用

    1
    2
    3
    4
    5
    n = divmod(100, 9)
    print(n)
                 
    # 输出
    (11, 1)
  • isinstance() 判断对象是否是一个类的实例, 返回一个布尔值

    1
    2
    3
    4
    5
    6
    7
    8
    r = isinstance("abc", str)
    print(r)
    r = isinstance("abc", dict)
    print(r)
                 
    # 输出
    True
    False
  • enumerate()   用于遍历序列中的元素以及它们的下标

    1
    2
    3
    4
    5
    6
    7
    for i,j in enumerate(('a','b','c')):
        print(i,j)
                 
    # 输出
    0 a
    1 b
    2 c
  • filter(函数名, 可迭代对象)      调用函数,将可迭代对象中的每一个元素传给函数去执行,返回的结果为True则保留该元素,将保留的元素组成一个列表,将该列表作为返回值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    def f2(a):
        if a > 22:
            return True
    li = [11, 22, 33, 44, 55, 66]
    ret = filter(f2, li)
    print(list(ret))
                 
    # 输出
    [33, 44, 55, 66]
                 
                 
                 
    ## 使用lambda表达式
    f1 = lambda a: a > 30
    li = [11, 22, 33, 44, 55, 66]
    ret = filter(f1, li)
    print(list(ret))
                 
    # 输出
    [33, 44, 55, 66]
  • map(函数,可迭代对象)  调用函数,将可迭代对象中的每一个元素传给函数去执行,返回的结果组成一个列表,将该列表作为返回值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    def f2(a):
        return a + 100
    li = [11, 22, 33, 44, 55, 66]
    ret = map(f2, li)
    print(list(ret))
                 
    # 输出
    [111, 122, 133, 144, 155, 166]
                 
                 
    ## 使用lambda表达式
    f2 = lambda a: a + 100
    li = [11, 22, 33, 44, 55, 66]
    ret = map(f2, li)
    print(list(ret))
    # 输出
    [111, 122, 133, 144, 155, 166]
  • globals()  # 全局变量     locals()   # 局部变量

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    NAME = "aaa"
    def show():
        a = 123
        print(globals())
        print(locals())
    show()
                 
    # 输出
    {'__file__': 'D:/SVN/learning/s13/day4/class_code/2、内置函数.py', 'show': <function show at 0x00000000004BCBF8>, '__builtins__': <module 'builtins' (built-in)>, '__spec__': None, 'NAME': 'aaa', '__cached__': None, '__package__': None, '__loader__': <_frozen_importlib.SourceFileLoader object at 0x000000000276E7B8>, '__doc__': None, '__name__': '__main__'}
    {'a': 123}
  • hash()   通过hash计算出一个全数字的值

    1
    2
    3
    4
    5
    6
    s = "123"
    ret = hash(s)
    print(ret)
                 
    # 输出   pycharm执行有问题,这个值会变,在python命令提示符下执行没问题
    -5981999319787686991
  • len()   python2.7 字节长度  python3 字符长度

    1
    2
    3
    4
    5
    name = "张三"
    print(len(name))
                 
    # 输出
    2
  • bytes()  将字符转成字节

    1
    2
    3
    4
    5
    6
    name = "张聪"
    ret = bytes(name, encoding="utf-8")
    print(ret)
                 
    # 输出
    b'\xe5\xbc\xa0\xe8\x81\xaa'
  • max() 求最大值

    1
    2
    3
    4
    5
    r = max([11, 22, 33, 1])
    print(r)
                 
    # 输出
    33
  • min()  求最小值

    1
    2
    3
    4
    5
    r = min([11, 22, 33, 1])
    print(r)
                 
    # 输出
    1
  • sum()  求和

    1
    2
    3
    4
    5
    r = sum([11, 22, 33, 1])
    print(r)
                 
    # 输出
    67
  • pow()   求幂次方

    1
    2
    3
    4
    5
    r = pow(2, 10# 2的10次方
    print(r)
                 
    # 输出
    1024
  • reversed() 反转  和list的reversed()方法一样

    1
    2
    3
    4
    5
    6
    li = [1, 3, 4, 1, 53, 3, 5]
    ret = reversed(li)
    print(list(ret))
                 
    # 输出
    [5, 3, 53, 1, 4, 3, 1]
  • round()  四舍五入

    1
    2
    3
    4
    5
    6
    7
    8
    ret = round(1.8)
    ret2 = round(3.3)
    print(ret)
    print(ret2)
                 
    # 输出
    2
    3
  • slice()   跟切片的方法一样 没什么卵用,比切片还麻烦

    1
    2
    3
    4
    5
    6
    7
    8
    9
    myslice = slice(0,5,2)
    print(myslice)
                 
    l = list(range(10))
    print(l[myslice])
                 
    # 输出
    slice(0, 5, 2)
    [0, 2, 4]
  • sorted() 排序

    1
    2
    3
    4
    5
    6
    li = [1, 3, 4, 1, 53, 3, 5]
    ret = sorted(li)
    print(ret)
                 
    # 输出
    [1, 1, 3, 3, 4, 5, 53]
  • type() 查看对象类型

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    a = "abc"
    b = [1, 2, 3]
    c = {1: "a", 2: "b"}
    print(type(a))
    print(type(b))
    print(type(c))
                 
    # 输出
    <class 'str'>
    <class 'list'>
    <class 'dict'>
  • zip()  将多个列表的相对应的位置进行组合成一个元组,元组作为元素产生新的列表

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    l1 = [11, 12, 13, 14]
    l2 = [21, 22, 23, 24]
    l3 = [31, 32, 33, 34]
                 
    ret = zip(l1, l2, l3)
    print(list(ret))
                 
                 
    # 输出
    [(11, 21, 31), (12, 22, 32), (13, 23, 33), (14, 24, 34)]

装饰器

装饰器可以在不改变函数体和函数调用的情况下在该函数执行之前,或者执行之后进行额外的操作

装饰器的功能

  • 自动执行装饰器函数,并将被装饰函数的函数名当做参数传递给装饰器函数

  • 将装饰器函数的返回值,重新赋值给被装饰函数

装饰器之案例演变

  • 创建一个简单的函数,该函数的内容为输出nginx告警信息,该函数同时被A部门调用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    def print_nginx_log():
        """
        nginx服务器告警
        :return:
        """
        print("nginx server is down")
              
    print_nginx_log()
              
    # 输出
    nginx server is down
  • 新的需求来了,A部门说需要在输出告警之前和输出告警之后分别输出"即将告警"和"告警结束",然后我们对上面的代码做如下修改:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    def print_nginx_log():    # 直接在该代码中告警的前后添加代码
        """
        nginx服务器告警
        :return:
        """
        print("nginx即将告警")
        print("nginx server is down")
        print("nginx告警结束")
              
    print_nginx_log()
              
    # 输出
    nginx即将告警
    nginx server is down
    nginx告警结束
              
    ### 这个时候完成了A部门的需求,A部门老大很高兴,请我出去happy了一下
  • 新的问题出现了,A部门老大说你这个修改了原来函数的代码,有没有办法在不修改函数代码的基础上完成这个功能啊,思考半天,灵机一动,想到一个办法,代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    def new_func(func):   # 新添加一个函数,在该函数内去调用nginx告警函数,并在告警前后完成A部门的需求
        print("nginx即将告警")
        func()
        print("nginx告警结束")
              
              
    def print_nginx_log():
        """
        nginx服务器告警
        :return: None
        """
        print("nginx server is down")
              
    new_func(print_nginx_log)
              
    # 输出
    nginx即将告警
    nginx server is down
    nginx告警结束
              
    ## 代码改完,告诉他新的函数的名称,让他去修改代码调用的函数,使用new_func(print_nginx_log)进行调用就可以实现他说的那个功能,A思考了1秒钟,回答说:"fuck,你知道这样我需要改多少个地方么,我有n个位置调用了这个nginx告警函数,让我改不现实,赶紧想办法解决吧",然后我就开始各种百度,谷歌一顿狂搜,然后发现了装饰器这么个玩意
  • 总结了一下A部门老大的需求就是要想不改变函数调用方式的情况下去对原函数做扩展,然后就有了下面的装饰器:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    def new_func(func):
        """
        装饰函数
        :param func: 被装饰函数的函数名
        :return: func
        """
        print("nginx即将告警")
        func()
        print("nginx告警结束")
        return func
              
              
    @new_func
    def print_nginx_log():
        """
        nginx服务器告警
        :return: None
        """
        print("nginx server is down")
              
              
    # 输出
    nginx即将告警
    nginx server is down
    nginx告警结束

    上面代码流程详解:python学习之路-4 内置函数和装饰器

  • 使用了装饰器之后执行发现,我并没有调用函数,但是自己就执行了,这肯定不是我想要得结果,然后继续百度、谷歌。。。各种FQ各种搜最后,代码修改如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    def new_func(func):
        """
        装饰函数
        :param func: 被装饰函数的函数名
        :return: func
        """
        def inner():
            print("nginx即将告警")
            func()
            print("nginx告警结束")
        return inner
              
    @new_func
    def print_nginx_log():
        """
        nginx服务器告警
        :return:
        """
        print("nginx server is down")
              
    print_nginx_log()
              
    # 输出
    nginx即将告警
    nginx server is down
    nginx告警结束
              
    ### 从结果中看出,当调用nginx告警函数的时候,才会进行输出,完成了A部门老大的需求,于是他猛夸了我一番

    上面代码流程详解:

    python学习之路-4 内置函数和装饰器

  • 过了几天,A部门老大跑过来对我说:"你看能不能这样,这个只能够对nginx做告警,我现在需要对mysql也要做告警,你能不能在底层函数上面加一个参数,然后我把告警的信息当做参数给传进去",然后我又一顿狂搜,搞出来的代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    def new_func(func):
        """
        装饰函数
        :param func: 被装饰函数的函数名
        :return: func
        """
        def inner(value):
            print("nginx即将告警")
            func(value)
            print("nginx告警结束")
        return inner
              
    @new_func
    def print_nginx_log(value):
        """
        nginx服务器告警
        :return:
        """
        print(value)
              
              
    value = "mysql is down"
    print_nginx_log(value)
              
    # 输出
    nginx即将告警
    mysql is down
    nginx告警结束
              
    ### 这样就解决了A部门老大的需求了
  • 过了没几天,他又跑过来,说mysql告警的时候需要传多个参数,nginx告警只需要传一个参数,你看能否搞下,然后我又进入到狂搜的状态,最后搞出来代码如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    def new_func(func):
        """
        装饰函数
        :param func: 被装饰函数的函数名
        :return: func
        """
        def inner(*args, **kwargs):
            print("nginx即将告警")
            func(*args, **kwargs)
            print("nginx告警结束")
        return inner
              
    @new_func
    def print_nginx_log(*args, **kwargs):
        """
        nginx服务器告警
        :return:
        """
        print(*args, **kwargs)
              
              
    value = "mysql is down"
    k_value = {"time": 100}
    print_nginx_log(value, k_value)
              
    # 输出
    nginx即将告警
    mysql is down {'time': 100}
    nginx告警结束
              
    ### 这样就解决了A部门老大的需求,于是他又请我出去happy了一下^.^
  • 过了没两天又跑来找我,说底层函数没有返回值,我需要一个返回值,然后经过一顿的狂搜,搞到下面的代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    def new_func(func):
        """
        装饰函数
        :param func: 被装饰函数的函数名
        :return: func
        """
        def inner(*args, **kwargs):
            print("nginx即将告警")
            res = func(*args, **kwargs)
            print("nginx告警结束")
            return res
        return inner
              
    @new_func
    def print_nginx_log(*args, **kwargs):
        """
        nginx服务器告警
        :return:
        """
        print(*args, **kwargs)
        res = "ok"
        return res
              
              
              
    value = "mysql is down"
    k_value = {"time": 100}
    res = print_nginx_log(value, k_value)
    print(res)
              
    ### 输出
    nginx即将告警
    mysql is down {'time': 100}
    nginx告警结束
    ok
上一篇:RPC调用框架比较分析--转载


下一篇:luogu P1563 玩具谜题