Python 面向对象 之 Property

初识 @property

Property 是 Python 类的一个内置的 装饰器. @property 的作用是 将一个方法, 变为属性来调用.

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

之前已经讨论过很多装饰器的细节了, 本质就是利用Pyhton变量的引用(指针)特性 和 变量命名空间来实现的.

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

@property 这个装饰器, 我一般会用在代码优化上多一点, 将一个方法, 封装为属性, 在阅读体验会好一些. 具体咋实现的, 也没搞清楚, 暂时能应用就好了.

具体写法即在需要的方法上边用 @property 装饰, 参数只有self, 调用的时候不加括号.

@property 将方法装饰为属性

# 访问类的私有属性
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

即在类自己的成员之间玩, (不需要传外部参数的情景下用, 表示 类的成员属性.), 初觉得比较 Pythonic 吧.

插一嘴, 上例中的 @property 所装饰的方法, 的功能是给 外部一个查看内部属性的接口. __ score 表示私有变量, 不能被直接访问, 期望上, 但 外部仍然是可以访问内部变量的, 感觉这算是 Pyhton不够严谨的地方吧, 没有绝对的安全哦.

s = Foo(66)

# 外部直接访问私有变量(方法) 是不可以的

print(s.__score)

# output
AttributeError: 'Foo' object has no attribute '__score'

but, 通过 实例对象.类名_ 私有属性 这样的方式是可以的 (为啥呢, 可以直接研究下Python类自身的构造原理)

s = Foo(66)

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

@property 相关属性

通过上面的写法, 感觉无非就是, 把方法变成了属性而已, 似乎.除了写法上比较简洁优雅一点, 具体的使用场景是什么呢?

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

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

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

s.score = 666

这样的无比粗暴 (直接将属性给暴露出去) 方式来 绑定属性 虽然写起来简单, 但是没有检验参数 导致可以随意被改.

这样粗暴的方法显然是不太合理的. 应该对 score进行一个校验, 值, 类型等都可以. 即我们在设置 score 属性的时候, 应该要实现两个 (自定义) 方法, get_score 用来查看值, 而 set_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 绑定属性-校验-@property 实现

  • 默认是 只读
  • setter
  • deleter
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的类, 主要用来描述书籍的名称, 价格和评论. 然后呢, 要求能用 property 装饰器实现对 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...")

小结

  • @property 装饰器的将方法变成属性来使用
  • @property 默认是只读, 配合 setter, deleter ... 等一起使用
  • 常用场景是对类实例属性赋值是, 进行一个 值的校验功能

