Python的property属性详细讲解


Posted in Python onApril 11, 2022

前言

Python 动态属性的概念可能会被面试问到,在项目当中也非常实用,但是在一般的编程教程中不会提到,可以进修一下。

先看一个简单的例子。创建一个 Student 类,我希望通过实例来获取每个学生的一些情况,包括名字,成绩等。成绩只有等到考试结束以后才会有,所以实例化的时候不会给它赋值。

class Student:
    def __init__(self, name):
        self.name = name
        self.score = None

mike = Student('mike')

考试完以后,准备给 mike 打分:

mike.score = 999

在这里,老师一不小心多打了个 9 ,通常来说打分都是 100 分值,999 是一个非法数据,不应该赋值成功。学生一多,老师打分出现手误的情况肯定会越来越多,所以我们必须想办法修改程序,限制 score 的值必须在 0-100 分。

限制值

我们定义一个方法,如果输入的不是 0-100 的整数,就让程序报错,数据合法,我们就把 score 属性修改成功。

def set_score(self, new_score):
    if not isinstance(new_score, int):
        raise ValueError('score must be int')

    if 0 <= new_score <= 100:
        self.score = new_score
        return self.score
    else:
        raise ValueError('score invalid')

这样我们每次需要获取成绩的时候使用 self.score 获取,修改成绩的时候调用函数来修改:

mike.set_score(999)

调用以后会报错,因为 999 是非法数据。注意,这个时候我使用 self.score 还是可以进行设置,而且不报错:

self.score = 999

这显然是不行的。所以我们要提供一种机制,把 score 变成私有属性,不能让外部访问。很遗憾,python 的私有属性是伪私有。通常我们把 _ 开头的属性叫私有属性,但是这只是一种协议和规定,你看到下划线开头的属性,不要去访问了。你硬要访问,是可以的,python 并不会禁止。

使用 @property 的方式代替。

上面的方法虽然实现了功能,但是改变了属性的使用方式。平常是这样使用的:

# 获取属性
a = mike.score
# 设置属性
mike.score = 99

@property
def score(self):
    return self._score

@score.setter
def score(self, new_score):
    if not isinstance(new_score, int):
        raise ValueError('score must be int')

        if 0 <= new_score <= 100:
            self._score = new_score
            return self._score
        else:
            raise ValueError('score invalid')

动态属性的好处

  • 统一了调用方式。self.score = 99 的方式,而不是函数调用的方式。
  • _score 我们就不直接去使用了。你要用也可以,不建议。
  • 如果我们一个属性只可以读,把 setter 部分注释掉就可以了。

现在我们来完善这个类,添加 birth 属性和年龄属性:

from datetime import datetime

class Student:
    def __init__(self, name, birth=1920):
        self.name = name
        self._score = None
        self.birth = birth
        self.age = datetime.now().year - self.birth

mike = Student('mike')
print(mike.birth)
print(mike.age)
  • birth 和 age 这两个是可以根据一个求出另外一个的。存在数据冗余问题。

  • age 属性这样是有问题的。mike 初始化的时候,age 已经被求出来了,如果我在下一年再去访问 age 属性,那他就是个错误的值。可以通过把 age 设成现在的秒数来验证:

    self.age = datetime.now().second
    
    mike = Student('mike')
    time.sleep(5)
    print(mike.age)
    print(datetime.now().second)

动态显示

@property
def age(self):
    return datetime.now().year - self.birth

注意,这里不要去设置 @age.setter ,因为他是动态变化的,你修改了会造成数据不一致,它只能作为一个只读属性。

@property 作用和应用场景:

  • @property 优化了属性读取和设置的可读性
  • 需要限制属性的特征;
  • 只读属性。如果属性只可以读,不可以写,用起来很方便。
  • 这个属性根据一个变化的环境动态改变。

附:用property代替getter和setter方法

>>>class Watermelon():
       def __init__(self,price):
           self._price = price                  #私有属性,外部无法修改和访问

       def get_price(self):
           return self._price

       def set_price(self,new_price):
           if new_price > 0:
               self._price = new_price
           else:
               raise 'error:价格必须大于零'

用property代替getter和setter

>>>class Watermelon():
       def __init__(self,price):
           self._price = price

       @property                          #使用@property装饰price方法
       def price(self):
           return self._price

       @price.setter                      #使用@property装饰方法,当对price赋值时,调用装饰方法
       def price(self,new_price):
           if new_price > 0:
               self._price = new_price
           else:
               raise 'error:价格必须大于零'
 
