Python 编程 | 连载 17 - 高阶函数与装饰器

简介: Python 编程 | 连载 17 - 高阶函数与装饰器

一、Python 中类的高阶函数

__str__ 函数,当print当前实例化对象的时候,会打印出该函数中的return的信息,相当于Java中的 toString 函数,也就是对象的描述信息的定义函数

class Student():
    def __init__(self, name):
        self.name = name
    # 定义实例化对象的描述信息
    def __str__(self):
        return 'Student[name={}]'.format(self.name)
    def breath(self):
        print('Student can breath')
if __name__ == '__main__':
    stu = Student('子渊')
    print(stu)
    stu.breath()
复制代码

image.png

打印对象时,输出了对象的属性信息也就是在__str__函数中返回的内容

__getattr__ 函数,当调用的属性或者方法不存在时,会返回返函数中定义的信息。

class Student():
    def __init__(self, name):
        self.name = name
    def __str__(self):
        return 'Student[name={}]'.format(self.name)
    def __getattr__(self, property):
        print('{}不存在'.format(property))
    def breath(self):
        print('Student can breath')
if __name__ == '__main__':
    stu = Student('子渊')
    print(stu)
    stu.breath()
    stu.age
复制代码

image.png

__setattr__ 函数,可以拦截当前类中不存在的属性或值,给不存在的属性设置属性值;在上面的 Student 类中增加函数

def __setattr__(self, key, value):
    if key not in self.__dict__:
        self.__dict__[key] = value
    print('key={}, value={}'.format(key, value))
复制代码

在main函数下增加代码

stu.like = 'lilith'
stu.like
复制代码

image.png

__call__ 函数可以将类变成一个函数;Student 类下增加函数

def __call__(self,name):
    print(name)
复制代码

在main函数中增加代码

# 像函数一样调用
stu('stark')
复制代码

image.png

实现链式调用

class Hero:
    def __init__(self, attr=''):
        self.__attr = attr
    def __getattr__(self, key):
        if self.__attr:
            key = '{}.{}'.format(self.__attr, key)
        else:
            key = key
        # 一定要返回Hero类才能实现链式调用    
        return Hero(key)
    def __call__(self, name):
        return name
hero = Hero()
name = hero.a.b.c('stark')
print(name)
复制代码

image.png

二、装饰器

装饰器:

  • 是一种函数
  • 可以接受函数作为参数
  • 可以返回函数
  • 接收一个函数作为参数,内部对其进行处理,然后返回一个新函数,动态增强函数功能

定义一个装饰器

def out(func): # 外围函数
    def inner(*args, **kwargs): # 内嵌函数,参数为外围函数参数的参数
        return func(*args, **kwargs) 
    return inner # 返回内嵌函数名,不加()
复制代码

装饰器的使用方式

  • 将被调用的函数直接作为参数参入装饰器的外围函数的参数
  • 将装饰器与被调用函数绑定在一起
  • @符号+装饰器函数放在被调用函数的上一行,被调用的函数正常定义,只需要直接调用被执行函数即可
def output_log(func):
    # 定义内嵌函数,用来指定传入的函数,内嵌函数的参数为传入的函数的参数
    def inner(*args, **kwargs):
        print('[info]{}被调用'.format(func.__name__))
        res = func(*args, **kwargs)
        print('[info]{}返回的结果为:{}'.format(func.__name__, res))
        return res
    # 返回内嵌函数的函数名
    return inner
# 使用装饰器
@output_log
def alpha(data):
    return data
res = alpha('pc12138')
print(res)
复制代码

image.png

使用关键字传参和位置传参,并在装饰器中打印出传入的参数

def output_log(func):
    # 定义内嵌函数,用来指定传入的函数,内嵌函数的参数为传入的函数的参数
    def inner(*args, **kwargs):
        print('[info]{}被调用'.format(func.__name__))
        print('[info]{}传入的元组类型参数为{}'.format(func.__name__, args))
        print('[info]{}传入的字典类型参数为{}'.format(func.__name__, kwargs))
        res = func(*args, **kwargs)
        print('[info]{}返回的结果为:{}---------'.format(func.__name__, res))
        return res
    # 返回内嵌函数的函数名
    return inner
# 使用装饰器
@output_log
def alpha(data):
    return data
alpha(data='pc12138')
alpha('pc12138')
复制代码

