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 来设置参数


相关文章
|
5天前
|
存储 数据挖掘 开发者
Python编程入门:从零到英雄
在这篇文章中,我们将一起踏上Python编程的奇幻之旅。无论你是编程新手,还是希望拓展技能的开发者,本教程都将为你提供一条清晰的道路,引导你从基础语法走向实际应用。通过精心设计的代码示例和练习,你将学会如何用Python解决实际问题,并准备好迎接更复杂的编程挑战。让我们一起探索这个强大的语言,开启你的编程生涯吧!
|
2天前
|
数据采集 存储 数据处理
Python中的多线程编程及其在数据处理中的应用
本文深入探讨了Python中多线程编程的概念、原理和实现方法,并详细介绍了其在数据处理领域的应用。通过对比单线程与多线程的性能差异,展示了多线程编程在提升程序运行效率方面的显著优势。文章还提供了实际案例,帮助读者更好地理解和掌握多线程编程技术。
|
5天前
|
存储 人工智能 数据挖掘
Python编程入门:打造你的第一个程序
本文旨在为初学者提供Python编程的初步指导,通过介绍Python语言的基础概念、开发环境的搭建以及一个简单的代码示例,帮助读者快速入门。文章将引导你理解编程思维,学会如何编写、运行和调试Python代码,从而开启编程之旅。
27 2
|
6天前
|
开发框架 缓存 测试技术
Python中的装饰器:魔法般的功能增强
在Python编程中,装饰器是一种强大而灵活的工具,它允许开发者修改或扩展函数和类的行为。本文将深入探讨Python装饰器的工作原理,并通过实例演示如何创建和使用自定义装饰器来增强代码的功能性和可读性。我们将从基础概念讲起,逐步深入到高级应用,揭示装饰器背后的“魔法”,并展示它们在实际开发中的多种用途。
|
6天前
|
存储 Python
Python编程入门:理解基础语法与编写简单程序
本文旨在为初学者提供一个关于如何开始使用Python编程语言的指南。我们将从安装Python环境开始,逐步介绍变量、数据类型、控制结构、函数和模块等基本概念。通过实例演示和练习,读者将学会如何编写简单的Python程序,并了解如何解决常见的编程问题。文章最后将提供一些资源,以供进一步学习和实践。
16 1
|
7天前
|
Python
探索Python中的装饰器(Decorators)
探索Python中的装饰器(Decorators)
14 0
|
1月前
|
安全 测试技术 数据库
Python编程--sys模块及OS模块简单用例
Python编程--sys模块及OS模块简单用例
|
1月前
|
JSON 数据格式 Python
Python编程:利用JSON模块编程验证用户
Python编程:利用JSON模块编程验证用户
|
1月前
|
数据处理 Python
Python编程-利用datetime模块生成当前年份之前指定的间隔所有年份的日期列表和csv文件
Python编程-利用datetime模块生成当前年份之前指定的间隔所有年份的日期列表和csv文件
|
6月前
|
人工智能 安全 Java
Python 多线程编程实战:threading 模块的最佳实践
Python 多线程编程实战:threading 模块的最佳实践
257 5
下一篇
无影云桌面