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

我是九柄,公众号【 九柄 】,分享软件测试文章、面试、教程资料,欢迎来看看。

Python动态属性有什么用的更多相关文章

  1. Python动态属性和特性(一)

    在Python中,数据的属性和处理数据的方法统称为属性.其实,方式只是可调用的属性.除了这二者之外,我们还可以创建特性(property),在不改变类接口的前提下,使用存取方法(即读取值和设置值方法) ...

  2. PythonI/O进阶学习笔记_7.python动态属性,__new__和__init__和元类编程(上)

    content: 上: 1.property动态属性 2.__getattr__和__setattr__的区别和在属性查找中的作用 3.属性描述符 和属性查找过程 4.__new__和__init__ ...

  3. python 动态属性

    先来看一下一个常见的Python类的定义: class Person(object): name = None age = None def __init__(self,name,age): self ...

  4. Python动态属性和特性(二)

    内置的property经常用作装饰器,但它其实是一个类.在Python中,函数和类通常可以互换,因为二者都是可调用对象,而且没有实例化的new运算符,所以调用构造方法和调用工厂函数没有区别,只要能返回 ...

  5. Python进阶:@property 动态属性

    Python进阶:@property 动态属性 Python 动态属性的概念可能会被面试问到,在项目当中也非常实用,但是在一般的编程教程中不会提到,可以进修一下. 先看一个简单的例子.创建一个 Stu ...

  6. Python属性描述符(二)

    Python存取属性的方式特别不对等,通过实例读取属性时,通常返回的是实例中定义的属性,但如果实例未曾定义过该属性,就会获取类属性,而为实例的属性赋值时,通常会在实例中创建属性,而不会影响到类本身.这 ...

  7. Python属性描述符(一)

    描述符是对多个属性运用相同存取逻辑的一种方式,,是实现了特性协议的类,这个协议包括了__get__.__set__和__delete__方法.property类实现了完整的描述符协议.通常,可以只实现 ...

  8. Python中的动态属性与描述符

    动态属性与属性描述符 属性描述符是什么?   在解释属性查找顺序之前我们需要了解Python中的属性描述符,属性描述符作为其他类对象的属性而存在,实现了特殊方法中的get.set.delete中的一种 ...

  9. Python的高级特性5:谈谈python的动态属性

    正常情况下,当我们定义了一个class,创建了一个class的实例后,我们可以给该实例绑定任何属性和方法,这就是动态语言的灵活性. 看下面一种常见的get/set操作 In [174]: class ...

随机推荐

  1. Win10系统链接蓝牙设备

    1. 进入控制面板,选择 设备 2. 进入设备界面,删除已有蓝牙,如果蓝牙耳机已经链接其他设备,先断开链接 3. 点击添加蓝牙或其他设备 4. 选择蓝牙,选择你的蓝牙耳机名称

  2. this-4

    ES6函数里的this指的是定义这个函数时外层代码的this,可以理解为:1.ES6箭头函数没有自己的this:2.ES6箭头函数的this是外层代码(定义时,非执行时,也就是词法作用域)this的引 ...

  3. 管家婆软件工贸版(标准财务+进销存+生产管理)V18.0功能简介

    管家婆软件工贸版(标准财务+进销存+生产管理)V18.0功能简介 管家婆 工贸版(标准财务+进销存+生产管理) 1.整体介绍 管家婆工贸版系列软件是针对国内中小型生产加工企业,将ERP管理思想与几十万 ...

  4. 群晖下 gitea+drone+harbor实现CI/CD 发布到云服务器

    常用命令 sudo -i然后输入密码登录root账户(群晖默认只能使用admin账号登陆) vim xxx编辑(编辑是进去之后按i,退出并保存是按esc,然后:wq!再回车) mkdir xx创建文件 ...

  5. 通过python将阿里云DNS解析作为DDNS使用

    通过python将阿里云DNS解析作为DDNS使用 脚本需要Python2.x运行 安装alidns python sdk sudo pip install aliyun-python-sdk-ali ...

  6. 阿里云OSS + PicGo搭建图床

    1.阿里云 OSS 登录阿里云,进入控制台. 打开侧边栏,找到对象存储 OSS. 右侧找到 Bucket 管理,点击创建 Bucket. 根据引导配置 Bucket 其他同城冗余存储和版本控制等增值服 ...

  7. Java面试宝典学习笔记【2020】

    Java面试题总结 一.Java基础 1)Java有没有goto? goto是C语言中的,通常与条件语句配合使用,可用来实现条件转移, 构成循环,跳出循环体等功能.Java保留了这个关键字但是没有使用 ...

  8. 题解 P3831 [SHOI2012]回家的路

    什么叫分层图最短路,我不会/kk 感觉自己做法和其他题解不大一样所以过来发篇题解了. 未刻意卡常拿下最优解 题目大意 就是说给你一个 \(n \times n\) 的网格图和 \(m\) 个可换乘点, ...

  9. liunx 服务器下面安装mysql8.0

    闲来无事,准备自己搭建一个服务器高点事情,不可避免的就是需要使用到mysql数据库了.在Linux系统安装MySQL8.0,网上已经有很多的教程了,到自己安装的时候却发现各种各样的问题,现在把安装过程 ...

  10. 关于『Markdown』:第二弹

    关于『Markdown』:第二弹 建议缩放90%食用 道家有云:一生二,二生三,三生万物 为什么我的帖子不是这样 各位打工人们! 自从我学了Markdown以来 发现 Markdown 语法真的要比 ...