Python 使用@property对属性进行数据规范性校验的实现

在绑定属性时,如果我们直接把属性暴露出去,虽然写起来很简单,但是,没办法检查参数,导致可以把成绩随便改:

s = Student()
s.score = 9999

这显然不合逻辑。为了限制score的范围,可以通过一个​​set_score()​​方法来设置成绩,再通过一个​​get_score()​​来获取成绩,这样,在​​set_score()​​方法里,就可以检查参数:

class Student(object):

    def get_score(self):
         return self._score

    def set_score(self, value):
        if not isinstance(value, int):
            raise ValueError('score must be an integer!')
        if value < 0 or value > 100:
            raise ValueError('score must between 0 ~ 100!')
        self._score = value

现在,对任意的Student实例进行操作,就不能随心所欲地设置score了:

>>> s = Student()
>>> s.set_score(60) # ok!
>>> s.get_score()
60
>>> s.set_score(9999)
Traceback (most recent call last):
  ...
ValueError: score must between 0 ~ 100!

但是,上面的调用方法又略显复杂,没有直接用属性这么直接简单。

有没有既能检查参数,又可以用类似属性这样简单的方式来访问类的变量呢?对于追求完美的Python程序员来说,这是必须要做到的!

还记得装饰器(decorator)可以给函数动态加上功能吗?对于类的方法,装饰器一样起作用。Python内置的​​@property​​装饰器就是负责把一个方法变成属性调用的:

class Student(object):

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

    @score.setter
    def score(self, value):
        if not isinstance(value, int):
            raise ValueError('score must be an integer!')
        if value < 0 or value > 100:
            raise ValueError('score must between 0 ~ 100!')
        self._score = value

​​@property​​的实现比较复杂,我们先考察如何使用。把一个getter方法变成属性,只需要加上​​@property​​就可以了,此时,​​@property​​本身又创建了另一个装饰器​​@score.setter​​,负责把一个setter方法变成属性赋值,于是,我们就拥有一个可控的属性操作:

>>> s = Student()
>>> s.score = 60 # OK,实际转化为s.set_score(60)
>>> s.score # OK,实际转化为s.get_score()
60
>>> s.score = 9999
Traceback (most recent call last):
  ...
ValueError: score must between 0 ~ 100!

注意到这个神奇的​​@property​​,我们在对实例属性操作的时候,就知道该属性很可能不是直接暴露的,而是通过getter和setter方法来实现的。

还可以定义只读属性,只定义getter方法,不定义setter方法就是一个只读属性:

class Student(object):

    @property
    def birth(self):
        return self._birth

    @birth.setter
    def birth(self, value):
        self._birth = value

    @property
    def age(self):
        return 2015 - self._birth

上面的​​birth​​是可读写属性,而​​age​​就是一个只读属性,因为​​age​​可以根据​​birth​​和当前时间计算出来。

要特别注意:属性的方法名不要和实例变量重名。例如,以下的代码是错误的:

class Student(object):

    # 方法名称和实例变量均为birth:
    @property
    def birth(self):
        return self.birth

这是因为调用​​s.birth​​时,首先转换为方法调用,在执行​​return self.birth​​时,又视为访问​​self​​的属性,于是又转换为方法调用,造成无限递归,最终导致栈溢出报错​​RecursionError​​。

小结

​​@property​​广泛应用在类的定义中,可以让调用者写出简短的代码,同时保证对参数进行必要的检查,这样,程序运行时就减少了出错的可能性。

练习

请利用​​@property​​给一个​​Screen​​对象加上​​width​​和​​height​​属性,以及一个只读属性​​resolution​​:

# -*- coding: utf-8 -*-
# 测试:
s = Screen()
s.width = 1024
s.height = 768
print('resolution =', s.resolution)
if s.resolution == 786432:
print('测试通过!')
else:
print('测试失败!')

完整源码:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

class Student(object):

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

@score.setter
def score(self, value):
if not isinstance(value, int):
raise ValueError('score must be an integer!')
if value < 0 or value > 100:
raise ValueError('score must between 0 ~ 100!')
self._score = value

s = Student()
s.score = 60
print('s.score =', s.score)
# ValueError: score must between 0 ~ 100!
s.score = 9999

