• Python 装饰器、高阶函数、匿名函数、类


    1、装饰器

    给函数加点东西

     1 from functools import wraps
     2 
     3 def addstar(func):
     4     @wraps(func)      # functools实现的装饰器,目的是保留被装饰的函数原本的名字
     5     def diy_wrap():    # 自己定义的装饰器要的效果
     6         return '*** ' + func() + ' ***'
     7     return diy_wrap
     8 
     9 @addstar    # 使用自己定义的装饰器
    10 def hello():
    11     return 'hello python'
    12 
    13 print(hello())   # output: *** hello python ***
    14 
    15 # **************************************************************************
    16 # 带上参数
    17 def addstar(func):
    18     @wraps(func)      # functools实现的装饰器,目的是保留被装饰的函数原本的名字
    19     def diy_wrap(*args, **kwargs):    # 自己定义的装饰器要的效果
    20         res = func(*args, **kwargs)
    21         return '*** ' + res + ' ***'
    22     return diy_wrap
    23 
    24 @addstar    # 使用自己定义的装饰器
    25 def hello():
    26     return 'hello python'
    27 
    28 @addstar    # 使用自己定义的装饰器
    29 def hi(name):
    30     return 'hello ' + name
    31 
    32 @addstar    # 使用自己定义的装饰器
    33 def nihao(name1, name2):
    34     return 'hello ' + name1 + ' and ' + name2
    35 
    36 print(hello())   # output: *** hello python ***
    37 print(hi('Python'))
    38 print(nihao('Java', 'Go'))
    39 
    40 # **************************************************************************
    41 # 基于类的装饰器
    42 class Star():
    43     def __init__(self, func):
    44         self.func = func
    45 
    46     def __call__(self, *args, **kwargs):
    47         return '*** ' + self.func(*args, **kwargs) + ' ***'
    48 
    49 @Star
    50 def hh():
    51     return 'hhh'

    2、高阶函数

    map

     1 """
     2 map(函数,待处理数据列表)
     3 """
     4 l1 = list(map(str, [1,2,3,4]))
     5 print(l1)
     6 
     7 l2 = list(map(int, ['1', '2', '3', '4']))
     8 print(l2)
     9 
    10 def double(x):
    11     return 2 * x
    12 l3 = list(map(double, [1,2,3,4]))
    13 print(l3)
    14 
    15 l4 = list(map(lambda x: 2 * x, [1,2,3,4]))
    16 print(l4)

    reduce

    1 l1 = reduce(lambda x, y: x * y, [1, 2, 3, 4])
    2 print(l1)    # 返回 24
    3 l2 = reduce(lambda x, y: x * y, [1, 2, 3, 4], 5)
    4 print(l2)   # 返回 120
    5 l3 = reduce(lambda a, b: a if (a > b) else b, [5, 8, 1, 10])
    6 print(l3)   # 返回 10

    filter

    1 l1 = list(map(lambda x: x % 2 == 0, [1, 2, 3, 4, 5, 6]))
    2 print(l1)    # 返回 [False, True, False, True, False, True]
    3 l2 = list(filter(lambda x: x % 2 == 0, [1, 2, 3, 4, 5, 6]))
    4 print(l2)   # 返回 [2, 4, 6]
    5 l2 = list(filter(lambda x: x < 'i', 'hijack'))
    6 print(l2)   # 返回 ['h', 'a', 'c']

    3、匿名函数

    lambda

    匿名函数,代码块简短,如一行for或一行if

    list([lambda x: for x in range(10)])

    list([lambda x: for x in range(10) if x % 2 == 0])

    4、闭包

     1 """
     2 什么是闭包
     3 >一个函数返回了一个内部函数,该内部函数引用了外部函数的相关参数和变量,我们把该返回的内部函数成为闭包Closure
     4 闭包的作用
     5 >闭包的最大特点就是引用了自由变量,即使生成闭包的环境已经释放,闭包仍然存在
     6 >闭包在运行时可以有多个实例,即使传入的参数相同
     7 >利用闭包,我们还可以模拟类的实例
     8 小结
     9 >闭包是携带自由变量的函数,即使创建闭包的外部函数的生命周期结束了,闭包所引用的自由变量仍会存在
    10 >闭包在运行可以有多个实例
    11 >尽量不要在闭包中引用循环变量,或者后续会发生变化的变量
    12 """
    13 from math import pow
    14 
    15 def make_pow(n):
    16     def inner_func(x):
    17         return pow(x, n)
    18     return inner_func
    19 
    20 pow2 = make_pow(2)
    21 print(pow2(6))     # 返回 36.0

    5、partial

    当函数参数太多且有固定参数值时,可用partial函数

     1 """
     2 partial:固定函数参数,返回一个新的函数
     3 当函数参数太多,且某些参数固定时,可以使用functools.partial创建一个新的函数
     4 """
     5 
     6 from functools import partial
     7 
     8 def multiple(x, y):
     9     return x * y
    10 
    11 res = partial(multiple, y=2)
    12 print(res(x=3))    # 3 * 2 = 6
    13 print(res(x=4))
    14 print(res(x=5))
    15 
    16 res = partial(multiple, x=3)
    17 print(res(y=4))    # 3 * 4 = 12
    18 print(res(y=5))
    19 print(res(y=6))
    20 
    21 def new_math(x, y, z):
    22     return str(x + y) + z
    23 
    24 res = partial(new_math, z='')
    25 print(res(2,3))    # 5元
    26 print(res(4,5))    # 9元

    6、类 / 方法

    类方法和静态方法

     1 """
     2 静态方法没有self和cls参数,可以把它看成是一个普通的函数
     3 """
     4 
     5 class A():
     6     bar = 1
     7 
     8     @classmethod
     9     def class_foo(cls):   # 类方法
    10         print('hello, ', cls)
    11         print(cls.bar)
    12 
    13     @staticmethod
    14     def static_foo():    # 静态方法
    15         print('hello, ', A.bar)
    16 
    17 A.class_foo()   # hello,  <class '__main__.A'>   1
    18 
    19 a = A()
    20 a.static_foo()    # hello,  1
    21 
    22 A.static_foo()   # hello,  1

    魔法函数(也叫特殊方法)

     1 """
     2 魔法函数也叫特殊方法
     3 
     4 创建一个类的实例时,类会先调用__new__(cls[, ...])来创建实例,然后__init__方法再对该实例(self)进行初始化
     5 注意事项:
     6 ·__new__是在__init__之前被调用的
     7 ·__new__是类方法,__init__是实例方法
     8 ·重载__new__方法,需要返回类的实例
     9 一般情况下,我们不需要重载__new__方法。但在某些情况下,我们想控制实例的创建过程,这时可以通过重载__new__方法来实现
    10 """
    11 class A():
    12     _dict = dict()
    13 
    14     def __new__(cls):
    15         """
    16         重载__new__方法
    17         """
    18         if 'key' in A._dict:
    19             print('Exists')
    20             return A._dict['key']
    21         else:
    22             print('New')
    23             return object.__new__(cls)   # 不存在则创建实例
    24 
    25     def __init__(self):
    26         print('Init')
    27         A._dict['key'] = self
    28 
    29 a1 = A()   # 第一次调用,不存在
    30 a2 = A()    # 后面调用就已经存在了
    31 a3 = A()

    str 和 repr

     1 """
     2 str & repr
     3 在类中加上repr方法,直接实例化类也能输出__str__的值,区别看最后两行注释
     4 """
     5 class Foo():
     6     def __init__(self, name):
     7         self.name = name
     8 
     9     def __str__(self):
    10         return self.name
    11 
    12     def __repr__(self):    #  可用 __repr__ = __str__  替换
    13         return self.name
    14 
    15 
    16 f = str(Foo('hi'))   # 输出hi
    17 print(type(f))   # <class 'str'>
    18 
    19 f1 = Foo('hi')      # 输出hi
    20 print(type(f1))   # <class '__main__.Foo'>
    21 
    22 Foo('hi')   # 加上__repr__方法,直接使用Foo('hi')也能输出name了
    23 
    24 l = []
    25 l.append(Foo('hh'))
    26 print(l)   # 没有__repr__的输出 [<__main__.Foo object at 0x0000021246BD7FD0>]
    27            # 有__repr__的输出 [hh]

    7、property

    property装饰器,可以将被装饰的方法当做属性来用。

    下面示例:score方法被property装饰成一个属性,另一个score被@score.setter装饰成用来赋值的属性。

     1 class Exam(object):
     2     def __init__(self, score):
     3         self._score = score
     4 
     5     @property
     6     def score(self):
     7         return self._score
     8 
     9     @score.setter
    10     def score(self, val):
    11         if val < 0:
    12             self._score = 0
    13         elif val > 100:
    14             self._score = 100
    15         else:
    16             self._score = val
    17 
    18 
    19 e = Exam(60)
    20 print(e.score)
    21 e.score = 90
    22 print(e.score)

    只用@property,不用@score.setter,这是score方法是一个只读属性,虽然能正常输出,但有提示。

     1 class Exam(object):
     2     def __init__(self, score):
     3         self._score = score
     4 
     5     @property
     6     def score(self):
     7         return self._score
     8 
     9     def score(self, val):   # 提示:Redeclared 'score' defined above without usage 
    10         if val < 0:
    11             self._score = 0
    12         elif val > 100:
    13             self._score = 100
    14         else:
    15             self._score = val
    16 
    17 
    18 e = Exam(60)
    19 print(e.score)
    20 e.score = 90    # 在Python 3.8中,依然能输出90这个值,但有黄色提示
    21 print(e.score)

    如果不用@property装饰器,可以用get和set方法

     1 class Exam(object):
     2     def __init__(self, score):
     3         self._score = score
     4 
     5     def get_score(self):
     6         return self._score
     7 
     8     def set_score(self, val):
     9         if val < 0:
    10             self._score = 0
    11         elif val > 100:
    12             self._score = 100
    13         else:
    14             self._score = val
    15 
    16 
    17 e = Exam(60)
    18 print(e.get_score)
    19 e.set_score = 90
    20 print(e.get_score)

    打印输出是 <bound method Exam.get_score of <__main__.Exam object at 0x0000012711598400>>

  • 相关阅读:
    linux目录特殊权限 t :禁止删除(粘滞)权限
    牛X 好用的sshd_config:ChrootDirectory:特别注意【该目录必须是只能且仅能root用户有w权限!】
    mysql FIND_IN_SET 尝试性优化
    Java base64 添加data URI
    【java】itext5 添加页眉页脚
    【java】一些图片印章的处理方法
    授权MySQL root 用户所有权限
    法学 五院四系
    最具投资前景
    JCL ABEND CODE
  • 原文地址:https://www.cnblogs.com/sue2015/p/16140722.html
Copyright © 2020-2023  润新知