Python中的@property像访问属性一样调用方法示例

 更新时间:2026年05月29日 09:43:46   作者:程序员榴莲  
property是Python中的一个内置函数,用于在类中创建和管理属性的getter和setter方法,这篇文章主要介绍了Python中@property像访问属性一样调用方法的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
# Python 中的 @property:像访问属性一样调用方法
在写类的时候,我们经常会遇到一个问题:  
对象的属性如果可以被随便修改,就可能出现一些不合理的数据。
比如一个人的年龄:
```python
class Person:
    def __init__(self, age):
        self.age = age

然后创建对象:

person1 = Person(-18)
print(person1.age)

这时候程序是可以正常运行的,但是很明显不合理。

因为年龄不可能是负数。

再比如学生成绩:

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

创建对象:

student1 = Student(100)
print(student1.score)

一开始这样写没什么问题。

但是如果外界可以随便修改:

student1.score = -100

那就会出现不合理的数据。

所以问题来了:
Python 有没有像 Java 一样,可以把属性保护起来,然后只暴露指定的接口让外界调用呢?

答案是有的。

在 Python 中,我们可以使用 @property 装饰器来控制属性的访问。

一、为什么需要属性访问控制

如果一个属性可以被外界随便赋值,那么数据就可能变得不安全。

比如:

person1 = Person(-18)

这个对象虽然创建成功了,但是 -18 这个年龄明显是不合理的。

我们希望在给 age 赋值的时候,能够先判断一下:

if age < 0 or age > 120:
    raise ValueError("不合理的年龄")

如果年龄不合理,就直接抛出异常。

二、使用 @property 定义属性

完整代码如下:

class Person:
    def __init__(self, age):
        self.age = age

    @property
    def age(self):
        return self._age

    @age.setter
    def age(self, age):
        if age < 0 or age > 120:
            raise ValueError('不合理的年龄')
        self._age = age


person1 = Person(18)
print(person1.age)

这段代码中,最重要的部分就是:

@property
def age(self):
    return self._age

@property 的作用是:

把一个方法变成属性一样来访问。

也就是说,虽然 age 本质上是一个方法:

def age(self):
    return self._age

但是我们调用的时候不需要写成:

person1.age()

而是可以直接写:

person1.age

看起来就像是在访问普通属性一样。

三、使用 setter 控制赋值

下面这段代码用来控制给 age 赋值:

@age.setter
def age(self, age):
    if age < 0 or age > 120:
        raise ValueError('不合理的年龄')
    self._age = age

当我们执行:

self.age = age

或者:

person1.age = 18

实际上都会自动调用这个 setter 方法。

所以在赋值之前,程序会先判断年龄是否合法:

if age < 0 or age > 120:
    raise ValueError('不合理的年龄')

如果年龄小于 0,或者大于 120,就会抛出异常。

如果年龄合理,才会真正赋值:

self._age = age

四、为什么使用 _age

在代码中,真正保存年龄的属性是:

self._age

而不是:

self.age

这是因为 self.age 已经被 @property@age.setter 接管了。

如果在 setter 里面继续写:

self.age = age

就会再次调用 setter,导致无限递归。

所以我们用:

self._age = age

来真正保存数据。

这里的 _age 前面有一个下划线,表示这是一个内部使用的属性,不建议外界直接访问。

五、创建对象时发生了什么

当我们创建对象:

person1 = Person(18)

会先执行构造方法:

def __init__(self, age):
    self.age = age

这里的:

self.age = age

并不是简单地创建一个普通属性。

因为类里面已经定义了:

@age.setter
def age(self, age):

所以这句代码会自动调用 setter 方法。

也就是说,创建对象的时候,年龄就已经被检查了一遍。

如果写成:

person1 = Person(-18)

就会抛出异常:

ValueError: 不合理的年龄

这样就避免了创建出不合理的对象。

六、读取属性时发生了什么

当我们执行:

print(person1.age)

这里的 .age 其实不是直接访问属性,而是在调用这个方法:

@property
def age(self):
    return self._age

只不过 @property 让它看起来像普通属性一样。

所以:

person1.age

本质上相当于调用了 getter 方法。

七、@property 的好处

使用 @property 有几个好处:

  1. 可以像访问普通属性一样访问方法
  2. 可以在赋值时增加数据校验
  3. 可以保护对象内部数据
  4. 可以让代码更加安全
  5. 对外使用简单,对内逻辑可控

比如外界仍然可以这样写:

person1.age

也可以这样赋值:

person1.age = 20

但是赋值的时候,程序会自动帮我们检查数据是否合法。

八、总结

@property 装饰器可以把方法伪装成属性来访问。

它通常和 setter 一起使用:

@property
def age(self):
    return self._age

@age.setter
def age(self, age):
    if age < 0 or age > 120:
        raise ValueError('不合理的年龄')
    self._age = age

这样做的好处是:

既保留了属性访问的简洁写法,又可以在内部控制数据是否合法。

简单来说:

@property

负责读取属性。

@属性名.setter

负责设置属性。

在这个例子中,我们通过 @property@age.setter,让 age 属性不能被随便设置成不合理的值。

这就是 Python 中属性访问控制的一种常见写法。

相关文章

  • python跨文件使用全局变量的实现

    python跨文件使用全局变量的实现

    这篇文章主要介绍了python跨文件使用全局变量的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • pandas数据分组groupby()和统计函数agg()的使用

    pandas数据分组groupby()和统计函数agg()的使用

    这篇文章主要介绍了pandas数据分组groupby()和统计函数agg()的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03
  • 对python中的pop函数和append函数详解

    对python中的pop函数和append函数详解

    今天小编就为大家分享一篇对python中的pop函数和append函数详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-05-05
  • Python模拟简易版淘宝客服机器人的示例代码

    Python模拟简易版淘宝客服机器人的示例代码

    这篇文章主要介绍了Python模拟简易版淘宝客服机器人的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03
  • tensorflow安装成功import tensorflow 出现问题

    tensorflow安装成功import tensorflow 出现问题

    这篇文章主要介绍了tensorflow安装成功import tensorflow 出现问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-04-04
  • python渗透测试linux密码激活的示例

    python渗透测试linux密码激活的示例

    这篇文章主要介绍了python渗透测试linux密码激活的相关知识,通过一个crypt的示例给大家介绍的非常详细,对大家学习python渗透知识有很大的帮助,需要的朋友可以参考下
    2021-05-05
  • 分享Pandas库中的一些宝藏函数transform()

    分享Pandas库中的一些宝藏函数transform()

    Pandas具有很多强大的功能,transform就是其中之一,利用它可以高效地汇总数据且不改变数据行数,transform是一种什么数据操作?如果熟悉SQL的窗口函数,就非常容易理解了
    2021-09-09
  • wxPython学习之主框架实例

    wxPython学习之主框架实例

    这篇文章主要介绍了wxPython学习之主框架应用实例,以一个基础的弹出窗体实例讲述了wxPython主框架应用程序的实现方法,需要的朋友可以参考下
    2014-09-09
  • Python使用正则匹配实现抓图代码分享

    Python使用正则匹配实现抓图代码分享

    本文给大家分享的是个人的第一个作品,使用Python正则匹配实现抓图代码,非常的简单实用,推荐给大家,小伙伴们可以自由扩展下。
    2015-04-04
  • Python2.7版os.path.isdir中文路径返回false的解决方法

    Python2.7版os.path.isdir中文路径返回false的解决方法

    这篇文章主要为大家详细介绍了Python2.7版os.path.isdir中文路径返回false的解决方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-06-06

最新评论