0
点赞
收藏
分享

微信扫一扫

潜聊django认证模块

三分梦_0bc3 2024-09-05 阅读 24

目录

前言

一、隐藏数据

(一)使用私有属性

(二)使用属性和方法的封装

二、隐藏功能

三、对象关联

(一)关联

(二)聚合

(三)组合

(四)继承

(五)依赖

(六)总结

四、单继承

(一)基本概念

(二)语法

五、多继承

(一)基本实例

(二)方法解析顺序(MRO)

(三)使用场景

(四)注意事项

六、重写

(一)注意

七、super函数

(一)语法

(二)构造函数中的super

(三)多重继承中的super

(四)总结

八、总结


前言

上篇文章主要了解面向对象中的类和对象、实例属性和实例方法等,接下来继续深入了解python的面向对象,冲冲冲!


一、隐藏数据

隐藏数据是面向对象编程中的一个重要概念,旨在实现数据封装和信息隐藏。通过隐藏类的内部数据,开发者可以防止外部代码直接访问和修改对象的内部状态,从而保证对象的完整性和一致性。在Python中隐藏数据的方式有两种:使用私有属性和使用属性和方法的封装。

(一)使用私有属性

在类中使用双下划线前缀来定义私有属性。虽然Python没有真正的私有属性,但使用双下划线前缀会触发名称重整,使得属性变得不容易访问。

示例:

class MyClass:
    def __init__(self, value):
        self.__hidden_value = value

    def get_value(self):
        return self.__hidden_value

obj = MyClass(42)
print(obj.get_value())  # 输出: 42
print(obj.__hidden_value)  # 会报错: AttributeError
print(obj._MyClass__hidden_value)  # 可以通过重整的名称访问

(二)使用属性和方法的封装

通过封装属性,使得它们只能通过特定的方法访问。这种方式可以控制数据的访问和修改,并在访问或修改时执行额外的操作。

示例:

class MyClass:
    def __init__(self, value):
        self._value = value

    @property
    def value(self):
        return self._value

    @value.setter
    def value(self, new_value):
        # 可以添加额外的逻辑
        self._value = new_value

obj = MyClass(42)
print(obj.value)  # 输出: 42
obj.value = 100
print(obj.value)  # 输出: 100

二、隐藏功能

在Python中隐藏功能或方法的主要作用与隐藏数据类似,但更侧重于控制类或模块的行为和接口。隐藏功能的主要作用有以下几种:

在python中,通过通过单下划线前缀和双下划线前缀隐藏功能,示例:

  • 单下划线前缀:通过使用单下划线前缀来标记某些方法或属性为内部使用。虽然这并不能真正阻止访问,但它表示这些功能不应该被外部代码使用。
class MyClass:
    def __init__(self):
        self._internal_function()

    def _internal_function(self):
        print("这是一个内部方法")

    def public_function(self):
        print("这是一个公开的方法")

obj = MyClass()
obj.public_function()  # 正常调用
obj._internal_function()  # 可以调用,但不建议这样做
  • 双下划线前缀:通过使用双下划线前缀将方法或属性标记为类的私有成员,触发名称重整,进一步限制外部访问。
class MyClass:
    def __init__(self):
        self.__hidden_function()

    def __hidden_function(self):
        print("这是一个隐藏的方法")

    def public_function(self):
        print("这是一个公开的方法")

obj = MyClass()
obj.public_function()  # 正常调用
obj.__hidden_function()  # 访问会引发AttributeError
obj._MyClass__hidden_function()  # 可以通过名称重整来访问,但不建议这样做

三、对象关联

对象关联是面向对象编程中的一个关键概念,用于描述不同对象之间的关系。对象关联可以帮助开发者组织和管理代码的结构,使其更加清晰和可维护。Python中的对象关联通常分为以下几种类型:

(一)关联

关联是最基本的对象关系,表示一个对象与另一个对象之间有某种联系。关联关系通常是双向的,但可以是单向的。对象之间通过引用彼此来实现关联。

示例:

class Driver:
    def __init__(self, name):
        self.name = name

class Car:
    def __init__(self, model, driver):
        self.model = model
        self.driver = driver  # 关联Driver对象

driver = Driver("张三")
car = Car("大众", driver)

print(car.driver.name)  # 输出: 张三

(二)聚合

聚合是一种特殊的关联关系,表示一种“整体-部分”关系。聚合关系下,部分对象可以独立于整体对象存在。整体对象通常会引用部分对象,但不会管理它们的生命周期。

示例:

class Engine:
    def __init__(self, horsepower):
        self.horsepower = horsepower

class Car:
    def __init__(self, model, engine):
        self.model = model
        self.engine = engine  # 聚合Engine对象

engine = Engine(150)
car = Car("大众", engine)

print(car.engine.horsepower)  # 输出: 150

在这个例子中,Engine是一个独立存在的对象,Car只是引用了它。这意味着即使Car对象被销毁,Engine对象仍然可以独立存在。