image.png

类中的常用装饰器

@classmethod 装饰器

使用 @classmethod 装饰器标注的函数可以不经过实例化而直接使用类调用

@classmethod
def func(cls, args):
    do
复制代码

cls 表示当前类本身,替代普通类函数中的self,self是指类实例化后的对象本身

class Bravo():
    def __init__(self, x):
        self.x = x
    def walk(self):
        print('普通成员函数,需要实例化对象调用')
    @classmethod
    def run(cls):
        print('类直接调用的函数,无须实例化')
Bravo.run()
复制代码

image.png

@classmethod 标注的函数可以通过类直接调用时

# 其他代码保持不变
@classmethod
def run(cls):
    print('类直接调用的函数,无须实例化')
    cls.walk()
复制代码

image.png

@classmethod 标注的函数中无法调用普通的类的成员函数

class Bravo():
    def __init__(self, x):
        self.x = x
    def walk(self):
        print('普通成员函数,需要实例化对象调用')
        self.run()
    @classmethod
    def run(cls):
        print('类直接调用的函数,无须实例化')
        # cls.walk()
Bravo.run()
bravo = Bravo('bravo')
bravo.walk()
复制代码

image.png

普通类的成员函数中可以调用 @classmethod 标注的函数

# 其他代码保持不变
# 实例化对象直接调用
bravo.run()
复制代码

image.png

实例化对象可以调用普通的类成员函数也可以调用 @classmethod 标注的函数

@staticmethod 装饰器

@staticmethod 可以将类函数可以不经过实例化而直接被调用,被装饰器调用的函数无须传递 self 或者 cls 函数,且无法在该函数内调用其他类函数或者类变量

class Bravo():
    def __init__(self, x):
        self.x = x
    def walk(self):
        print('普通成员函数,需要实例化对象调用')
        self.run()
    @staticmethod
    def run():
        print('类直接调用的函数,无须实例化,且无须传入cls或者self参数')
        # self.wakl()
    # @classmethod
    # def rush(cls):
    #     print()
Bravo.run()
bravo = Bravo('bravo')
bravo.walk()
bravo.run()
复制代码

image.png

类和普通对象以及类的普通函数中都可以调用 @staticmethod 标注的函数

@staticmethod
def run():
    print('类直接调用的函数,无须实例化')
    self.walk()
复制代码

image.png

@staticmethod 标注的函数中不能调用类的普通函数

增加一个 @classmethod 标注的函数

@classmethod
def rush(cls):
    print('类直接调用的函数,无须实例化,需要传入cls参数')
    cls.run()
复制代码

image.png

@classmethod 标注的函数中可以调用 @staticmethod 标注的函数

@staticmethod
def run():
    print('类直接调用的函数,无须实例化,且无须传入cls或者self参数')
    self.rush()
复制代码

image.png

@staticmethod 标注的函数中无法调用 @classmethod 标注的函数

  • 类的普通函数中既可以调用@staticmethod标注的函数也可以调用@classmethod标注的函数,因为含有self参数
  • @classmethod标注的函数中可以调用@staticmethod标注的函数,因为有cls参数,但是不能调用普通类的函数,因为需要实例化
  • @staticmethod标注的函数不可以调用@staticmethod标注的函数和类的普通函数,因为没有参数

@property 装饰器

@property 可以将类函数的执行免去括弧,类似于调用属性的方式

class Bravo():
    def __init__(self, x):
        self.x = x
    def walk(self):
        print('普通成员函数,需要实例化对象调用')
    @property
    def run(self):
        print('类似于普通类函数,需要传入self参数,不同的是调用时不必加括弧')
bravo = Bravo('bravo')
bravo.run
复制代码

image.png

带有参数的 @property 标注的函数

class Bravo():
    # 其余代码不变
    @property
    def rush(self):
        return '带参数的@property函数要通过@函数名.setter设置参数,传入的参数为{}'.format(self.__name)
    # rush函数参数设置方式
    @rush.setter
    def rush(self, name):
        self.__name = name
bravo = Bravo('bravo')
bravo.rush = 'Stark'
res = bravo.rush
print(res)
复制代码

image.png

@property 标注的函数如果有参数,要通过 @函数名.setter 来设置参数


