news 2026/9/8 16:24:45

装饰器: 在不改变原函数的基础上, 动态给函数增加功能

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
装饰器: 在不改变原函数的基础上, 动态给函数增加功能

面向对象 之 初识 @

是类之内置的一个装饰器, @的作用在于经由过程特定体式格局, 把一个按正常应当以方法情势调用的执行体, 转化为以属性情势来操控调用。

装饰器: 在不改变原函数的基础上, 动态给函数增加功能

很多装饰器的些许细节, 之前已然开展过讨论, 其本质是借助变量的引用(指针)特色以及变量命名空间最终达成的。

def out(func): def inner(*args, **kwargs): print(f"...{args[0]} is checking...") return func(*args, **kwargs) return inner @out def check_2019_nCov(name): msg = f"okay, {name} is very healthy." return msg ret = check_2019_nCov("youge") print(ret) # output ...youge is checking... okay, youge is very health

@针对这个装饰器, 通常情况下我会更多地将它运用在代码优化方面, 把一个方法进行封装从而使其成为属性, 如此一来在阅读体验上会更优一些。关于具体是怎样实现的, 我也尚未弄明白, 暂且只要能够应用就行。

具体的写法是, 在需要用到的那个方法的上面, 使用 @ 进行装饰, 其参数仅仅只有 self, 在调用这个方法的时候, 不需要加上括号。

@ 将方法装饰为属性

# 访问类的私有属性 class Foo: def __init__(self, score): self.__score = score @property # 将方法装饰为属性 def show_score(self): return self.__score if __name__ == '__main__': s = Foo(66) # 在写法上更加优雅, 不用多写 "方法()" 没用的括号 print(s.show_score) # output: 66

就是待在类自身的成员里头玩耍, (在无需传递外部参数的情况之下运用, 表示类的成员属性), 刚开始感觉挺 呢。

咱们插句话说一下, 就上例之中, 那个被 @所装饰的方法, 它的功能是为外部提供一个能够查看内部属性的接口。其中, 代表私有变量, 它不能被加以直接访问。抱有期望来讲, 然而外部却依旧是能够访问内部变量的, 感觉这算得上是不够严谨的一处地方, 毕竟不存在绝对的安全。

s = Foo(66) # 外部直接访问私有变量(方法) 是不可以的 print(s.__score) # output AttributeError: 'Foo' object has no attribute '__score'

但是, 经由实例对象 . 类名 _ 的私有属性, 采用这样的途径的话是可行的, (其中缘由是什么呢, 能够直接去探究一下类自身的构造原理)。

s = Foo(66) # 没有绝对的安全哦, 只要互相尊重 print(s._Foo__score) # output 66

@ 相关属性

采用上面所提及的那种写法, 给人的感觉好像仅仅只是, 将原本的方法转变成为了属性罢了, 似乎就只是这样, 除去在写法方面相对而言较为简洁优雅一些之外, 那它具体的实际应用场景究竟会是怎样的情况呢?

绑定属性-校验-手动实现

class Foo: def __init__(self, score): self.score = score # 绑定score属性 s = Foo(666)

更改 score 属性时, 我通常这样写.

s.score = 666

以这样子的, 无比粗暴的方式, 也就是直接把属性给暴露出去的方式, 来进行绑定属性,虽说, 这样子写起来是简单的, 然而, 它没有检验参数, 这就致使其能够被随意修改。

运用这般粗野的方式明显是不怎么合乎情理的, 应当针对score开展一回验证, 值、类型等等均可, 也就是当我们去设定score属性之际, 应当要达成两个(自定义)方法, 一个用来查看值, 另一个用来设置值。

class Foo: def get_score(self): """获取属性值""" print(self.score) def set_score(self, value): """设置属性值""" if not isinstance(value, int): raise ValueError("score 必须为整数哦") if value > 100 or value <= 0: raise ValueError("score 必须在 0-100哦") self.score = value if __name__ == '__main__': f = Foo() # 校验通过是可以的 f.set_score(66) f.get_score() # output 66
# 随便设置 score 属性就不可以了. if __name__ == '__main__': f = Foo() f.set_score('youge') f.get_score() # output raise ValueError("score 必须为整数哦") ValueError: score 必须为整数哦
# 继续 debug if __name__ == '__main__': f = Foo() f.set_score('youge') f.get_score() # output raise ValueError("score 必须在 0-100哦") ValueError: score 必须在 0-100哦