(三)组合

组合是一种更强的“整体-部分”关系,表示部分对象的生命周期完全依赖于整体对象。整体对象负责创建和销毁部分对象,这意味着当整体对象被销毁时,部分对象也会被销毁。

示例:

class Engine:
    def __init__(self, horsepower):
        self.horsepower = horsepower

class Car:
    def __init__(self, model, horsepower):
        self.model = model
        self.engine = Engine(horsepower)  # 组合Engine对象

car = Car("大众", 200)
print(car.engine.horsepower)  # 输出: 200

在组合关系中,Engine对象是Car对象的一部分。当Car对象被销毁时,其内部的Engine对象也会被销毁。

(四)继承

继承用于表示子类继承父类的属性和方法。继承允许子类复用父类的代码,同时可以添加或修改功能。

示例:

class Vehicle:
    def __init__(self, brand):
        self.brand = brand

    def drive(self):
        print(f"{self.brand} ")

class Car(Vehicle):  # 继承Vehicle
    def __init__(self, brand, model):
        super().__init__(brand)
        self.model = model

car = Car("大众", "宝来")
car.drive()  # 输出: 大众

(五)依赖

依赖表示一个对象使用另一个对象作为参数或返回值,通常是临时的。依赖关系表示两个对象之间的一种“使用”关系。

示例:

class Fuel:
    def __init__(self, type):
        self.type = type

class Car:
    def __init__(self, model):
        self.model = model

    def refuel(self, fuel):
        print(f"这车加的油是 {fuel.type}")

# 示例
fuel = Fuel("汽油")
car = Car("大众")
car.refuel(fuel)  # 输出: 这车加的油是汽油

在这个例子中,Car对象依赖于Fuel对象,但这种依赖是临时的,仅在refuel方法调用期间存在。

(六)总结

Python中的对象关联通过以上几种基本关系来描述对象之间的交互方式:

  • 关联:描述一般的联系或依赖。
  • 聚合:整体-部分关系,但部分可以独立存在。
  • 组合:更强的整体-部分关系,部分依赖整体的生命周期。
  • 继承:子类继承父类,复用代码。
  • 依赖:一种临时的“使用”关系。

这些关联类型帮助开发者更好地组织和管理代码结构,使得软件设计更加模块化、可维护。


四、单继承

Python中的继承是面向对象编程中的一个核心概念,用于表示类之间的层次关系。继承允许一个类继承另一个类的属性和方法,从而实现代码的重用、扩展和多态性。

(一)基本概念

  • 父类(基类):被继承的类,提供基础属性和方法。
  • 子类(派生类):继承父类的类,可以复用父类的属性和方法,也可以添加新的属性和方法,或覆盖(重写)父类的方法。

(二)语法

继承通过定义一个类时在括号内指定父类来实现,语法如下:

class ParentClass:
    # 父类的属性和方法
    pass

class ChildClass(ParentClass):
    # 子类的属性和方法
    pass

示例:

class Animal:
    def __init__(self, name):
        self.name = name
    
    def speak(self):
        return f"{self.name} 正在叫"

class Dog(Animal):  # Dog 类继承自 Animal 类
    def speak(self):
        return f"{self.name} 叫"

# 使用继承创建对象
dog = Dog("旺财")
print(dog.speak())  # 输出:旺财 叫

在这个例子中,Dog 类继承了 Animal 类的属性和方法。Dog 类重写了 speak() 方法,因此调用 Dog 类的 speak() 方法时,会返回 "叫" 而不是父类中的 "正在叫"。


五、多继承

多重继承是指一个子类可以继承多个父类。它允许子类从多个基类中获取属性和方法,从而实现更加灵活和强大的功能。然而,多重继承也会带来一些复杂性,尤其是在处理同名方法和属性时。Python 使用方法解析顺序(MRO)来决定调用的顺序。

(一)基本实例

class Base1:
    def method(self):
        print("父类1方法")

class Base2:
    def method(self):
        print("父类2方法")

class Derived(Base1, Base2):
    pass

d = Derived()
d.method()  # 输出:父类1方法

在这个例子中,Derived 类继承了 Base1Base2。当调用 method() 时,Derived 类首先使用 Base1method(),因为 Base1 在继承列表中排在 Base2 之前。

(二)方法解析顺序(MRO)

Python 使用方法解析顺序(MRO)来确定在多重继承情况下调用方法的顺序。可以使用 ClassName.mro()ClassName.__mro__ 查看 MRO。

示例:

class A:
    def process(self):
        print("A流程")

class B(A):
    def process(self):
        print("B流程")

class C(A):
    def process(self):
        print("C流程")

class D(B, C):
    pass

d = D()
d.process()  # 输出:B流程
print(D.mro())  # 输出:[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]

该例子中,D 类的 MRO 是 D -> B -> C -> A -> object,因此调用 process() 方法时,会首先调用 B 类中的方法。