到此这篇关于Python 使用@property对属性进行数据规范性校验的实现的文章就介绍到这了,更多相关Python @property 属性校验内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Python进阶之@property动态属性的实现

    Python 动态属性的概念可能会被面试问到,在项目当中也非常实用,但是在一般的编程教程中不会提到,可以进修一下. 先看一个简单的例子.创建一个 Student 类,我希望通过实例来获取每个学生的一些情况,包括名字,成绩等.成绩只有等到考试结束以后才会有,所以实例化的时候不会给它赋值. class Student: def __init__(self, name): self.name = name self.score = None mike = Student('mike') 考试完以后,准

  • 属性与 @property 方法让你的python更高效

    一.用属性替代 getter 或 setter 方法 以下代码中包含手动实现的 getter(get_ohms) 和 setter(set_ohms) 方法: class OldResistor(object): def __init__(self, ohms): self._ohms = ohms self.voltage = 0 self.current = 0 def get_ohms(self): return self._ohms def set_ohms(self, ohms): s

  • Python 类,property属性(简化属性的操作),@property,property()用法示例

    本文实例讲述了Python 类,property属性(简化属性的操作),@property,property()用法.分享给大家供大家参考,具体如下: property属性的创建方式有两种:1.@property装饰器方式   2.类属性方式 ( 类属性=property() ) property属性可以简化实例对象对属性的操作(获取.设置),可以对属性做类型校验和预处理等. 装饰器方式: demo.py(@property,获取属性值,旧式类与新式类都有的方式): class Goods: @

  • Python 使用@property对属性进行数据规范性校验的实现

    在绑定属性时,如果我们直接把属性暴露出去,虽然写起来很简单,但是,没办法检查参数,导致可以把成绩随便改: s = Student() s.score = 9999 这显然不合逻辑.为了限制score的范围,可以通过一个​​set_score()​​方法来设置成绩,再通过一个​​get_score()​​来获取成绩,这样,在​​set_score()​​方法里,就可以检查参数: class Student(object): def get_score(self): return self._sco

  • Python高级property属性用法实例分析

    本文实例讲述了Python高级property属性用法.分享给大家供大家参考,具体如下: property属性 1.property属性: 是一个提高开发者用户体验度的属性,可以将一个函数改造的像属性一样. 例: # 定义的时候像是一个函数 使用的时候和属性的方式是以样的 class Foo(object): @property def money(self): return 100 # f = Foo() # m = f.money() # print(m) f = Foo() print(f

  • Python中property属性的用处详解

    目录 前言 限制值 使用 @property 的方式代替. 动态属性的好处 动态显示 附:用property代替getter和setter方法 总结 前言 Python 动态属性的概念可能会被面试问到,在项目当中也非常实用,但是在一般的编程教程中不会提到,可以进修一下. 先看一个简单的例子.创建一个 Student 类,我希望通过实例来获取每个学生的一些情况,包括名字,成绩等.成绩只有等到考试结束以后才会有,所以实例化的时候不会给它赋值. class Student: def __init__(

  • python中的property及属性与特性之间的优先权

    目录 前言 属性(attribute) 属性的定义 属性的用法 特性(property) 特性的定义 特性的用法 特性的使用场景 属性和特性之间的差别和联系 属性和特性之间的优先权 前言 这几天看<流畅的python>这本书了,在一个示例中又看到了property作为装饰器在使用,因为很久没有用这个东西了,对它的一些特性和使用方法等都不是很熟悉,所以又专门在搜了几篇博客和在官方文档中学习了它的相关用法.再者又刚好学到了python中的属性(attribute),所以刚好这两者可以两相对比,也许

  • Python中property属性实例解析

    本文主要讲述的是对Python中property属性(特性)的理解,具体如下. 定义及作用: 在property类中,有三个成员方法和三个装饰器函数. 三个成员方法分别是:fget.fset.fdel,它们分别用来管理属性访问: 三个装饰器函数分别是:getter.setter.deleter,它们分别用来把三个同名的类方法装饰成property. fget方法用来管理类实例属性的获取,fset方法用来管理类实例属性的赋值,fdel方法用来管理类实例属性的删除: getter装饰器把一个自定义类

  • python中property属性的介绍及其应用详解

    Python的property属性的功能是:property属性内部进行一系列的逻辑计算,最终将计算结果返回. 使用property修饰的实例方法被调用时,可以把它当做实例属性一样 property的用法1--装饰器方式 在类的实例方法上应用@property装饰器 class Test: def __init__(self): self.__num = 100 @property def num(self): print("--get--") return self.__num @n

  • python基于property()函数定义属性

    这篇文章主要介绍了python基于property()函数定义属性,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 正常情况下,类包含的属性应该是隐藏的,只允许通过类提供的方法来间接的实现对类属性的访问和操作. class Person: #构造函数 def __init__(self, name): self.name = name #设置name属性值的函数 def setname(self, name): self.name = name

  • python中@Property属性使用方法

    目录 一.前言 二.创建用于计算的属性 三.为属性添加安全保护机制 一.前言 本文介绍的属性与类属性和实例属性不同.类属性和实例属性介绍的属性将返回所存储的值.而本文要介绍的属性是一种特殊的属性,访问它时将计算它的值.另外,该属性还可以为属性添加安全保护机制. 二.创建用于计算的属性 在Python中,可以通过@property(装饰器)将一个方法转换为属性,从而实现用于计算的属性.将方法转换为属性后,可以直接通过方法名来访问方法,而不需要再添加一对小括号“()”,这样可以让代码更简洁. 通过@

  • Python中property函数用法实例分析

    本文实例讲述了Python中property函数用法.分享给大家供大家参考,具体如下: 通常我们在访问和赋值属性的时候,都是在直接和类(实例的)的__dict__打交道,或者跟数据描述符等在打交道.但是假如我们要规范这些访问和设值方式的话,一种方法是引入复杂的数据描述符机制,另一种恐怕就是轻量级的数据描述符协议函数Property().它的标准定义是: + property(fget=None,fset=None,fdel=None,doc=None) + 前面3个参数都是未绑定的方法,所以它们

  • Python中静态方法,类方法,属性方法使用方法

    目录 1.静态方法 2.类方法 3.静态方法与类方法总结 4.属性方法 1.静态方法 通过@staticmethod装饰器即可把其装饰的方法变为一个静态方法,什么是静态方法呢?其实不难理解,普通的方法,可以在实例化后直接调用,并且在方法里可以通过self.调用实例变量或类变量,但静态方法是不可以访问实例变量或类变量的,一个不能访问实例变量和类变量的方法,其实相当于跟类本身已经没什么关系了,它与类唯一的关联就是需要通过类名来调用这个方法 应用: 对与一个类,我们要调用它的一个方法,必须要绑定实例,

随机推荐