Python 面向对象编程全面解析与深度探索

发布于:2024-12-18 ⋅ 阅读:(76) ⋅ 点赞:(0)

目录

类和对象的概念

类(Class)

对象(Object)

(一)属性(Attributes)

(a).实例属性(Instance Attributes)

(b).类属性(Class Attributes)

(二)方法(Methods)

(a)实例方法(Instance Methods)

(b)类方法(Class Methods)

(c)静态方法(Static Methods)

(三) 继承(Inheritance)

(四) 多态(Polymorphism)

(五) 封装(Encapsulation)

补充

(1)特殊方法(Magic Methods)或双下划线方法(Dunder Methods)

(2)装饰器与面向对象

(3)类的组合

(4)元类(Metaclasses)


 

类和对象的概念

  • 类(Class)

    • 类是一种抽象的数据类型,它定义了一组具有相同属性(Attributes)和方法(Methods)的对象的模板。可以把类想象成制作某种物品的蓝图。例如,定义一个 “汽车(Car)” 类,这个类可以包含汽车的属性,如颜色(color)、品牌(brand)、速度(speed)等,以及汽车可以执行的方法,如加速(accelerate)、刹车(brake)等。
    • 在 Python 中,类的定义使用class关键字。例如:
class Car:
    def __init__(self, color, brand):
        self.color = color
        self.brand = brand
        self.speed = 0

 

  • 对象(Object)

    • 对象是类的一个具体实例。根据上面的 “汽车(Car)” 类的蓝图,可以创建出多个具体的汽车对象。比如,car1 = Car("red", "Toyota")car2 = Car("blue", "Ford"),这里car1car2就是Car类的两个对象,它们分别具有自己的颜色、品牌和初始速度(在__init__方法中初始化为 0)等属性。

(一)属性(Attributes)

(a).实例属性(Instance Attributes)

  • 实例属性是属于对象个体的属性。在上面的Car类中,colorbrandspeed就是实例属性。每个Car类的对象都可以有不同的颜色和品牌,并且它们的速度也可以独立变化。通过self关键字来访问和修改实例属性。例如:
class Car:
    def __init__(self, color, brand):
        self.color = color
        self.brand = brand
        self.speed = 0
    def accelerate(self, increment):
        self.speed += increment

accelerate方法中,通过self.speed来访问和修改对象的速度属性。

(b).类属性(Class Attributes)

  • 类属性是属于类本身的属性,被该类的所有对象所共享。例如,定义一个Car类的类属性wheels来表示汽车的轮子数量,因为通常汽车的轮子数量是固定的(假设为 4),对于所有Car类的对象都是一样的。
class Car:
    wheels = 4
    def __init__(self, color, brand):
        self.color = color
        self.brand = brand
        self.speed = 0

可以通过Car.wheels来访问类属性,所有Car类的对象都共享这个属性值。

(二)方法(Methods)

(a)实例方法(Instance Methods)

  • 实例方法是定义在类中的函数,用于操作对象的实例属性或者执行与对象相关的操作。实例方法的第一个参数通常是self,它代表调用该方法的对象本身。例如在Car类的accelerate方法中,self表示正在加速的那个汽车对象。
class Car:
    def __init__(self, color, brand):
        self.color = color
        self.brand = brand
        self.speed = 0
    def accelerate(self, increment):
        self.speed += increment
    def brake(self, decrement):
        if self.speed >= decrement:
            self.speed -= decrement
        else:
            self.speed = 0

这里acceleratebrake都是实例方法,它们通过self访问和修改对象的speed属性。

(b)类方法(Class Methods)

  • 类方法是与类本身相关的方法,而不是与类的某个具体对象相关。类方法使用@classmethod装饰器来定义,并且第一个参数通常是cls,代表类本身。类方法可以用于创建工厂方法或者修改类属性等操作。例如:
class Car:
    wheels = 4
    @classmethod
    def change_wheels(cls, new_wheels):
        cls.wheels = new_wheels

通过Car.change_wheels(6)可以修改Car类的wheels类属性的值。

(c)静态方法(Static Methods)

  • 静态方法是定义在类中的普通函数,它不需要访问实例属性或者类属性,也不需要self或者cls参数。静态方法通常用于实现一些与类相关但又不依赖于类的实例或者类本身的状态的功能。例如:
class Car:
    @staticmethod
    def is_motor_vehicle():
        return True

is_motor_vehicle静态方法只是简单地返回一个布尔值,表示汽车是机动车,它不依赖于任何Car类的实例或者类属性。


(三) 继承(Inheritance)

  • 继承是面向对象编程中的一个重要特性,它允许创建一个新类(子类),子类继承了父类的属性和方法,并且可以添加新的属性和方法或者重写父类的现有属性和方法。例如,定义一个 “电动汽车(ElectricCar)” 类,它继承自 “汽车(Car)” 类。
class ElectricCar(Car):
    def __init__(self, color, brand, battery_capacity):
        super().__init__(color, brand)
        self.battery_capacity = battery_capacity
    def charge(self):
        print("Charging the electric car.")

ElectricCar类中,通过super().__init__(color, brand)调用父类Car__init__方法来初始化继承自父类的属性(colorbrand),同时添加了新的属性battery_capacity和新的方法charge

(四) 多态(Polymorphism)

  • 多态是指不同类型的对象对同一消息(方法调用)做出不同的响应。在 Python 中,多态通常通过方法重写(在子类中重新定义父类的方法)来实现。例如,Car类和ElectricCar类都有accelerate方法,但是它们的实现细节可能不同。
class Car:
    def __init__(self, color, brand):
        self.color = color
        self.brand = brand
        self.speed = 0
    def accelerate(self, increment):
        self.speed += increment
class ElectricCar(Car):
    def __init__(self, color, brand, battery_capacity):
        super().__init__(color, brand)
        self.battery_capacity = battery_capacity
    def accelerate(self, increment):
        # 假设电动汽车加速方式不同
        self.speed += increment * 2

当调用car.accelerate(10)carCar类的对象)和electric_car.accelerate(10)electric_carElectricCar类的对象)时,它们会根据各自类中accelerate方法的定义做出不同的加速行为,这就是多态的体现。


(五) 封装(Encapsulation)

  • 封装是将数据(属性)和操作数据的方法组合在一起,并对外部隐藏对象的内部细节。在 Python 中,可以通过在属性和方法名前面添加双下划线(__)来实现一定程度的封装。例如:
class Car:
    def __init__(self, color, brand):
        self.__color = color
        self.__brand = brand
        self.__speed = 0
    def accelerate(self, increment):
        self.__speed += increment
    def get_color(self):
        return self.__color
    def set_color(self, new_color):
        self.__color = new_color

在这个Car类中,__color__brand__speed属性被封装起来,外部不能直接访问这些属性,但是可以通过get_colorset_color等方法来间接访问和修改属性的值。这样可以保护对象的内部状态,防止外部代码随意修改,提高代码的可维护性和安全性

 

补充

(1)特殊方法(Magic Methods)或双下划线方法(Dunder Methods)

这些方法在 Python 中具有特殊的意义,它们通常以双下划线开头和结尾。例如 __str__ 和 __repr__ 方法用于对象的字符串表示。

class Car:
    def __init__(self, color, brand):
        self.color = color
        self.brand = brand

    def __str__(self):
        return f"Car: {self.brand} in {self.color}"

    def __repr__(self):
        return f"Car({self.color}, {self.self.brand})"

__str__ 方法主要用于提供给用户友好的对象字符串表示,比如在使用 print 函数打印对象时会调用该方法__repr__ 方法则更侧重于提供对象的精确表示,通常在交互式环境中直接输入对象时显示,也用于对象的序列化等场景,有助于调试和记录对象的状态。

还有其他一些特殊方法,如 __add__ 用于定义对象的加法操作。例如对于自定义的向量类,可以定义 __add__ 方法来实现向量相加的逻辑:

class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __add__(self, other):
        return Vector(self.x + other.x, self.y + other.y)

这样就可以像使用内置数据类型一样对自定义的 Vector 类对象进行加法运算:v1 = Vector(1, 2); v2 = Vector(3, 4); v3 = v1 + v2 。

(2)装饰器与面向对象

装饰器可以应用于类和类的方法,以扩展其功能。例如,@property 装饰器是一种常用的装饰器,它可以将一个方法转换为一个类似属性的访问方式,同时可以在方法内部添加一些逻辑,比如数据验证等。