case1 绑定属性-校验-@ 实现

class Foo: @property # read only def score(self): """获取属性值""" return self.score @score.setter def score(self, value): """设置属性值""" if not isinstance(value, int): raise ValueError("score 必须为整数哦") if value > 100 or value <= 0: raise ValueError("score 必须在 0-100哦") # 这里一定不能 self.socre = value 哦, 不然就递归了. self._score = value print(f"set score = {value} successfully.") if __name__ == '__main__': f = Foo() f.score = 66 # print(f.score) # output: set score = 66 successfully
if __name__ == '__main__': f = Foo() f.score = 'youge' # output raise ValueError("score 必须为整数哦") ValueError: score 必须为整数哦

case 2 - 封装类属性

那再来一个小小的例子, 嗯, 去封装一个名为Book的类, 这个类主要是用来对书籍的名称、价格以及评论进行描述的, 然后, 还要求能够运用装饰器来实现对Book的实例属性的set和get方法进行定义, 也就是要使得实例对象能够以属性的方式去操作方法或者属性。

class Book: def __init__(self, name, price, comment=None): self.__name = name self.__price = price self.__comment = comment # 传统方法对price属性进行 设置和访问 def get_price(self): return self.__price def set_price(self, value): self.__price = value # price = property(get_price, set_price) # @property 装饰器对 comment 属性进行 设置和访问 @property def my_comment(self): # 默认是 getter, 需要return 或 yeild return self.__comment @my_comment.setter def my_comment(self, value): # 检验 if not isinstance(value, float): raise ValueError("must be a decimal number") if value < 0 or value > 1000: raise ValueError("0 ~ 1000") self.__comment = value @my_comment.deleter def my_comment(self): print("delete this atrr...")

小结

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/8 16:23:44

前端转AI大模型开发:小白也能轻松入门的收藏必备学习路线!

本文为前端开发者提供了从前端逐步转向AI大模型应用开发的实用指南。作者结合自身近一年的经验&#xff0c;建议前端开发者不必死磕算法或研究训练&#xff0c;而是应优先进入“大模型应用开发”赛道。文章详细介绍了四个学习阶段&#xff1a;基础补齐&#xff08;Python编程&a…

作者头像 李华
网站建设 2026/9/8 16:23:03

Vibe Kanban:用看板管理AI编程助手的任务与上下文

过去一年&#xff0c;我绝大部分编码工作都是和AI编程助手结对完成的。代码生成、重构、补测试&#xff0c;模型干得很漂亮&#xff0c;但我的效率瓶颈却跑到了“会话”上&#xff1a;每次新开一个对话&#xff0c;都要把项目背景、模块入口、技术约束重新喂一遍&#xff1b;如…

作者头像 李华
网站建设 2026/9/8 16:20:59

常见的Python解释器,以及如何判断当前使用的是哪个解释器?

用于执行代码的程序是解释器, 它是语言核心组件之一, 负责读取代码, 负责解释代码, 负责运行代码, 解释器有几种不同实现, 每种实现都有其独特特点, 每种实现都有其独特用途。以下是一些主要的 解释器&#xff1a;1. 这是最为普遍的解释器, 该解释器是由软件基金会所开发的, 它…

作者头像 李华
网站建设 2026/9/8 16:20:11

整车在环ViL测试系统深度解析:架构、关键技术与工程实践

1. 为什么整车在环测试成了智能汽车绕不开的关卡 智能汽车测试这些年是被逼着往前走的一个领域。我在这个行业摸爬滚打十年&#xff0c;眼看着测试手段从“台架道路”两条腿走路&#xff0c;硬生生被逼出了第三条路——整车在环&#xff08;Vehicle in the Loop&#xff0c;ViL…

作者头像 李华