Python使用@property装饰器--getter和setter方法变成属性

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python使用@property装饰器--getter和setter方法变成属性相关的知识,希望对你有一定的参考价值。

原贴:为什么Python不需要getter和setter

getter 和 setter在java中被广泛使用。一个好的java编程准则为:将所有属性设置为私有的,同时为属性写getter和setter函数以供外部使用。 这样做的好处是属性的具体实现被隐藏,当未来需要修改时,只需要修改getter 和 setter即可,而不用修改代码中所有引用这个属性的地方。可能做的修改为:

  • 在获取或设置属性时打一条日志
  • 设置属性时,对值对进检查
  • 设置发生时, 修改设置的值
  • 获取属性时,动态地计算值

可谓是好处多多,getter和setter为变量访问提供了灵活的方式。

但python中情况却不同,因为对象属性访问的机制不同。java中需要为变量写getter和setter的原因为:当我们写这样的表达式 Person.name来获取一个Person对象的name属性时,这个表达式的意义是固定的,它就是获取这个属性,而不可能触发一个函数的调用。但对于python, 这个表达式即可能是直接获取一个属性,也可能会调用一个函数。这取决 Person类的实现方式。也就是说,python的对象属性访问的语法,天然就提供了getter和setter的功能。

由于这个区别,我们没有必要在python中为每个对象的属性写getter和setter。最开始时,我们总是将属性作为一个直接可访问的属性。当后续需要对这个属性的访问进行一些控制时,我们可以将其修改为函数触发式属性。在修改前后,调用这个对象属性的代码不用修改,因为还是使用相同的语法来访问这个属性。

public class Student{  
        private String number;//学生学号  
        private String name;//学生姓名  
        private int grade;//学生成绩  
        public Student(){  
        }  
        public String getNumber(){//用get方法得到学号(下同)  
            return number;  
        }  
        public void setNumber(String number){//用set方法去设置学号(下同)  
            this.number=number;  
        }  
        public String getName(){  
            return name;  
        }  
        public void setName(String name){  
            this.name=name;  
        }  
        public int getGrade(){  
            return grade;  
        }  
        public void setGrade(int grade){  
            this.grade=grade;  
        }  
    public static void main(String agrs[]){  
    Student st=new Student();  
    st.setNumber("010112233");  
    st.setName("小明");  
    st.setGrade(100);  
    System.out.println("学号为:"+st.getNumber()+","+"姓名为:"+st.getName()+","+"成绩为:"+st.getGrade()+"。");  
  }  
}  

用setter来改变数据成员的值时,操作必须由这个对象自己来触发
用public来改变数据成员的值时,操作可以由任何对象来触发
这是面向对象的封装,总之就是自己的数据成员,只对自己可见,也只有自己才能改变其值

对象的封装性,
private的只有对象自己才可以访问,其他任何对象不行,包括它的子类和父类。安全性高,其他对象只能通过它的public方法,set,get来获取或设置原对象的private属性。
public其他对象可以访问,安全性就不高了。

 

在Python中

可以使用@property 装饰器将一个直接访问的属性转变为函数触发式属性。如下所示,使用@property前的代码为

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

person = Person("Tom")
>>>print(person.name)
tom

使用@property

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

    @property #getter方法
    def name(self):
        return self._name

    @name.setter  #在setter方法中可以约束属性,非str将捕获一个type错误
    def name(self,name):
         if not isinstance(name, str):
            raise TypeError("Expected a string")
        self._name = name

p = Person(tom)
>>>print(p.name)
tom

>>>p1 = Person(123)
typeerror:Expected a string

还可以只给getter方法,不写setter方法,相当于对参数的写入保护

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

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

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

    @property
    def birth(self):
        return 2017-self._age

p = Person(20)
>>>print(p.age)
20
>>>print(p.birth)
1997

>>>p.birth = 1997
Attribute error #birth不存在setter方法

 






以上是关于Python使用@property装饰器--getter和setter方法变成属性的主要内容,如果未能解决你的问题,请参考以下文章

Python @property装饰器

python描述符property函数(类)装饰器实例解析

python 描述符 上下文管理协议 类装饰器 property metaclass

Python入门-6面向对象编程:06私有属性和私有方法(实现封装)-@property装饰器-get和set方法-总结

Python-面向对象之property装饰器的实现(数据描述器)

十四 —— 装饰器