主页
  • 主页
  • 分类
  • 热文
  • 教程
  • 面试
  • 标签
Python

Python 基础

Python 主页
Python 概述
Python 历史
Python 功能
Python 与 C++
Python Hello World
Python 应用领域
Python 解释器及其模式
Python 环境设置
Python 虚拟环境
Python 语法
Python 变量
Python 数据类型
Python 类型转换
Python Unicode 系统
Python 文字
Python 运算符
Python 算术运算符
Python 比较运算符
Python 赋值运算符
Python 逻辑运算符
Python 位运算符
Python 成员运算符
Python 身份运算符
Python 运算符优先级
Python 注释
Python 用户输入
Python 数字
Python 布尔值

Python 控制语句

Python 控制流
Python 决策
Python if 语句
Python if-else 语句
Python 嵌套 if 语句
Python match-case 语句
Python 循环
Python For 循环
Python for-else 循环
Python while 循环
Python break 语句
Python Continue 语句
Python pass 语句
Python 嵌套循环

Python 函数和模块

Python 函数
Python 默认参数
Python 关键字参数
Python 关键字专用参数
Python 位置参数
Python 仅限位置参数
Python 任意或可变长度参数
Python 变量作用域
Python 函数注释
Python 模块
Python 内置函数

Python 字符串

Python 字符串
Python 字符串切片
Python 字符串修改
Python 字符串连接
Python 字符串格式化
Python 转义字符
Python 字符串方法
Python 字符串练习

Python 列表

Python 列表
Python 访问列表项
Python 更改列表项
Python 添加列表项
Python 删除列表项
Python 循环列表
Python 列表推导式
Python 排序列表
Python 复制列表
Python 合并列表
Python 列表方法
Python 列表练习

Python 元组

Python 元组
Python 访问元组项
Python 更新元组
Python 解包元组项
Python 循环元组
Python 合并元组
Python 元组方法
Python 元组练习

Python 集合

Python 集合
Python 访问集合项
Python 添加集合项
Python 删除集合项
Python 循环集合
Python 合并集合
Python 复制集合
Python 集合运算符
Python 集合方法
Python 集合练习

Python 字典

Python 字典
Python 访问字典项
Python 更改字典项
Python 添加字典项
Python 移除字典项
Python 字典视图对象
Python 循环字典
Python 复制字典
Python 嵌套字典
Python 字典方法
Python 字典练习

Python 数组

Python 数组
Python 访问数组项
Python 添加数组项
Python 移除数组项
Python 循环数组
Python 复制数组
Python 反转数组
Python 排序数组
Python 合并数组
Python 数组方法
Python 数组练习

Python 文件处理

Python 文件处理
Python 文件写入
Python 文件读取
Python 重命名和删除文件
Python 目录
Python 文件方法
Python 文件/目录方法
Python OS.Path 方法

Python 面向对象编程

Python OOP 概念
Python 类和对象
Python 类属性
Python 类方法
Python 静态方法
Python 构造函数
Python 访问修饰符
Python 继承
Python 多态
Python 方法重写
Python 方法重载
Python 动态绑定
Python 动态类型
Python 抽象
Python 封装
Python 接口
Python 包
Python 内部类
Python 匿名类和对象
Python 单例类
Python 包装器类
Python 枚举
Python 反射

Python 错误和异常

Python 语法错误
Python 异常处理
Python Try-Except
Python Try-Finally
Python 抛出异常
Python 异常链
Python 嵌套 try
Python 用户定义异常
Python 日志记录
Python 断言
Python 内置异常

Python 多线程

Python 多线程
Python 线程生命周期
Python 创建线程
Python 启动线程
Python 合并线程
Python 命名线程
Python 线程调度
Python 线程池
Python 主线程
Python 线程优先级
Python 守护线程
Python 线程同步

Python 同步

Python 线程间通信
Python 死锁
Python 中断线程

Python 网络

Python 网络编程
Python 套接字编程
Python URL 处理
Python 泛型

Python 杂项

