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方法