>>> watermelon = Watermelon(4)
>>> 
>>> watermelon.price
4
>>> 
>>> watermelon.price = 7
>>> 
>>> watermelon.price
7
Python 相关文章推荐
python判断字符串是否纯数字的方法
Nov 19 Python
Python中__name__的使用实例
Apr 14 Python
详解python时间模块中的datetime模块
Jan 13 Python
vue.js实现输入框输入值内容实时响应变化示例
Jul 07 Python
Python实现的括号匹配判断功能示例
Aug 25 Python
Python操作rabbitMQ的示例代码
Mar 19 Python
Pandas之DataFrame对象的列和索引之间的转化
Jun 25 Python
用sqlalchemy构建Django连接池的实例
Aug 29 Python
VSCode基础使用与VSCode调试python程序入门的图文教程
Mar 30 Python
浅谈keras保存模型中的save()和save_weights()区别
May 21 Python
Python使用Selenium实现淘宝抢单的流程分析
Jun 23 Python
pycharm 使用anaconda为默认环境的操作
Feb 05 Python
OpenCV项目实践之停车场车位实时检测
Python进程池与进程锁之语法学习
Python进程间的通信之语法学习
Python+Matplotlib图像上指定坐标的位置添加文本标签与注释
浅析Python OpenCV三种滤镜效果
实战Python爬虫爬取酷我音乐
用PYTHON去计算88键钢琴的琴键频率和音高
You might like
PHP语法速查表
2007/01/02 PHP
PHP 截取字符串 分别适合GB2312和UTF8编码情况
2009/02/12 PHP
PHP递归遍历多维数组实现无限分类的方法
2016/05/06 PHP
浅谈PHP中的面向对象OOP中的魔术方法
2017/06/12 PHP
Laravel 修改默认日志文件名称和位置的例子
2019/10/17 PHP
简易js代码实现计算器操作
2013/04/15 Javascript
Js实现手机发送验证码时按钮延迟操作
2014/06/20 Javascript
Json实现异步请求提交评论无需跳转其他页面
2014/10/11 Javascript
javascript关于继承的用法汇总
2014/12/20 Javascript
angularJS 中$attrs方法使用指南
2015/02/09 Javascript
动态设置form表单的action属性的值的简单方法
2016/05/25 Javascript
JavaScript 函数节流详解及方法总结
2017/02/09 Javascript
javascript编写简易计算器
2017/05/06 Javascript
elementUI Vue 单个按钮显示和隐藏的变换功能(两种方法)
2018/09/04 Javascript
angular的输入和输出的使用方法
2018/09/22 Javascript
浅谈Vue.js组件(二)
2019/04/09 Javascript
Vue.js组件通信之自定义事件详解
2019/10/19 Javascript
Vue + Element-ui的下拉框el-select获取额外参数详解
2020/08/14 Javascript
[01:34:42]NAVI vs EG 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/17 DOTA
python中字符串类型json操作的注意事项
2017/05/02 Python
Python饼状图的绘制实例
2019/01/15 Python
python opencv 图像拼接的实现方法
2019/06/27 Python
flask 实现token机制的示例代码
2019/11/07 Python
python+pygame实现坦克大战小游戏的示例代码(可以自定义子弹速度)
2020/08/11 Python
如何将anaconda安装配置的mmdetection环境离线拷贝到另一台电脑
2020/10/15 Python
Python用SSH连接到网络设备
2021/02/18 Python
python 制作磁力搜索工具
2021/03/04 Python
css3 column实现卡片瀑布流布局的示例代码
2018/06/22 HTML / CSS
美国男士和女士奢侈品折扣手表购物网站:Certified Watch Store
2018/06/13 全球购物
俄罗斯马克西多姆家居用品网上商店:Максидом
2020/02/06 全球购物
中文教师求职信
2014/02/22 职场文书
小学班级口号
2014/06/09 职场文书
《微笑着面对生活》优秀演讲稿范文
2014/09/23 职场文书
python数据分析之用sklearn预测糖尿病
2021/04/22 Python
golang gopm get -g -v 无法获取第三方库的解决方案
2021/05/05 Golang
python 爬取京东指定商品评论并进行情感分析
2021/05/27 Python