Python Date and Time
Python math模块
Python 迭代器
Python 生成器
Python 闭包
Python 装饰器
Python 递归
Python 正则表达式
Python Pip
Python 数据库访问
Python 弱引用
Python 序列化
Python 模板技术
Python 输出格式化
Python 性能测量
Python 数据压缩
Python 通用网关接口
Python XML 处理
Python 用户界面(GUI)
Python 命令行参数
Python Docstrings
Python JSON
Python 发送电子邮件
Python 进一步扩展
Python 工具/实用程序
Python GUI

Python 高级概念

Python 抽象基类
Python 自定义异常
Python 高阶函数
Python 对象的内部机制
Python 内存管理
Python 元类
Python 元编程
Python 模拟与桩
Python 猴子补丁
Python 信号处理
Python 类型提示
Python 进行自动化
Python Humanize包
Python 上下文管理器
Python 协程
Python 描述符
Python 内存泄漏
Python 不可变数据结构

基础

Python 主页
Python 概述
Python 历史
Python 功能
Python 与 C++
Python Hello World
Python 应用领域
Python 解释器及其模式
Python 环境设置
Python 虚拟环境
Python 语法
Python 变量
Python 数据类型
Python 类型转换
Python Unicode 系统
Python 文字
Python 运算符
Python 算术运算符
Python 比较运算符
Python 赋值运算符
Python 逻辑运算符
Python 位运算符
Python 成员运算符
Python 身份运算符
Python 运算符优先级
Python 注释
Python 用户输入
Python 数字
Python 布尔值

控制语句

Python 控制流
Python 决策
Python if 语句
Python if-else 语句
Python 嵌套 if 语句
Python match-case 语句
Python 循环
Python For 循环
Python for-else 循环
Python while 循环
Python break 语句
Python Continue 语句
Python pass 语句
Python 嵌套循环

函数和模块

Python 函数
Python 默认参数
Python 关键字参数
Python 关键字专用参数
Python 位置参数
Python 仅限位置参数
Python 任意或可变长度参数
Python 变量作用域
Python 函数注释
Python 模块
Python 内置函数

字符串

Python 字符串
Python 字符串切片
Python 字符串修改
Python 字符串连接
Python 字符串格式化
Python 转义字符
Python 字符串方法
Python 字符串练习

列表

Python 列表
Python 访问列表项
Python 更改列表项
Python 添加列表项
Python 删除列表项
Python 循环列表
Python 列表推导式
Python 排序列表
Python 复制列表
Python 合并列表
Python 列表方法
Python 列表练习

元组

Python 元组
Python 访问元组项
Python 更新元组
Python 解包元组项
Python 循环元组
Python 合并元组
Python 元组方法
Python 元组练习

集合

Python 集合
Python 访问集合项
Python 添加集合项
Python 删除集合项
Python 循环集合
Python 合并集合
Python 复制集合
Python 集合运算符
Python 集合方法
Python 集合练习

字典

Python 字典
Python 访问字典项
Python 更改字典项
Python 添加字典项
Python 移除字典项
Python 字典视图对象
Python 循环字典
Python 复制字典
Python 嵌套字典
Python 字典方法
Python 字典练习

数组

Python 数组
Python 访问数组项
Python 添加数组项
Python 移除数组项
Python 循环数组
Python 复制数组
Python 反转数组
Python 排序数组
Python 合并数组
Python 数组方法
Python 数组练习

文件处理

Python 文件处理
Python 文件写入
Python 文件读取
Python 重命名和删除文件
Python 目录
Python 文件方法
Python 文件/目录方法
Python OS.Path 方法

面向对象编程

Python OOP 概念
Python 类和对象
Python 类属性
Python 类方法
Python 静态方法
Python 构造函数
Python 访问修饰符
Python 继承
Python 多态
Python 方法重写
Python 方法重载
Python 动态绑定
Python 动态类型
Python 抽象
Python 封装
Python 接口
Python 包
Python 内部类
Python 匿名类和对象
Python 单例类
Python 包装器类
Python 枚举
Python 反射

错误和异常

Python 语法错误
Python 异常处理
Python Try-Except
Python Try-Finally
Python 抛出异常
Python 异常链
Python 嵌套 try
Python 用户定义异常
Python 日志记录
Python 断言
Python 内置异常

多线程

Python 多线程
Python 线程生命周期
Python 创建线程
Python 启动线程
Python 合并线程
Python 命名线程
Python 线程调度
Python 线程池
Python 主线程
Python 线程优先级
Python 守护线程
Python 线程同步