(三)使用场景

  • 类的扩展: 允许类从多个基础类中获取功能,并进行扩展。
  • 接口实现: 可以用多继承实现多个接口,尤其是在类似 Java 的接口设计中。

(四)注意事项

  • 设计复杂性: 多重继承可能导致复杂的继承图谱,容易使代码难以理解和维护。
  • 钻石继承问题: 如果两个基类有共同的父类,可能会导致方法重复调用的复杂情况。Python 的 MRO 处理了这个问题,通过 C3 线性化算法来确保一致性。

六、重写

        重写指的是子类重新定义从父类继承的方法。这使得子类可以提供特定的实现,而不是使用父类的默认实现。重写是面向对象编程中的一个核心概念,它允许你在继承的基础上扩展或修改行为。 当子类继承父类的方法时,它可以重写这些方法,以便提供不同的实现。子类中定义的方法将替代父类中的方法,而在子类实例上调用该方法时将使用新的实现。

示例:

假设我们有一个父类 Animal 和一个子类 Dog,其中 Dog 重写了 Animal 类的 speak 方法:

class Animal:
    def speak(self):
        return "动物叫"

class Dog(Animal):
    def speak(self):
        return "狗吠"

# 使用继承和重写创建对象
animal = Animal()
dog = Dog()

print(animal.speak())  # 输出:动物叫
print(dog.speak())     # 输出:狗吠

说明:Dog 类重写了 Animal 类的 speak 方法,因此当调用 dog.speak() 时,返回的是 "狗叫",而不是父类的实现。

(一)注意

  • 方法签名: 子类重写方法时,确保方法签名与父类一致,即方法名称和参数列表应相同,否则可能导致方法调用失败或行为不一致。
  • 调用父类方法: 在需要保留父类原有功能的情况下,使用 super() 调用父类的方法,确保子类扩展而不完全替代父类功能。
  • 保持一致性: 重写方法时,确保新实现与父类的接口一致,以避免引入错误或不一致的行为。

七、super函数

super() 函数用于调用父类的方法。它是面向对象编程中的一个重要工具,尤其在涉及继承和方法重写时,可以帮助你在子类中调用父类的实现。使用 super() 函数可以确保子类在扩展父类功能的同时,还能够利用父类已经实现的功能。

示例:

class Parent:
    def method(self):
        print("父类方法")

class Child(Parent):
    def method(self):
        super().method()  # 调用父类的 method 方法
        print("子类方法")

child = Child()
child.method()
# 输出:
# 父类方法
# 子类方法

该示例中,Child 类重写了 method 方法,并通过 super().method() 调用了 Parent 类中的 method 方法。

(一)语法

super() 函数通常用在方法内部,不需要传递任何参数。Python 会自动确定要调用的父类。

示例:

super().method()

在 Python 2.x 中,super() 的用法略有不同,通常需要传递当前类和实例作为参数:

super(Child, self).method()

(二)构造函数中的super

super在类的构造函数中非常有用,可以确保父类的构造函数被正确调用,从而初始化继承来的属性。

示例:

class Parent:
    def __init__(self, name):
        self.name = name

class Child(Parent):
    def __init__(self, name, age):
        super().__init__(name)  # 调用父类的构造函数
        self.age = age

child = Child("杰克", 30)
print(child.name)  # 输出:杰克
print(child.age)   # 输出:30

说明:Child 类的构造函数调用了 Parent 类的构造函数,以确保 name 属性被正确初始化。

(三)多重继承中的super

在多重继承中,super变得更复杂,但也更强大。它帮助确保方法调用按照正确的顺序执行,遵循方法解析顺序(MRO)。

示例:

class A:
    def method(self):
        print("A方法")

class B(A):
    def method(self):
        print("B方法")
        super().method()

class C(A):
    def method(self):
        print("C方法")
        super().method()

class D(B, C):
    def method(self):
        print("D方法")
        super().method()

d = D()
d.method()
# 输出:
# D方法
# B方法
# C方法
# A方法

在这个例子中,D 类的 method 方法通过 super() 调用 BC 类的 method 方法,最终调用 A 类的方法。super() 按照 MRO 确保了正确的调用顺序。

(四)总结

  • super() 函数用于调用父类的方法,确保在子类中扩展或重写方法时能够利用父类的实现。
  • 在构造函数中使用 super() 可以确保父类的构造函数被调用,从而初始化继承来的属性。
  • 在多重继承中,super() 遵循 MRO,确保方法调用按照正确的顺序进行。
  • 使用 super() 时需要注意方法的存在性以及继承结构的复杂性。

八、总结

该文章中更进一步了解了面向对象,内容有继承、重写和super等,从这些知识点可以了解到python的语法,同时也能体会到python的特殊之处,下篇文章会继续更新一步了解python面向对象,让我们拭目以待吧!

举报

相关推荐

0 条评论