• [转载]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方法
  • 相关阅读:
    《大道至简》读书笔记 第3篇
    《大道至简》读书笔记 第2篇
    返回一个二维整数数组中最大联通子数组的和(思路)
    《大道至简》读书笔记 第1篇
    给尊敬的王老师
    团队开发——冲刺2.g
    第一阶段冲刺的总结报告
    团队开发——冲刺2.f
    《人月神话》读书笔记 第3篇
    团队开发——冲刺2.e
  • 原文地址:https://www.cnblogs.com/mzc1997/p/7663052.html
Copyright © 2020-2023  润新知