相关文章
|
1天前
|
缓存 算法 数据处理
Python入门:9.递归函数和高阶函数
在 Python 编程中,函数是核心组成部分之一。递归函数和高阶函数是 Python 中两个非常重要的特性。递归函数帮助我们以更直观的方式处理重复性问题,而高阶函数通过函数作为参数或返回值,为代码增添了极大的灵活性和优雅性。无论是实现复杂的算法还是处理数据流,这些工具都在开发者的工具箱中扮演着重要角色。本文将从概念入手,逐步带你掌握递归函数、匿名函数(lambda)以及高阶函数的核心要领和应用技巧。
Python入门:9.递归函数和高阶函数
|
23天前
|
存储 缓存 Java
Python高性能编程:五种核心优化技术的原理与Python代码
Python在高性能应用场景中常因执行速度不及C、C++等编译型语言而受质疑,但通过合理利用标准库的优化特性,如`__slots__`机制、列表推导式、`@lru_cache`装饰器和生成器等,可以显著提升代码效率。本文详细介绍了这些实用的性能优化技术,帮助开发者在不牺牲代码质量的前提下提高程序性能。实验数据表明,这些优化方法能在内存使用和计算效率方面带来显著改进,适用于大规模数据处理、递归计算等场景。
58 5
Python高性能编程:五种核心优化技术的原理与Python代码
|
1月前
|
设计模式 前端开发 Shell
Python装饰器是什么?
装饰器是Python中用于动态修改函数、方法或类功能的工具,无需改变原代码。通过将函数作为参数传递并返回新函数,装饰器可以在原函数执行前后添加额外逻辑。例如,使用`@logger`装饰器可以打印函数调用日志,而`@timethis`则可用于计算函数执行时间。为了保持被装饰函数的元信息(如`__name__`和`__doc__`),可使用`functools.wraps`装饰器。此外,带参数的装饰器可通过嵌套函数实现,如`@timeitS(2)`,以根据参数条件输出特定信息。
90 59
|
1月前
|
测试技术 数据库 Python
Python装饰器实战:打造高效性能计时工具
在数据分析中,处理大规模数据时,分析代码性能至关重要。本文介绍如何使用Python装饰器实现性能计时工具,在不改变现有代码的基础上,方便快速地测试函数执行时间。该方法具有侵入性小、复用性强、灵活度高等优点,有助于快速发现性能瓶颈并优化代码。通过设置循环次数参数,可以更准确地评估函数的平均执行时间,提升开发效率。
106 61
Python装饰器实战:打造高效性能计时工具
|
2月前
|
Python
[oeasy]python055_python编程_容易出现的问题_函数名的重新赋值_print_int
本文介绍了Python编程中容易出现的问题,特别是函数名、类名和模块名的重新赋值。通过具体示例展示了将内建函数(如`print`、`int`、`max`)或模块名(如`os`)重新赋值为其他类型后,会导致原有功能失效。例如,将`print`赋值为整数后,无法再用其输出内容;将`int`赋值为整数后,无法再进行类型转换。重新赋值后,这些名称失去了原有的功能,可能导致程序错误。总结指出,已有的函数名、类名和模块名不适合覆盖赋新值,否则会失去原有功能。如果需要使用类似的变量名,建议采用其他命名方式以避免冲突。
52 14
|
2月前
|
分布式计算 大数据 数据处理
技术评测:MaxCompute MaxFrame——阿里云自研分布式计算框架的Python编程接口
随着大数据和人工智能技术的发展,数据处理的需求日益增长。阿里云推出的MaxCompute MaxFrame(简称“MaxFrame”)是一个专为Python开发者设计的分布式计算框架,它不仅支持Python编程接口,还能直接利用MaxCompute的云原生大数据计算资源和服务。本文将通过一系列最佳实践测评,探讨MaxFrame在分布式Pandas处理以及大语言模型数据处理场景中的表现,并分析其在实际工作中的应用潜力。
116 2
|
2月前
|
Unix Linux 程序员
[oeasy]python053_学编程为什么从hello_world_开始
视频介绍了“Hello World”程序的由来及其在编程中的重要性。从贝尔实验室诞生的Unix系统和C语言说起,讲述了“Hello World”作为经典示例的起源和流传过程。文章还探讨了C语言对其他编程语言的影响,以及它在系统编程中的地位。最后总结了“Hello World”、print、小括号和双引号等编程概念的来源。
126 80

热门文章

最新文章

推荐镜像

更多