Python面向对象编程:公有属性、私有属性、私有方法与继承

117 阅读7分钟

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
'''

解释:

  1. 父类 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

解释:

  • 公有属性nameEmployee 类的公有属性,可以直接访问。
  • 私有属性__salaryEmployee 类的私有属性,通过 get_salary()set_salary() 方法访问和修改。
  • 私有方法set_salary()get_salary() 是公有方法,用于操作私有属性。
  • 继承Manager 类继承了 Employee 类的属性,并且通过重写 display_info() 方法,添加了部门信息的显示。

这就是 Python 面向对象编程的公有和私有属性、方法,以及继承知识,通过公有和私有属性、方法,以及继承来设计灵活的类结构,可以提高代码的复用性和可维护性。