同步

Python 线程间通信
Python 死锁
Python 中断线程

网络

Python 网络编程
Python 套接字编程
Python URL 处理
Python 泛型

杂项

Python Date and Time
Python math模块
Python 迭代器
Python 生成器
Python 闭包
Python 装饰器
Python 递归
Python 正则表达式
Python Pip
Python 数据库访问
Python 弱引用
Python 序列化
Python 模板技术
Python 输出格式化
Python 性能测量
Python 数据压缩
Python 通用网关接口
Python XML 处理
Python 用户界面(GUI)
Python 命令行参数
Python Docstrings
Python JSON
Python 发送电子邮件
Python 进一步扩展
Python 工具/实用程序
Python GUI

高级概念

Python 抽象基类
Python 自定义异常
Python 高阶函数
Python 对象的内部机制
Python 内存管理
Python 元类
Python 元编程
Python 模拟与桩
Python 猴子补丁
Python 信号处理
Python 类型提示
Python 进行自动化
Python Humanize包
Python 上下文管理器
Python 协程
Python 描述符
Python 内存泄漏
Python 不可变数据结构

Python 装饰器


上一章 下一章

Python 中的装饰器是一个函数,它接收另一个函数作为参数。传入的函数是要被装饰的函数。装饰器扩展了被装饰函数的行为,而无需实际修改它。

本章中,我们将学习如何使用 Python 装饰器。

定义函数装饰器

Python 中的函数是一等对象。这意味着它们可以像其他数据类型(如数字、字符串或列表等)一样作为参数传递给另一个函数。也可以在另一个函数内部定义一个函数。这样的函数称为嵌套函数。此外,函数也可以返回其他函数。

装饰器函数的典型定义如下:

def decorator(arg_function): # arg_function 是要被装饰的函数
   def nested_function():
      # 这里包裹了 arg_function 并扩展了它的行为
      # 调用 arg_function
      arg_function()
   return nested_function

这里是一个普通的 Python 函数:

def function():
   print("hello")

现在你可以通过将其传递给装饰器来装饰此函数以扩展其行为:

function = decorator(function)

如果现在执行这个函数,它将会显示出由装饰器扩展后的输出。

Python 装饰器示例

练习以下示例来理解 Python 装饰器的概念。

示例 1

下面的代码是一个简单的装饰器示例:

def my_function(x):
   print("The number is=", x)

def my_decorator(some_function, num):
   def wrapper(num):
      print("Inside wrapper to check odd/even")
      if num % 2 == 0:
         ret = "Even"
      else:
         ret = "Odd!"
      some_function(num)
      return ret
   print("wrapper function is called")
   return wrapper

no = 10
my_function = my_decorator(my_function, no)
print("It is", my_function(no))

my_function() 只是打印出接收到的数字。然而,通过将其传递给 my_decorator,其行为被修改了。内部函数接收数字并返回它是奇数还是偶数。上述代码的输出为:

wrapper function is called
Inside wrapper to check odd/even
The number is= 10
It is Even

示例 2

一种更优雅的方式来装饰一个函数是在其定义前加上装饰器名前缀 @ 符号。上面的例子改写成这种方式如下:

def my_decorator(some_function):
   def wrapper(num):
      print("Inside wrapper to check odd/even")
      if num % 2 == 0:
         ret = "Even"
      else:
         ret = "Odd!"
      some_function(num)
      return ret
   print("wrapper function is called")
   return wrapper

@my_decorator
def my_function(x):
   print("The number is=", x)

no = 10
print("It is", my_function(no))

Python 标准库定义了以下内置装饰器:

@classmethod 装饰器

classmethod 是一个内置函数。它把一个方法转换成类方法。类方法不同于实例方法。定义在类中的实例方法是由类的对象调用的,该方法隐式接收一个引用 self。另一方面,类方法隐式接收类本身作为第一个参数。

语法

为了声明一个类方法,使用以下装饰器的标记:

class Myclass:
   @classmethod
   def mymethod(cls):
      #...

@classmethod 的形式如同前面描述的函数装饰器。mymethod 接收对类的引用。它既可以被类也可以被其对象调用。也就是说,Myclass.mymethod 以及 Myclass().mymethod 都是有效的调用。