class Person:
    def __init__(self, name, age):
        self._name = name
        self._age = age

    @property
    def age(self):
        return self._age

    @age.setter
    def age(self, new_age):
        if new_age > 0:
            self._age = new_age
        else:
            raise ValueError("Age must be positive.")

这里通过 @property 装饰器将 age 方法转换为属性,使得可以像访问属性一样获取年龄值(person.age),同时通过 @age.setter 装饰器定义了属性的设置方法,在设置年龄时可以进行数据验证。

(3)类的组合

除了继承,类的组合也是构建复杂对象关系的重要方式。类的组合是指一个类将其他类的对象作为自己的属性,从而利用其他类的功能来构建更复杂的功能。

例如,一个 Car 类可以包含一个 Engine 类的对象作为其发动机属性:

class Engine:
    def start(self):
        print("Engine started.")

    def stop(self):
        print("Engine stopped.")

class Car:
    def __init__(self, color, brand):
        self.color = color
        self.brand = brand
        self.engine = Engine()

    def start_car(self):
        self.engine.start()

    def stop_car(self):
        self.engine.stop()

通过这种组合方式,Car 类可以利用 Engine 类的功能来实现汽车的启动和停止操作,而不需要继承 Engine 类,这种方式在一些情况下可以提供更灵活的设计,避免了复杂的继承层次带来的问题。

(4)元类(Metaclasses)

元类是创建类的类。在 Python 中,一切皆对象,类也是对象,而元类就是用来创建这些类对象的。默认情况下,Python 使用 type 作为元类来创建普通的类。但可以自定义元类来控制类的创建过程,例如添加自定义的属性或方法到创建的类中,或者修改类的定义方式。

class MyMeta(type):
    def __new__(cls, name, bases, attrs):
        attrs['new_attribute'] = "This is a new attribute added by metaclass"
        return super().__new__(cls, name, bases, attrs)

class MyClass(metaclass=MyMeta):
    pass

print(MyClass.new_attribute)
  1. 自定义元类 MyMeta 代码解读
class MyMeta(type):
    def __new__(cls, name, bases, attrs):
        attrs['new_attribute'] = "This is a new attribute added by metaclass"
        return super().__new__(cls, name, bases, attrs)

这里定义了一个名为 MyMeta 的自定义元类,它继承自 type(因为元类本身就是创建类的类,type 是 Python 中默认用于创建类的元类基础)。在 MyMeta 类里重写了 __new__ 方法,此方法在类创建时被调用。
在 __new__ 方法内,接收了几个关键参数:

  • cls:代表当前的元类自身(在这里就是 MyMeta 类)。
  • name:是即将要创建的类的名称(在后续示例中对应 MyClass 的类名)。
  • bases:是一个包含了新类要继承的基类的元组(示例中 MyClass 没有显式指定基类继承,该参数对应为空元组等情况)。
  • attrs:是一个字典,里面存放着即将创建的类的属性和方法等信息(类似类的命名空间)。
    在 __new__ 方法中,往 attrs 字典里添加了一个新的键值对,键是 new_attribute,值是 "This is a new attribute added by metaclass",意味着通过这个元类创建的类将会拥有这个新属性。最后,调用父类(也就是 type 类)的 __new__ 方法来实际创建类对象,并返回创建好的类对象。
  1. 使用自定义元类创建 MyClass 类及验证
class MyClass(metaclass=MyMeta):
    pass

print(MyClass.new_attribute)

定义 MyClass 类时,通过 metaclass=MyMeta 指定了使用自定义的 MyMeta 元类来创建它。由于 MyMeta 元类在创建类时添加了 new_attribute 属性,所以后续可以直接通过 MyClass.new_attribute 来访问这个属性,并打印出对应的值 "This is a new attribute added by metaclass"

在这个例子中,自定义的元类 MyMeta 在创建 MyClass 类时添加了一个新的属性 new_attribute。虽然元类在日常编程中使用相对较少,但在一些高级的框架开发和特定的编程模式中有着重要的应用,如 Django 框架中的一些模型类的创建就利用了元类的特性来实现数据库表的映射等功能。

 

 


网站公告

今日签到

点亮在社区的每一天
去签到