当前位置: 首页 > news >正文

专业网站设计学校企业营销型网站建设厂家

专业网站设计学校,企业营销型网站建设厂家,企业建站源代码,专业深圳网站建设Python编程-浅析装饰器原理与装饰器设计模式和函数式编程案例讲解 本文制作时基于Python3.11.8与Python3.12.1#xff0c;存在谬误#xff0c;请联系修改#xff0c;希望对你有所帮助 什么是函数式编程 函数式编程#xff08;Functional Programming#xff09;是一种编程…Python编程-浅析装饰器原理与装饰器设计模式和函数式编程案例讲解 本文制作时基于Python3.11.8与Python3.12.1存在谬误请联系修改希望对你有所帮助 什么是函数式编程 函数式编程Functional Programming是一种编程范式它将计算视为数学函数的计算并避免了状态改变以及可变数据。在函数式编程中函数被视为一等公民意味着它们可以像其他数据类型一样被传递、返回和操作。 以下是函数式编程的一些主要特征 纯函数Pure Functions纯函数指的是函数的输出仅由输入决定不会对外部状态产生影响也不依赖外部状态。相同的输入总是产生相同的输出这种特性使得纯函数易于理解、测试和并行化。 不可变性Immutability在函数式编程中数据是不可变的即一旦创建就不可更改。这意味着一旦数据被创建就不能被修改而是通过创建新的数据来代替。 无副作用Side-effect free函数式编程尽量避免副作用即对系统外部环境造成的影响。这意味着函数不会修改外部状态包括修改全局变量、执行 I/O 操作等。 高阶函数Higher-order Functions函数式编程支持高阶函数即函数可以作为参数传递给其他函数或者从其他函数返回。 递归Recursion递归是函数式编程中常见的一种迭代方式用于替代循环。 惰性计算Lazy Evaluation函数式编程支持惰性计算即只有在需要时才会计算表达式的值这种特性在处理无限数据结构时特别有用。 函数式编程的优势包括代码简洁、可读性强、易于测试和并行化。它在处理并发编程、大数据处理、分布式系统等方面具有很好的适用性。常见的函数式编程语言包括Haskell、Clojure、Scala、Erlang等。此外现代编程语言如Python、JavaScript和Java等也提供了一些函数式编程的特性和支持。 什么是高阶函数 在Python中函数名可以作为参数进行传递例如多线程中的方法包装 def function_name():passthread Thread(targetfunction_name)由于函数名可以作为一个参数进行传递于是python中存在将一个函数传递给另一个函数的函数被称为高阶函数 def print_hello(hint_string) - None:print(Hello hint_string)def start_func(other_func) - None:other_func(World)start_func(print_hello)上述的start_func即为高阶函数这个和PHP是较为类似的也可以理解为C语言中的函数指针 高阶函数匿名函数使用案例 Lambda 表达式是 Python 中的一种匿名函数它允许快速定义简单的函数而不需要使用 def 定义函数的形式。Lambda 表达式的语法如下 lambda arguments: expression其中 lambda关键字表示定义 lambda 表达式。arguments函数的参数可以是零个或多个参数与普通函数一样但不允许使用默认参数值或可变参数。expression函数体表示函数的返回值。 Lambda 表达式通常用于需要一个函数作为参数的情况比如在高阶函数中例如 map()、filter()、sorted() 等函数中或者在需要临时定义一个简单函数的地方。 例如使用 Lambda 表达式定义一个简单的函数计算两个数的和 add lambda x, y: x y print(add(3, 4)) # 输出7高阶函数map使用案例 map函数接收一个函数名和一个或多个可迭代对象返回的是一个map对象并且map对象实现了可迭代协议 def calculate_func(num: int) - int:return abs(num) ** 2num_list: list[int] [1, 2, 4, -5, -9]res_list: list[int] list(map(calculate_func, num_list))print(res_list)for i in map(calculate_func, num_list): # 借助可迭代协议进行迭代的方式print(i)在上述操作中map函数会将可迭代对象的每个元素逐个递交由第一个参数所指定的函数进行处理然后返回一个map对象供我们操作 并且需要注意的是除了第一个参数指定为函数名后面的可迭代对象的参数将逐个以位置形参的形式传递给函数名 def calculate_func(list1_var: int, list2_var: int) - int:return list1_var list2_varnum_list1: list[int] [1, 2, 4, -5, -9] num_list2: list[int] [1, 7, 4, -6, -9]res_list: list[int] list(map(calculate_func, num_list1, num_list2))print(res_list)高阶函数reduce使用案例 位于functools中的reduce接收三个参数第一个参数必须为两个参数的函数名第二个参数必须是一个可迭代的对象第三个参数用于指定初始值它是一个可选值未指定值时时使用可迭代对象的第一个参数为基准指定后则以指定的值为基准值。reduce函数用来将函数运算的结果进行累计即将函数运算的结果累计作为下一次运算的第一个参数可迭代对象的下一个值将自动作为第二参数继续运算直到可迭代对象迭代结束。 from functools import reducedef calculate_func(num1: int, num2: int) - int:return num1 num2num_list: list[int] [1, 8, 4, -5, -9]res_list: int reduce(calculate_func, num_list)print(res_list)在上述代码中未指定初始值基准为传入列表的第一个值作为基准进入函数作为第一参数运算时列表的第二个元素作为函数的第二参数下面我们看指定初始值的情况,我这里使用了lambda表达式 from functools import reducenum_list: list[int] [1, 8, 4, -5, -9]res: int reduce(lambda x, y: xy, num_list, 25)print(res)高阶函数filter的使用案例 filter() 是 Python 中的一个内置函数用于过滤序列列表、元组、集合等中的元素。filter() 函数接受一个函数和一个可迭代的序列作为参数并返回一个由符合条件的元素组成的迭代器。该函数在每次迭代时都会将序列中的元素传递给指定的函数如果函数返回值为 True则该元素将被保留否则将被过滤掉。 from functools import reducedef is_pos_neg_num(num: int) - bool:if num 0 :return Trueelse :return Falsenum_list: list[int] [1, 8, 4, -5, -9, 5, -8]res list(filter(is_pos_neg_num, num_list))print(res)还可以用来过滤字符串中的值这里以去除空格为例 from functools import reduceoriginal_string Hello World Python Java CPPres: str .join(list(filter(lambda x: False if x else True, original_string)))print(res)高阶函数sorted使用案例 sorted() 是 Python 中的一个内置函数用于对可迭代对象进行排序操作。它接受一个可迭代对象作为参数并返回一个新的已排序的列表sorted还有两个关键字参数 key可选用于指定排序的比较函数。默认为 None表示直接对元素进行比较排序。如果指定了 key则 sorted() 函数将会以 key 函数的返回值作为排序的依据。reverse可选指定排序的顺序如果设置为 True则降序排序如果设置为 False默认值则升序排序。 words [banana, apple, orange, grape, kiwi]res sorted(words, keylen, reverseTrue)print(res)如上示例我们以指定以字符串长度为比较依据并且置为逆序 高阶函数偏函数使用案例 Python 中的偏函数Partial Function是指使用 functools.partial 函数对现有函数创建一个新的函数固定该函数的部分参数。在需要多次调用同一个函数但又希望保持某些参数不变的情况下非常有用使用函数默认值也可以实现。 from functools import partialdef get_greeting(name, sentence):return Hello!!! str(name) , str(sentence)get_greeting_default partial(get_greeting, sentenceYou are the real IKUN)print(get_greeting_default(kun)) print(get_greeting_default(kunkun))使用此方法更多时候是需要重写自己不方便修改的部分例如在使用bytes对象转换时需要使用指定编码时或使用int时指定转换进制 gbk_bytes partial(bytes, encodinggbk) binary_int partial(int, base2)高阶函数闭包函数与使用案例 闭包Closure是函数式编程中的一个重要概念闭包实质上也是一种高阶函数也在 Python 中得到了支持。闭包指的是一个函数对象该函数可以访问并操作其创建时所在的作用域中的变量即使这些变量在函数被调用之后已经不存在了。在 Python 中闭包通常由内部函数和外部函数组成。内部函数可以访问外部函数中定义的变量一般定义闭包就是需要访问外部函数的变量或参数即使外部函数已经执行完毕并且不再存在。 def outer_function(x):def inner_function(y):return x yreturn inner_functionclosure outer_function(5) print(closure(3))在这个示例中outer_function 是外部函数它接受一个参数 x。内部函数 inner_function 可以访问外部函数 outer_function 中的变量 x。当调用 outer_function(5) 后它返回了一个闭包 closure此时 x 被赋值为 5。当调用 closure(3) 时内部函数 inner_function 访问了外部函数中的变量 x并且将 3 加上了 x得到了 8。 闭包的优点之一是它可以保持外部函数的状态这使得它允许函数在每次调用时记住它所处的上下文并且可以在之后的调用中使用这个上下文。 需要注意的是闭包可能会导致内存泄漏因为闭包中引用的外部变量会被保留即使它们不再被使用。因此应该小心使用闭包并确保在不需要时适时释放资源。 利用闭包求解任意点到固定点之间的距离 from typing import Callable import mathdef set_fixed_point(x1, y1) - Callable[[int, int], float]:def get_distance(x2, y2) - float:return math.sqrt((x1 - x2)**2 (y1 - y2)**2)return get_distancedistance set_fixed_point(0, 0) print(distance(2, 2))多个内部函数闭包使用案例 Python允许在一个函数中创建多个内部函数。在 Python 中函数是一级对象因此可以像任何其他对象一样在函数内部进行定义、传递和返回。需要注意的是每个内部函数都会占用内存空间如果定义了大量的内部函数可能会导致内存占用过多。 当在一个函数中定义了多个内部函数时可以通过调用外部函数来获取对应的内部函数。每个内部函数在外部函数被调用时都会重新创建因此每次调用外部函数都会得到新的内部函数实例并且它们之间是相互独立的互不影响。 def outer_function():def inner_function1():return This is inner function 1def inner_function2():return This is inner function 2return inner_function1, inner_function2# 调用外部函数获取内部函数 func1, func2 outer_function()# 分别调用内部函数 print(func1()) print(func2()) 在这个示例中outer_function 中定义了两个内部函数 inner_function1 和 inner_function2。通过调用 outer_function我们得到了对应的内部函数实例 func1 和 func2。然后我们可以像普通函数一样调用这些内部函数。 多重闭包函数使用案例 既然闭包允许函数并列成为内部函数自然套娃也是可以的 def outer_function():def inner_function1():def inner_function2():print(This is inner function 2)print(This is inner function 1)return inner_function2return inner_function1func1 outer_function() func2 func1() func2()这一点在多重装饰器上将会体现出来 使用闭包添加新的功能 在项目维护与功能添加中如果要获取一些关键节点的信息直接修改已有的项目代码显然是不够方便的此时我们可以使用闭包来更新功能 from typing import Callable from time import asctimedef running_function() - str:print(This is running function)def create_logs(func: Callable) - None:with open(log.txt, a, encodingutf-8) as file:file.write(str(func.__name__) asctime() \n)def outer_function(func) - Callable[[None], str]:def inner_function() - None:create_logs(func)func()return inner_functionfunc_start outer_function(running_function)()在 Python 中__name__ 是一个特殊的内置变量它用于获取当前模块的名称。当 Python 文件作为主程序直接执行时__name__ 的值为 __main__而当 Python 文件被导入为模块时__name__ 的值为该模块的名称。这个特性常用于将一些代码块标记为主程序或模块中的一部分以便在需要时能够灵活地执行或导入模块而不会对整个脚本产生副作用。 需要注意的是__name__可以用于获取当前模块的名称但不仅限于获取模块名称还可以用于其他一些情况如获取函数名等。t下面是用于模板渗透时的常见方式 获取内容使用方法模块名__name__函数名function.__name__类名self.__class__.__name__方法名method.__name__类的模块名self.__module__ 闭包函数的作用域特性 闭包函数的作用域问题是指内部函数闭包函数可以访问外部函数的变量而外部函数无法直接访问内部函数的变量。这种作用域链的特性使得闭包函数可以在其定义时捕获外部作用域的变量并在稍后的调用中保持对这些变量的引用。 具体来说当内部函数引用外部函数的变量时Python 解释器会在内部函数的作用域中查找这些变量。如果在内部函数的作用域中找不到对应的变量则会继续向上一级作用域查找直到找到或者到达全局作用域。这样就形成了闭包函数可以访问外部函数作用域中的变量的效果。闭包函数的作用域具有以下几个特点 **捕获外部变量**闭包函数可以在其定义时捕获外部作用域的变量并在稍后的调用中保持对这些变量的引用即使外部函数已经执行完毕这些变量依然存在于闭包函数的作用域中。 **保持状态**由于闭包函数可以访问外部函数作用域中的变量并且这些变量在闭包函数调用之间保持不变因此闭包函数可以用来实现状态的保持例如计数器、缓存等。 **避免全局污染**使用闭包函数可以避免将变量声明为全局变量从而减少了全局作用域的变量污染和命名冲突的可能性。 即闭包中的内部函数中的字段对于外部是不可见的内部函数却可以捕获外面的字段这保证了内部数据的完整性不过需要注意的是内部函数一般不用于修改外部内容 编程语言中的的对象级别 在 Python 中常见的对象级别大致上可以分为两个实质上并无明确规定 一级对象的特征 一级对象First-class object是指在编程语言中能够作为普通对象使用的实体。具有一级对象特性的对象可以被传递给函数、存储在变量中、作为函数的返回值、放在数据结构中等。在 Python 中函数、类、模块、数字、字符串、列表、字典等都是一级对象。 可赋值性Assignability一级对象可以被赋值给变量并且可以存储在数据结构中。作为函数参数Passability as arguments一级对象可以作为函数的参数传递给其他函数。作为函数返回值Returnability from functions一级对象可以作为函数的返回值返回给调用者。可以存储在数据结构中Storability in data structures一级对象可以被存储在列表、字典、集合等数据结构中。 二级对象的特征 二级对象通常指的是某些限制了一定程度使用和支持的对象在一些编程语言中二级对象可能不能作为函数的参数、返回值或存储在数据结构中或者有其他限制。在 Python 中常见的二级对象可能是一些特殊的内置类型或对象例如文件对象、生成器对象等它具有以下特点: 部分支持作为函数参数和返回值某些对象可能不支持作为函数的参数或返回值或者只能作为参数而不能作为返回值。部分支持存储在数据结构中某些对象可能不能被直接存储在数据结构例如列表、字典中或者只能在特定的上下文中存储。有限的操作和功能某些对象可能只支持有限的操作和功能而不能像一级对象那样支持全部的操作。具有特定的使用限制或约束某些对象可能有特定的使用限制或约束可能需要满足特定的条件才能使用或进行操作。 装饰器的概念与自定义方式 装饰器Decorator是一种Python语法特性它允许在不修改原始函数或类定义的情况下动态地添加功能或修改其行为。装饰器本质上是一个函数它期望接受一个函数作为输入并返回一个新的函数作为输出。需要注意的是装饰器函数必须定义在被装饰的函数被之前 装饰器通常用于以下几个方面 **代码重用**可以使用装饰器将一些通用的功能分离出来并将其应用于多个函数或方法从而实现代码重用。 **日志记录**通过装饰器可以在函数执行前后添加日志记录功能记录函数的调用时间、参数、返回值等信息。 **权限检查**装饰器可以用于检查用户权限例如验证用户是否具有执行特定函数的权限。 **性能测试**可以使用装饰器来测量函数的执行时间以便进行性能分析和优化。 **异常处理**装饰器可以用于捕获函数中的异常并进行适当的处理或记录。 装饰器的语法使用 符号将装饰器函数放在被装饰函数之前。例如 def my_decorator(function):def wrapper():print(Something is happening before the function is called.)function()print(Something is happening after the function is called.)return wrappermy_decorator def say_hello():print(Hello! World)say_hello()在上面的例子中say_hello 函数被 my_decorator 装饰器修饰当调用 say_hello 函数时实际上是调用了装饰器中的 wrapper 函数从而实现了在函数执行前后添加额外的功能。 装饰器与闭包的关系 装饰器和闭包在 Python 中常常一起使用它们之间有一定的联系但也有一些区别。下面是它们之间的关系 **装饰器使用闭包**装饰器本质上是一个接受函数作为参数并返回一个新函数的函数。通常情况下装饰器内部会定义一个嵌套函数也就是闭包在这个闭包中可以访问外部函数的变量和参数。这个闭包函数通常用来包装原始函数以便添加额外的功能。 **闭包不一定是装饰器**闭包是指内部函数可以访问外部函数的作用域形成了一个封闭的作用域。闭包并不一定与装饰器结合使用它可以用于各种目的如延迟执行、保存状态等。 **装饰器提供了一种更方便的语法来使用闭包**使用装饰器可以更方便地将闭包应用于函数上而不需要显式地调用闭包函数。装饰器的语法简洁明了更符合 Pythonic 风格。 **装饰器可以串联使用多个闭包**由于装饰器可以叠加使用一个函数可以被多个装饰器修饰这样就形成了多个闭包嵌套的情况这为函数添加多个不同的功能提供了便利。 装饰器的执行逻辑 从装饰器的概念来讲本质上是闭包函数多了一个自动执行的过程。即使我们不执行传递进入的函数不过被返回的内部函数将会在返回后被执行正如下面的代码 def decorator(func):print(This function is started: , decorator.__name__)def inner_func1():print(This function is started: , inner_func1.__name__)return inner_func1decorator def func():print(This function is started: , func.__name__)func()我们将的到如下运行结果 This function is started: decorator This function is started: inner_func1即装饰器的实质调用链在此为decorator(func)()我们去掉print内容再来观察进行装饰时Python虚拟机的字节码 2 2 LOAD_CONST 0 (code object decorator at 0x0000023D0A57D7C0, file string, line 2)4 MAKE_FUNCTION 06 STORE_NAME 0 (decorator)7 8 LOAD_NAME 0 (decorator)8 10 LOAD_CONST 1 (code object func at 0x0000023D0A355470, file string, line 7)12 MAKE_FUNCTION 07 14 PRECALL 018 CALL 08 28 STORE_NAME 1 (func)Python虚拟机依次进行了以下操作 LOAD_CONST: 将常量加载到栈顶。在这里常量 code object decorator at 0x0000023D0A57D7C0, file string, line 2 被加载到栈顶。MAKE_FUNCTION: 使用栈顶的常量创建一个函数对象并将其推送到栈顶。在这里栈顶的常量是之前加载的 code object decorator at 0x0000023D0A57D7C0, file string, line 2。STORE_NAME: 将栈顶的函数对象存储到名为 “decorator” 的变量中。LOAD_NAME: 将名为 “decorator” 的变量加载到栈顶。LOAD_CONST: 再次加载一个常量到栈顶。在这里常量 code object func at 0x0000023D0A355470, file string, line 7 被加载到栈顶。MAKE_FUNCTION: 创建一个函数对象并将其推送到栈顶。与之前类似栈顶的常量是 code object func at 0x0000023D0A355470, file string, line 7。PRECALL: 进行函数调用之前的预调用操作。CALL: 执行函数调用操作。STORE_NAME: 将函数调用的结果存储到名为 “func” 的变量中。 则我们可以得出结论在上述的代码中 decorator实质上执行的过程为在定义函数时执行了类似于func decorator(func)的操作 多重装饰器包装方法 使用多个装饰器进行包装时直接在被包装函数前以多个进行引入即可如下示例 def my_decorator_one(function):def wrapper_one():print(Something is happening before the function is called., ---by decorator one)function()print(function.__name__ is started)print(Something is happening after the function is called., ---by decorator one)return wrapper_onedef my_decorator_two(function):def wrapper_two():print(Something is happening before the function is called., ---by decorator two)function()print(function.__name__ is started)print(Something is happening after the function is called., ---by decorator two)return wrapper_twomy_decorator_one my_decorator_two def say_hello():print(Hello! World)say_hello()需要注意的是运行后的结果 Something is happening before the function is called. ---by decorator one Something is happening before the function is called. ---by decorator two Hello! World say_hello is started Something is happening after the function is called. ---by decorator two wrapper_two is started Something is happening after the function is called. ---by decorator one可见程序是先执行的第一个装饰器然后将第二个装饰器作为了第一个装饰器装饰的方法然后第二装饰器装饰了被包装方法即出现了嵌套的装饰器即多重闭包 包装需要参数的函数或方法 与定义闭包函数时是类似的我们要想包装需要参数的方法或函数只需要将装饰器内部的函数定义为接收对应参数数量即可 def decorator(function):def inner_function(*args):print(This is inner of decorator)function(*args)return inner_functiondecorator def connect_two_string(string1, string2):print(string1 string2)connect_two_string(Hello, World!!!)向装饰器传递额外的参数 不难看出装饰器的本质上依然是闭包函数那么既然是函数我们就可以为其传递参数并在其中使用参数或进行更加复杂的操作 def decorator(*call_word):print(decorator.__name__ is started)def inner_function(function):print(inner_function.__name__ is started)def core_function(*args):print(core_function.__name__ is started)function(*args)print(inner_function.__name__ str(call_word))return core_functionreturn inner_function decorator(Welcome to Python!!!) def connect_two_string(string1, string2):print(string1 string2)connect_two_string(Hello, World!!!) 运行结果如下 decorator is started inner_function is started inner_function (Welcome to Python!!!,) core_function is started HelloWorld!!!即在我们需要在装饰器使用额外的数据时我们需要使用多重闭包在第一层闭包中返回一个装饰器所以上述代码的调用链应该是这样的 decorator(Welcome to Python!!!)(connect_two_string)(Hello, World!!!)字节码中也是这样操作的 0 0 RESUME 02 2 LOAD_CONST 0 (code object decorator at 0x000002D462405F00, file string, line 2)4 MAKE_FUNCTION 06 STORE_NAME 0 (decorator)14 8 PUSH_NULL10 LOAD_NAME 0 (decorator)12 LOAD_CONST 1 (Welcome to Python!!!)14 PRECALL 118 CALL 115 28 LOAD_CONST 2 (code object connect_two_string at 0x000002D462411C50, file string, line 14)30 MAKE_FUNCTION 014 32 PRECALL 036 CALL 015 46 STORE_NAME 1 (connect_two_string)18 48 PUSH_NULL50 LOAD_NAME 1 (connect_two_string)52 LOAD_CONST 3 (Hello)54 LOAD_CONST 4 (World!!!)56 PRECALL 260 CALL 270 POP_TOP72 LOAD_CONST 5 (None)74 RETURN_VALUE在进行装饰的过程中多了一步12 LOAD_CONST 1 (Welcome to Python!!!)而后在闭包的第二层也就是装饰器所在处执行了以下内容返回了一个装饰器 15 28 LOAD_CONST 2 (code object connect_two_string at 0x000002D462411C50, file string, line 14)30 MAKE_FUNCTION 014 32 PRECALL 036 CALL 015 46 STORE_NAME 1 (connect_two_string)装饰器的嵌套行为 既然闭包都能嵌套那么装饰器不能进行嵌套可太不合理了不过这样可能会引起代码逻辑过于混乱不建议尝试有时显得低效且冗余 def decorator_one(func):def inner_func(x, y):func(abs(x), abs(y))return inner_funcdef decorator_two(func):decorator_onedef inner_func(x, y):func(x-1, y-1)return inner_funcdecorator_two def sum(x, y):print(xy)sum(-6, 6)实现智能装饰器案例讲解 经过上述的内容我们会注意到一个问题装饰器大致分为三种调用情况 decorator # 直接装饰函数 decorator() # 装饰器本身使用了参数默认值 decorator(..., ...) # 装饰器传递了所有或合法参数怎样实现在三种情况下都可以使用同一个装饰器来进行装饰呢其实智能装饰器就是实现了情况判断的闭包函数 def decorator(*args, **kwargs):# 处理装饰器参数if len(args) 1 and callable(args[0]): func args[0]def wrapper(*func_args, **func_kwargs):print(# * 20)result func(*func_args, **func_kwargs)print(# * 20)return resultreturn wrapperelse:# 如果装饰器本身使用了参数默认值或传递了参数则在这里处理def actual_decorator(func):def wrapper(*func_args, **func_kwargs):print(- * 20)print(Decorator args:, args)print(Decorator kwargs:, kwargs)result func(*func_args, **func_kwargs)print(- * 20)return resultreturn wrapperreturn actual_decorator# 使用装饰器来装饰函数 decorator def function():print(Inside function)decorator() # 装饰器本身使用了参数默认值 def function_with_default():print(Inside function_with_default)decorator(arg1, keyvalue) # 装饰器传递了所有或部分合法参数 def function_with_args():print(Inside function_with_args)# 调用 function() print() function_with_default() print() function_with_args() wraps装饰器使用案例 在Python中wraps装饰器是一个用于创建装饰器的辅助函数通常与装饰器一起使用以保留原始函数的元数据例如函数名称、文档字符串、参数签名等。这对于调试和日志记录非常有用因为它能够保留原始函数的信息而不是让被装饰的函数看起来像是另一个函数。 wraps装饰器位于functools模块中。通常编写一个装饰器会在内部定义一个包装函数并在这个包装函数内部对被装饰的函数进行一些操作。使用wraps装饰器来装饰这个包装函数这样可以确保原始函数的元数据被正确传递到包装函数。需要注意的是使用它时必须传入指定的函数名作为参数这也表明了其使用位置必须是装饰器中使用外部函数的内部函数而不是装饰器函数本身 from functools import wrapsdef decorator(*call_word):print(decorator.__name__ is started)def inner_function(function):print(inner_function.__name__ is started)wraps(function)def core_function(*args):print(core_function.__name__ is started)function(*args)print(inner_function.__name__ str(call_word))return core_functionreturn inner_function decorator(Welcome to Python!!!) def connect_two_string(string1, string2):print(string1 string2)connect_two_string(Hello, World!!!)此时得到运行结果中获取的core_function已经变成了外部函数名 decorator is started inner_function is started inner_function (Welcome to Python!!!,) connect_two_string is started HelloWorld!!!什么是Python元数据 在Python中元数据是指与对象相关的描述性信息它包括但不限于以下内容 函数名称__name__函数的名称。模块名称__name__模块的名称。文档字符串__doc__函数、类、模块或方法的文档字符串提供了有关对象的描述和说明。参数签名__annotations__函数或方法的参数和返回值的注释。函数参数列表__code__.co_varnames函数的参数列表。函数字节码__code__.co_code函数的字节码指令序列。类名称__name__类的名称。类文档字符串__doc__类的文档字符串提供了有关类的描述和说明。类属性和方法__dict__类的属性和方法字典。模块级别的全局变量和函数globals()模块中定义的全局变量和函数。类级别的方法__dict__类中定义的方法存储在类的字典中。类继承关系__bases__类的直接父类。模块级别的导入信息__path__, __file__等模块的导入路径、文件路径等信息。 利用Callable特性实现装饰器类 在Python中callable是一个特性用于检查一个对象是否可以被调用即是否可作为函数调用。如果一个对象是可调用的则可以像调用函数一样使用它通过在对象名后面加上一对圆括号并且可以传递参数给它。在Python中函数、类如果定义了 __call__ 方法、类的实例如果定义了 __call__ 方法以及其他一些对象都是可调用的。通过使用内置函数 callable()你可以检查对象是否是可调用的。当你调用 callable() 并将一个对象作为参数传递给它时如果该对象是可调用的它将返回 True否则返回 False。 from functools import wrapsclass CustomDecorator:def __init__(self, arg1, arg2):self.arg1 arg1self.arg2 arg2def __call__(self, func):wraps(func)def wrapped_func(*args, **kwargs):print(Decorator arguments:, self.arg1, self.arg2)result func(*args, **kwargs)print(This is function: , wrapped_func.__name__)return resultreturn wrapped_funcCustomDecorator(Hello, World) def my_function():print(Inside the function)if callable(CustomDecorator):my_function() 设计模式之装饰器模式 所谓装饰就是不能更改被装饰对象、类或者函数的原有的行为在这些原有的行为上添加一些扩展行为来实现装饰的目的。 在设计模式中装饰器模式是一种通用的解决方案它的思想可以被用于设计实现中但实际上并不一定需要使用 Python 中的装饰器语法来实现。 装饰器模式是一种结构型设计模式它允许动态地为一个对象添加新的功能而无需改变其原始类的结构。这种模式通过将对象放入一个包装器中来实现该包装器包含了要添加的额外功能。在装饰器模式中通常会有以下角色 组件接口Component Interface定义了被装饰对象和装饰器共同实现的接口或抽象类。它是被装饰对象和装饰器的共同父类。 具体组件Concrete Component实现了组件接口它是被装饰的原始对象。 装饰器Decorator也实现了组件接口它包含了一个对组件的引用并且可以通过该引用动态地添加额外的功能。 具体装饰器Concrete Decorator扩展了装饰器类添加了具体的附加功能。 考虑一个简单的示例假设我们有一个 Coffee 类代表一杯咖啡它有一个方法 cost() 来计算咖啡的价格。我们希望能够动态地为咖啡添加额外的配料如奶油、糖浆等而不需要修改 Coffee 类本身。 # 组件接口 class Coffee:def cost(self):pass# 具体组件 class SimpleCoffee(Coffee):def cost(self):return 5# 装饰器 class CoffeeDecorator(Coffee):def __init__(self, decorated_coffee):self.decorated_coffee decorated_coffeedef cost(self):return self.decorated_coffee.cost()# 具体装饰器 class Milk(CoffeeDecorator):def cost(self):return self.decorated_coffee.cost() 2class Sugar(CoffeeDecorator):def cost(self):return self.decorated_coffee.cost() 1在这个示例中Coffee 是组件接口SimpleCoffee 是具体组件CoffeeDecorator 是装饰器而 Milk 和 Sugar 是具体装饰器。现在我们可以创建一个咖啡对象并动态地添加配料 coffee SimpleCoffee() print(coffee.cost())coffee_with_milk Milk(coffee) print(coffee_with_milk.cost()) coffee_with_milk_and_sugar Sugar(coffee_with_milk) print(coffee_with_milk_and_sugar.cost())通过装饰器模式我们可以在不修改原始 Coffee 类的情况下动态地添加额外的功能使得代码更加灵活和可维护。
http://www.tj-hxxt.cn/news/226131.html