@classmethod 装饰器示例

让我们通过以下示例来理解类方法的行为:

class counter:
   count = 0
   def __init__(self):
      print("init called by", self)
      counter.count = counter.count + 1
      print("count=", counter.count)
   @classmethod
   def showcount(cls):
      print("called by", cls)
      print("count=", cls.count)

c1 = counter()
c2 = counter()
print("class method called by object")
c1.showcount()
print("class method called by class")
counter.showcount()

在类定义中,count 是一个类属性。__init__() 方法是构造函数,显然它是一个实例方法,因为它接收 self 作为对象引用。每个对象声明都会调用此方法,并使 count 加一。

@classmethod 装饰器将 showcount() 方法转换为类方法,即使是由其对象调用,它也会接收类的引用作为参数。可以看到,即使是 c1 对象调用 showcount,也显示了 counter 类的引用。

它将显示以下输出:

init called by <__main__.counter object at 0x000001D32DB4F0F0>
count= 1
init called by <__main__.counter object at 0x000001D32DAC8710>
count= 2
class method called by object
called by <class '__main__.counter'>
count= 2
class method called by class
called by <class '__main__.counter'>

@staticmethod 装饰器

staticmethod 同样是 Python 标准库中的内置函数。它将一个方法转换为静态方法。静态方法在无论是由类的实例还是类自身调用时都不会接收任何引用参数。在类中声明静态方法使用的标记如下:

class Myclass:
   @staticmethod
   def mymethod():
      #...

尽管 Myclass.mymethod 以及 Myclass().mymethod 都是有效的调用,但静态方法不会接收任何引用。

@staticmethod 装饰器示例

counter 类被修改如下:

class counter:
   count = 0
   def __init__(self):
      print("init called by", self)
      counter.count = counter.count + 1
      print("count=", counter.count)
   @staticmethod
   def showcount():
      print("count=", counter.count)

c1 = counter()
c2 = counter()
print("class method called by object")
c1.showcount()
print("class method called by class")
counter.showcount()

如同之前所述,在 __init__() 方法内部每个对象声明时 count 类属性都会增加。然而,由于 mymethod 是静态方法,它没有接收 self 或者 cls 参数。因此,类属性 count 的值显示时带有显式的 counter 引用。

上述代码的输出如下:

init called by <__main__.counter object at 0x000002512EDCF0B8>
count= 1
init called by <__main__.counter object at 0x000002512ED48668>
count= 2
class method called by object
count= 2
class method called by class
count= 2

@property 装饰器

Python 的 property() 内置函数是用于访问类的实例变量的接口。@property 装饰器将实例方法转换为同名只读属性的“getter”,并且设置属性的文档字符串为“获取实例变量的当前值”。

您可以使用以下三种装饰器来定义一个属性:

  • @property —— 声明方法为属性。
  • @<property-name>.setter —— 指定属性的设置方法。
  • @<property-name>.deleter —— 指定删除属性的方法。

由 property() 函数返回的属性对象有 getter、setter 和 delete 方法。

property(fget=None, fset=None, fdel=None, doc=None)

fget 参数是 getter 方法,fset 是 setter 方法。可选地可以有 fdel 作为删除对象的方法,doc 是文档字符串。

语法

property() 对象的 setter 和 getter 也可以用以下语法来赋值:

speed = property()
speed = speed.getter(speed, get_speed)
speed = speed.setter(speed, set_speed)

其中 get_speed() 和 set_speed() 是检索和设置 Car 类中实例变量 speed 的值的实例方法。

上述语句可以通过 @property 装饰器实现。使用装饰器重写 Car 类如下:

@property 装饰器示例

class car:
   def __init__(self, speed=40):
      self._speed = speed
      return
   @property
   def speed(self):
      return self._speed
   @speed.setter
   def speed(self, speed):
      if speed < 0 or speed > 100:
         print("speed limit 0 to 100")
         return
      self._speed = speed
      return

c1 = car()
print(c1.speed) # 调用 getter
c1.speed = 60 # 调用 setter

属性装饰器是非常方便且推荐处理实例属性的方法。

上一章 下一章
阅读号二维码

关注阅读号

联系二维码

联系我们

© 2024 Yoagoa. All rights reserved.

粤ICP备18007391号

站点地图