Python 面向对象编程:公有属性、私有属性、私有方法与继承
Python 是一种支持面向对象编程(OOP)的语言,面向对象编程强调将数据和操作数据的函数封装在一起,并通过类和对象来实现代码复用、模块化和数据保护。
下面是面向对象编程中几个核心概念:公有属性、私有属性、私有方法和继承,分别进行详细讲解。
1. 公有属性与私有属性
公有属性
公有属性是指可以在类的外部直接访问和修改的属性。它是默认的属性类型,在类内部定义时,不使用任何特殊符号标记。
和普通写法没什么区别
示例代码:
class Person:
def __init__(self, name, age):
self.name = name # 公有属性
self.age = age # 公有属性
# 创建实例
person = Person("Alice", 30)
print(person.name) # 直接访问公有属性
person.age = 31 # 修改公有属性
print(person.age) # 输出修改后的公有属性
私有属性
私有属性是指类外部不能直接访问或修改的属性,通常用于限制外部代码对类内部数据的访问。私有属性通过在属性名前加上双下划线(__)来标识。
在属性名前面添加了两个下划线就成了私有属性
示例代码:
class Person:
def __init__(self, name, age):
self.__name = name # 私有属性
self.__age = age # 私有属性
def get_name(self): # 提供公共方法访问私有属性
return self.__name
def set_name(self, name): # 提供公共方法修改私有属性
self.__name = name
# 创建实例
person = Person("Alice", 30)
print(person.get_name()) # 通过方法访问私有属性
person.set_name("Bob") # 通过方法修改私有属性
print(person.get_name())
输出结果
'''
Alice
Bob
'''
在方法里面调用也需要添加两个下划线
注意:
- 私有属性无法通过实例直接访问,如
person.__name会抛出错误。 - 可以通过
get_name()和set_name()等方法间接访问或修改私有属性。
强制访问私有属性
尽管 Python 强烈建议使用私有属性,但由于 Python 是一种动态语言,私有属性仍然可以通过 _ClassName__attribute 访问。虽然这并不推荐,但可以在调试时使用。
语法
print(实例变量名._类名字__私有属性名) # 强制访问私有属性
示例代码:
print(person._Person__age) # 强制访问私有属性,输出 30
小结
- 公有属性:类外部可以直接访问和修改的属性。
- 私有属性:类外部不能直接访问和修改的属性,通常通过类内部的方法来操作。
2. 公有方法与私有方法
公有方法
公有方法是指可以在类的外部直接调用的方法。它用于执行类中的某些操作,提供类的外部接口。默认情况下,方法是公有的,除非显式指定为私有方法。
示例代码:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def greet(self): # 公有方法
print(f"Hello, my name is {self.name} and I am {self.age} years old.")
# 创建实例
person = Person("Alice", 30)
person.greet() # 直接调用公有方法
私有方法
私有方法是指仅限于类内部使用,不能从类的外部调用的方法。通过在方法名前加上双下划线(__)来标识私有方法。
示例代码:
class Person:
def __init__(self, name, age):
self.__name = name
self.__age = age
def __calculate_years_left(self): # 私有方法
return 100 - self.__age
def display_info(self):
print(f"Name: {self.__name}, Age: {self.__age}")
print(f"Years left to 100: {self.__calculate_years_left()}") # 调用私有方法
# 创建实例
person = Person("Alice", 30)
person.display_info() # 可以调用公有方法,但私有方法不能直接访问
注意:
- 私有方法不能从类外部直接调用,如
person.__calculate_years_left()会抛出错误AttributeError - 可以通过类内部的方法间接调用私有方法。
强制访问私有方法
尽管 Python 强烈建议使用私有方法,私有方法仍然可以通过 _ClassName__method 强制访问,但不推荐这样做。
和访问私有属性大同小异
print(person._Person__calculate_years_left()) # 强制访问私有方法
总结
- 公有方法:类外部可以直接调用的方法。
- 私有方法:类外部不能直接调用的方法,通常用于类的内部逻辑。
3. 继承
继承概念
继承是 OOP 中的一个重要概念,它允许一个类(子类)继承另一个类(父类)的属性和方法。继承可以实现代码重用,并且使得代码结构更具层次性。
抽象理解:我继承了爸爸的家产,他的东西都归我
语法:
class 定义的类名(继承的类名):
示例代码:
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
print(f"{self.name} makes a sound")
class Dog(Animal): # Dog 类继承 Animal 类
def __init__(self, name, breed):
super().__init__(name) # 调用父类构造函数
self.breed = breed
def speak(self): # 重写父类的方法
print(f"{self.name} barks")
# 创建 Dog 类的实例
dog = Dog("Buddy", "Golden Retriever")
dog.speak() # 调用重写的 speak 方法
print(dog.breed) # 访问子类的属性
方法重写(Overriding)
子类可以重写父类的方法,提供更具体的实现。比如在 Dog 类中,speak 方法被重写
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
print(f"{self.name} 我是父类Animal")
# 创建一个 Animal 类的实例
animal = Animal("父类属性")
# 重写父类的 speak 方法的
class Dog(Animal):
def __init__(self, name, breed):
self.name = name
self.breed = breed
def speak(self): # 重写父类的 speak 方法
print(f"{self.name} 我是子类Dog")
# 创建一个 Dog 类的实例
dog = Dog("子类属性1", "子类属性2")
print(dog.name) # 输出 子类属性2
print(dog.breed) # 输出 '子类属性1'
dog.speak() # 调用重写的 speak 方法 输出 子类属性1 我是子类Dog
# 输出:
'''
子类属性1
子类属性2
子类属性1 我是子类Dog
'''
解释:
- 父类
Animal:- 定义了构造方法
__init__(self, name),用于初始化name属性。 - 定义了一个方法
speak(self),输出{self.name} 我是父类Animal。
- 定义了构造方法
2 子类 Dog:
- 重写了父类的
speak方法
3 输出:
dog.speak()输出子类属性1 是子类Dog,因为在Dog类中重写了speak方法。
继承的关键字 super()
在子类中使用 super() 关键字,可以调用父类的方法或构造函数。
- 继承构造函数语法
super().父类构造方法(父类属性)
- 继承父类方法语法:
super().方法名()
示例代码:
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
print(f"{self.name} 我是父类speak方法")
# 创建一个实例对象
animal = Animal("父类属性")
class Cat(Animal):
def __init__(self, name, color):
super().__init__(name) # 调用父类构造函数
self.color = color
def speak(self):
super().speak()
print(f"{self.name}我使用super()函数调用了父类speak方法")
# 然后传递给 Cat 构造函数
cat = Cat(animal.name, "Gray") # 传递父类属性给子类
print(cat.name) # 访问继承的属性
print(cat.color) # 访问子类特有属性
cat.speak() #输出两行
#输出
'''
父类属性
Gray
父类属性 我是父类speak方法
父类属性我使用super()函数调用了父类speak方法
'''
总结
- 继承:子类可以继承父类的属性和方法,从而避免重复代码。
- 方法重写:子类可以重写父类的方法,提供特定实现。
super():用于调用父类的方法或构造函数,避免手动编写重复的代码。
4. 实际案例:员工管理系统
下面我们将结合公有属性、私有属性、私有方法和继承的概念,编写一个员工管理系统的简单示例。
示例代码:
class Employee:
def __init__(self, name, salary):
self.name = name # 公有属性
self.__salary = salary # 私有属性
def get_salary(self): # 公共方法获取私有属性
return self.__salary
def set_salary(self, salary): # 公共方法修改私有属性
if salary > 0:
self.__salary = salary
else:
print("Salary must be greater than 0!")
class Manager(Employee): # 继承 Employee 类
def __init__(self, name, salary, department):
super().__init__(name, salary) # 调用父类构造函数
self.department = department # 子类特有属性
def display_info(self):
print(f"Name: {self.name}")
print(f"Salary: {self.get_salary()}")
print(f"Department: {self.department}")
# 创建实例
emp = Manager("John Doe", 5000, "Sales")
emp.display_info()
emp.set_salary(5500) # 修改私有属性
emp.display_info()
输出:
Name: John Doe
Salary: 5000
Department: Sales
Name: John Doe
Salary: 5500
Department: Sales
解释:
- 公有属性:
name是Employee类的公有属性,可以直接访问。 - 私有属性:
__salary是Employee类的私有属性,通过get_salary()和set_salary()方法访问和修改。 - 私有方法:
set_salary()和get_salary()是公有方法,用于操作私有属性。 - 继承:
Manager类继承了Employee类的属性,并且通过重写display_info()方法,添加了部门信息的显示。
这就是 Python 面向对象编程的公有和私有属性、方法,以及继承知识,通过公有和私有属性、方法,以及继承来设计灵活的类结构,可以提高代码的复用性和可维护性。