相关文章:

  • 网站位置导航wordpress wpml 下载
  • 模特公司网站模板重庆点优建设网站公司
  • 简单个人网站网页设计色彩搭配
  • asp做的静态网站卡不卡网站做了301重定向域名会自动跳转吗
  • 太原有网站工程公司吗shop商城系统
  • 私人定制平台网站WordPress显示加载时间
  • 网站 配色百度竞价排名魏则西
  • 网站做兼容需要多少钱短网址生成防红
  • 最新网站开发建设教材网站登录界面模板html
  • 电子商务网站运营方案vp代理商网站管理系统
  • 个人网站建立内容网站建设佰首选金手指十六
  • 做网站兼容性怎么设置信息平台网站的建设 文档
  • 阿里云建设网站流程企业网站设计好的缺点有哪些
  • 电子商务网站建设服务外包网站建设项目申请书
  • p2p平台网站开发北京值得去的商场
  • 北京网站建设市场深圳it培训
  • 短网址是什么西安seo霸屏
  • 哪里有零基础网站建设教学杭州网站设计建立企业网站
  • 网站 当前时间 代码洪涛怎么样海城市建设网站
  • 传媒公司 网站开发代做ansys网站
  • 网站建设费入万维网官方网站
  • 怀化主要网站怎么查看一个网站的后台
  • 公司做免费网站建设缘魁上海网站建设
  • 做个中英文网站多少钱网站设计中怎么设置当前元素不可见
  • 网站建设奕网情深代做cad平面图的网站
  • 微页制作平台网站建设水电维修在哪个网站上做推广好些
  • 民兵信息化网站建设做网站撘框架
  • 档案网站建设书flashfxp怎么上传对应网站空间
  • 温州编程网站网站建设技术服务公司
  • 爱ppt模板下载免费版seo推广怎么做视频教程