在Python中,私有属性以双下划线开头,例如"__private_attribute"。保护属性以单下划线开头,例如"_protected_attribute"。私有属性和保护属性都是用来限制对类属性的访问权限。
当一个类被继承时,子类会继承父类的所有属性和方法,包括私有属性和保护属性。但是,子类无法直接访问父类的私有属性。这是因为Python会将私有属性名字进行名称修饰,例如"_classname__private_attribute",以防止子类修改父类的私有属性。
子类可以访问父类的保护属性,但是无法直接访问父类的私有属性。如果子类想要访问父类的私有属性,可以通过调用父类的公共方法来间接地访问私有属性。例如:
class Parent:
def __init__(self):
self.__private_attribute = 42
self._protected_attribute = 13
def get_private_attribute(self):
return self.__private_attribute
class Child(Parent):
def get_private_attribute_of_parent(self):
return self.get_private_attribute()
parent = Parent()
child = Child()
print(parent._protected_attribute) # 输出: 13
print(child._protected_attribute) # 输出: 13
# 下面两行代码会报错,因为私有属性是不能直接访问的
#print(parent.__private_attribute)
#print(child.__private_attribute)
print(child.get_private_attribute_of_parent()) # 输出: 42
在子类中,可以通过调用父类的公共方法来访问父类的私有属性。在这个例子中,子类Child调用了父类Parent的公共方法get_private_attribute(),并通过该方法返回父类的私有属性值。
有一个Teacher类表示教师,它有一个私有属性__name和一个保护属性_salary。我们还有一个子类Professor表示教授,它继承了Teacher类。现在我们来看一下如何在子类中访问父类的私有属性和保护属性。
class Teacher:
def __init__(self, name, salary):
self.__name = name
self._salary = salary
def get_name(self):
return self.__name
def get_salary(self):
return self._salary
class Professor(Teacher):
def __init__(self, name, salary, research_area):
super().__init__(name, salary)
self.research_area = research_area
def get_name(self):
return f"Professor {self._Teacher__name}" # 使用父类的私有属性,需要进行名称修饰
def get_research_area(self):
return self.research_area
teacher = Teacher("Alice", 50000)
professor = Professor("Bob", 80000, "Computer Science")
print(teacher.get_name()) # 输出: Alice
print(teacher.get_salary()) # 输出: 50000
print(professor.get_name()) # 输出: Professor Bob
print(professor.get_salary()) # 输出: 80000
print(professor.get_research_area()) # 输出: Computer Science
在这个例子中,Teacher类有一个私有属性__name和一个保护属性_salary。Professor类继承了Teacher类,并添加了一个research_area属性。在Professor类中,我们重写了get_name()方法来使用父类的私有属性。我们可以看到,在子类中通过调用父类的公共方法来访问父类的保护属性。
其中
def get_name(self):
return f"Professor {self.__name}" # 使用父类的私有属性,需要进行名称修饰
如果不修饰为return f"Professor {self._Teacher__name}" # 。如果我们直接使用self.__name来访问父类的私有属性,会导致AttributeError异常。因为Python会将私有属性的名称进行名称修饰,以防止子类修改父类的私有属性。