Python 面向对象 之 @property的更多相关文章

  1. Python面向对象 -- slots, @property、多重继承MixIn、定制类(str, iter, getitem, getattr, call, callable函数,可调用对象)、元类(type, metaclass)

    面向对象设计中最基础的3个概念:数据封装.继承和多态 动态给class增加功能 正常情况下,当定义了一个class,然后创建了一个class的实例后,可以在程序运行的过程中给该实例绑定任何属性和方法, ...

  2. Python - 面向对象编程 - @property

    前言 前面讲到实例属性的时候,我们可以通过 实例对象.实例属性 来访问对应的实例属性 但这种做法是不建议的,因为它破坏了类的封装原则 正常情况下,实例属性应该是隐藏的,只允许通过类提供的方法来间接实现 ...

  3. python 面向对象七 property() 函数和@property 装饰符

    一.property引入 为了使对象的属性不暴露给调用者和进行属性值检查,设置了访问属性的接口函数,使用函数访问属性,并可以在函数内部检查属性. >>> class Student( ...

  4. python面向对象高级:@property

    @property 把方法『变成』了属性,广泛应用在类的定义中,可以让调用者写出简短的代码,同时保证对参数进行必要的检查,这样,程序运行时就减少了出错的可能性. 最大的作用就是既能检查参数,又可以用类 ...

  5. python面向对象进阶(八)

    上一篇<Python 面向对象初级(七)>文章介绍了面向对象基本知识: 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用 类 是一个模板,模板中包装了多个“函数”供使 ...

  6. python 面向对象(进阶篇)

    上一篇<Python 面向对象(初级篇)>文章介绍了面向对象基本知识: 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用 类 是一个模板,模板中包装了多个“函数”供使 ...

  7. python 面向对象和类成员和异常处理

    python 面向对象 你把自己想象成一个上帝,你要创造一个星球,首先你要把它揉成一个个球,两个直径就能创造一个球 class star: '''名字(name),赤道直径(equatorial di ...

  8. python 面向对象学习

    ------Python面向对象初 下面写一个类的简单实用,以便方便理解类 #python 3.5环境,解释器在linux需要改变 #阅读手册查询readme文件 #作者:S12-陈金彭 class ...

  9. python 面向对象、特殊方法与多范式、对象的属性及与其他语言的差异

    1.python 面向对象 文章内容摘自:http://www.cnblogs.com/vamei/archive/2012/06/02/2532018.html   1.__init__() 创建对 ...

  10. python面向对象(二)——类成员

    Python面向对象    类成员 1.字段         普通字段    属于对象         静态字段    属于类   2.方法 普通方法   触发者是对象    括号里至少一个参数 se ...

随机推荐

  1. NFS使用TrueNAS SCALE的好处

    之前一直习惯于使用linux自带的NFS服务,但由于NFS空间占用较大自身不带压缩能力,最近使用了号称比较流行的 TrueNAS SCALE 版本,重要的是它还可以提供块服务 Block (iSCSI ...

  2. DeepSeek崛起:程序员“饭碗”被抢,还是职业进化新起点?

    2025年伊始,Meta创始人扎克伯格的一则声明引发全球程序员热议:"AI将在今年达到中级工程师水平,逐步接管编程工作."与此同时,国产AI大模型DeepSeek的爆火,让一名8岁 ...

  3. hbase - [06] rowkey的设计

    HBase是三维有序存储的,通过rowkey(行键),column key(column family和qualifier)和TimeStamp(时间戳)这三个维度可以对HBase中的数据进行快速定位 ...

  4. 一套基于 Material Design 规范实现的 Blazor 和 Razor 通用组件库

    前言 今天大姚给大家分享一套基于 Material Design 规范实现的.开源(MIT license)且免费的 Blazor 和 Razor 通用组件库:MatBlazor. Blazor介绍 ...

  5. day3-运算符

    基本概念 运算符是一种特殊的符号,用于表示数据的运算.赋值.比较等 算数运算符 赋值运算符 比较运算符/关系运算符 逻辑运算符 位运算 其他运算符 算数运算符 对数值类型的变量进行运算 /基本运算,如 ...

  6. 代码托管平台对比分析:Gitee与GitLab

    一.Gitee:本土化服务的深度实践者 Gitee凭借对中国开发者需求的精准洞察,提供了多项针对性优化功能,尤其适合国内团队: 高速稳定的访问体验 服务器均部署于国内,代码拉取.推送及CI/CD流程的 ...

  7. 一个生成随机颜色的js函数

    function getRandomColor(){ let rgb = []; for(let i=0;i<3;++i){ let color = Math.floor(Math.random ...

  8. .netCore 使用 Quartz 实例

    一.参考源文链接 1.https://www.likecs.com/show-897836.html 2.https://blog.csdn.net/weixin_43614067/article/d ...

  9. C# Semaphore

    1.Semaphore定义Semaphore,是负责协调各个线程, 以保证它们能够正确.合理的使用公共资源.也是操作系统中用于控制进程同步互斥的量. Semaphore常用的方法有两个WaitOne( ...

  10. Vue3组合式API终极指南:从原理到实战,彻底掌握高效开发!

    前言 在Vue3从发布到今天,组合式API已成为现代前端开发的标杆设计模式.本文通过真实项目场景,深度解析组合式API的核心特性,配以完整代码示例,助你彻底掌握企业级Vue应用开发精髓. 一.为什么组 ...