Python 基础 (八)Python的类与对象

Python基础文章系列

Python 基础 (一)Python基本认识与环境搭建Python 基础 (一)Python基本认识与环境搭建
Python 基础 (二)Python变量与基本数据类型Python 基础 (二)Python变量与基本数据类型
Python 基础 (三)Python基本语句与基本运算Python 基础 (三)Python基本语句与基本运算
Python 基础 (四)Python函数Python 基础 (四)Python函数
Python 基础 (五)Python包与模块Python 基础 (五)Python包与模块
Python 基础 (六)Python的文件模块Python 基础 (六)Python的文件模块
Python 基础 (七)Python的异常处理机制Python 基础 (七)Python的异常处理机制
Python 基础 (八)Python的类与对象Python 基础 (八)Python的类与对象
Python 基础 (九)Python的内置模块Python 基础 (九)Python的内置模块
Python 基础 (十)Python实现简单的图书管理系统Python 基础 (十)Python实现简单的图书管理系统

在这里插入图片描述

4.8 类与对象

4.8.1 面向对象

Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对象是很容易的。

  • **类(Class): **用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
  • **方法:**类中定义的函数。
  • **类变量:**类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
  • **数据成员:**类变量或者实例变量用于处理类及其实例对象的相关的数据。
  • **方法重写:**如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
  • **局部变量:**定义在方法中的变量,只作用于当前实例的类。
  • **实例变量:**在类的声明中,属性是用变量来表示的,这种变量就称为实例变量,实例变量就是一个用 self 修饰的变量。
  • **继承:**即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。
  • **实例化:**创建一个类的实例,类的具体对象。
  • **对象:**通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。

4.8.2 类定义

类(Class)是面向对象编程中的重要概念,它用于定义对象的模板,描述了对象的属性和方法。在Python中,类的定义通常遵循以下结构:

class ClassName:
    # 类的属性
    class_variable = value
    
    # 构造函数,初始化对象的属性
    def __init__(self, parameter1, parameter2, ...):
        self.instance_variable1 = parameter1
        self.instance_variable2 = parameter2
        # 更多初始化操作
    
    # 类的方法
    def method1(self, arg1, arg2, ...):
        # 方法的实现
        # 可以访问实例变量和类变量
        # 可以执行各种操作
    
    def method2(self, arg1, arg2, ...):
        # 另一个方法的实现
        # 可以访问实例变量和类变量
        # 可以执行不同的操作

让我解释一下上述代码的各个部分:

  • class ClassName::这是类的定义语句,用于创建一个名为ClassName的类。
  • class_variable = value:这是类变量(或静态变量),它在类的所有实例之间共享。您可以在类中定义各种属性,它们对于该类的所有对象都是相同的。
  • def __init__(self, parameter1, parameter2, ...)::这是构造函数,用于初始化对象的属性。构造函数会在创建对象时自动调用,通常用于将传递给类的参数分配给对象的实例变量。
  • self.instance_variable1 = parameter1:在构造函数中,使用self来引用对象本身,然后将参数值分配给对象的实例变量。这些实例变量将在整个对象的生命周期内存储数据。
  • def method1(self, arg1, arg2, ...)::这是类的方法,用于定义对象可以执行的操作。方法通常以self作为第一个参数,以便可以访问实例变量和其他方法。方法可以执行各种操作,包括修改实例变量、调用其他方法等。

通过定义类和类的方法,您可以创建类的实例并使用它们来执行特定的任务。例如:

# 创建类的实例
obj = ClassName(parameter1_value, parameter2_value)

# 调用对象的方法
obj.method1(arg1_value, arg2_value)
obj.method2(arg1_value, arg2_value)
# ---encoding:utf-8---
# @Time    : 2023/9/3 13:30
# @Author  : Darwin_Bossen
# @Email   :3139066125@qq.com
# @Site    :  类定义
# @File    : Person.py

# 类的定义格式:
class Person:
    # 类属性
    name = ""
    age = 0
    # 初始化方法
    def __init__(self, name, age):
        self.name = name
        self.age = age
    # 类方法
    def say(self):
        print("my name is {0}, I am {1} years old".format(self.name, self.age))
    # 类方法
    def __str__(self):
        return "my name is {0}, I am {1} years old".format(self.name, self.age)
    # 类方法
    def __del__(self):
        print("对象被回收了")

    def __new__(cls, *args, **kwargs):
        print("创建对象")
        return super().__new__(cls)

    def __call__(self, *args, **kwargs):
        print("对象被调用了")

    def __getitem__(self, item):
        print("获取对象的索引值")
        return item



if __name__ == '__main__':
    Person("Darwin", 18).say()

image.png

4.8.3 Self

在Python的类定义中,self是一个特殊的参数,用于表示对象本身。它在方法定义中作为第一个参数出现,通常被称为"self",但实际上您可以使用任何名称,尽管约定俗成的做法是使用"self"。
以下是关于self的一些重要信息和用法:

  1. 表示对象self代表了类的实例或对象本身。在类的方法内部,通过self可以访问和操作对象的属性(实例变量)和其他方法。
  2. 访问实例变量:通过self,您可以访问对象的实例变量。例如,self.variable_name表示访问对象的特定实例变量。
  3. 调用其他方法:通过self,您可以调用对象的其他方法。这是因为self允许您在类的方法内部引用同一对象的其他方法。
  4. 必须作为第一个参数:在类的方法定义中,self必须作为第一个参数出现。这是Python的约定,用于指示该方法是对象的一部分。

以下是一个简单的示例,演示了self的使用:

class MyClass:
    def __init__(self, value):
        self.my_value = value  # 创建实例变量

    def display_value(self):
        print("The value is:", self.my_value)  # 访问实例变量

    def update_value(self, new_value):
        self.my_value = new_value  # 修改实例变量

# 创建类的实例
obj = MyClass(42)

# 调用对象的方法
obj.display_value()  # 输出:The value is: 42

# 更新实例变量的值
obj.update_value(99)

# 再次调用方法
obj.display_value()  # 输出:The value is: 99

在上述示例中,self被用于访问和操作MyClass对象的实例变量my_value以及调用方法display_valueupdate_value。这种方式使您能够在类的方法中处理对象的状态和行为。

4.8.4 继承

继承是面向对象编程中的重要概念,它允许一个类(子类或派生类)从另一个类(父类或基类)继承属性和方法。Python支持类的继承,允许您创建一个新类,从一个或多个现有类派生出来,并继承其特性。
以下是关于继承的一些基本概念和示例:

  1. 父类和子类:在继承中,父类是被继承的类,子类是继承父类的类。
  2. 继承语法:在Python中,使用以下语法来创建子类并继承父类的属性和方法:
    子类的定义中,将父类作为参数传递给子类的名称。
  3. 访问父类方法:在子类中,您可以通过使用super()函数来访问父类的方法。这允许您在子类中扩展或修改父类的方法。
  4. 覆盖方法:子类可以覆盖(重写)父类中的方法,以便实现特定于子类的行为。方法覆盖是多态性的一部分。

以下是一个简单的示例,演示了继承的基本概念:

# 父类
class Animal:
    def __init__(self, name):
        self.name = name

    def speak(self):
        pass

# 子类继承父类
class Dog(Animal):
    def speak(self):
        return f"{self.name} says Woof!"

class Cat(Animal):
    def speak(self):
        return f"{self.name} says Meow!"

# 创建子类的实例
dog = Dog("Buddy")
cat = Cat("Whiskers")

# 调用子类方法
print(dog.speak())  # 输出:Buddy says Woof!
print(cat.speak())  # 输出:Whiskers says Meow!

在上述示例中,DogCatAnimal的子类,它们继承了Animal类的name属性和speak方法。然后,它们覆盖了speak方法,以实现特定于子类的行为。

  • 继承允许您创建具有层次结构的类,提高代码的可重用性和组织性。
  • 父类可以定义通用的属性和方法,而子类可以根据需要进行扩展或修改。

4.8.5 super函数

super()是一个内置函数,常用于在子类中调用父类的方法。在Python中,当您创建子类并希望继承父类的行为时,super()函数非常有用,它允许您在子类中调用父类的构造函数和方法。
super()函数的一般语法如下:

super().method_name(arguments)

这里是关于super()函数的一些重要信息和用法:

  1. 在构造函数中调用父类的构造函数:当您在子类中定义构造函数时,通常希望初始化子类特有的属性,并且还希望调用父类的构造函数来初始化从父类继承的属性。使用super().__init__(arguments)来实现这一点。
  2. 在子类方法中调用父类方法:在子类中,如果您覆盖了父类的方法,但仍希望在子类方法中调用父类版本的方法,可以使用super().method_name(arguments)来调用父类的方法。

以下是一个示例,演示了super()函数的用法:

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

    def display(self):
        print(f"Name: {self.name}")

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

    def display(self):
        super().display()  # 调用父类的方法
        print(f"Age: {self.age}")

# 创建子类的实例
child = Child("Alice", 25)

# 调用子类的方法
child.display()

在上述示例中,Child类继承自Parent类,并且在构造函数和display方法中使用了super()来调用父类的构造函数和方法。这允许子类初始化自己的属性并访问父类的方法。
注意:super()函数的使用可能会根据Python版本和具体情况略有不同,特别是在多重继承的情况下。但通常情况下,它用于在子类中调用父类的方法。

4.8.6 类属性与方法

私有属性
在Python中,类的私有属性是指仅在类的内部访问的属性,外部无法直接访问。私有属性的命名约定是在属性名前面添加一个或多个下划线(例如,_private_attribute__private_attribute)。有两种方式来定义私有属性:

  1. 单下划线前缀:在属性名前面加一个下划线,例如 _private_attribute。这是一种约定,用于指示该属性是私有的,但实际上仍然可以在类的外部访问。
    虽然这个属性不是真正的私有属性,但它是一种向其他开发人员传达属性意图的方式。
  2. 双下划线前缀:在属性名前面加两个下划线,例如 __private_attribute。这种方式更严格,Python会对属性名称进行名称修饰,以防止外部直接访问。但实际上,它仍然可以通过名称修饰来访问,如_ClassName__private_attribute
class MyClass:
    def __init__(self):
        self.__private_attribute = 42

obj = MyClass()
# 以下方式可以访问,但不建议这样做
print(obj._MyClass__private_attribute)

请注意,即使使用双下划线前缀也不能完全防止访问私有属性,因为Python允许通过特定的名称修饰来访问它们。然而,这是一种不建议的做法,应避免在实际代码中使用。
私有方法
在Python中,私有方法是指只能在类的内部调用,外部无法直接访问的方法。通常,私有方法的命名约定是在方法名前面加一个或多个下划线(例如,_private_method__private_method)。虽然Python不像某些其他编程语言那样提供严格的私有方法访问控制,但是通过命名约定,可以达到限制对方法的直接访问的目的。
以下是使用命名约定创建私有方法的示例:

class MyClass:
    def __init__(self):
        self.public_variable = "I am a public variable"

    def _private_method(self):
        print("This is a private method")

    def public_method(self):
        print("This is a public method")
        self._private_method()  # 在类的内部调用私有方法

# 创建类的实例
obj = MyClass()

# 调用公共方法
obj.public_method()  # 输出:This is a public method

# 调用私有方法(虽然不建议)
obj._private_method()  # 输出:This is a private method

在上述示例中,_private_method被定义为私有方法,因为它的名称以单下划线开头。虽然可以从外部调用它,但是通过命名约定,它被视为私有,并且开发人员通常不应该直接访问私有方法。
虽然Python不强制限制私有方法的访问,但是开发人员通常遵循命名约定,以防止不必要的外部访问。如果要确保方法不被外部调用,可以使用更强大的封装技巧,如属性方法和属性装饰器,以提供更好的控制和封装。
类的专有方法
在Python中,类的专有方法(也称为魔法方法或特殊方法)是以双下划线开头和结尾的方法,例如__init____str____eq__等。这些方法具有特殊的含义和用途,它们定义了类在特定情况下如何行为,从而使类更加强大和灵活。
以下是一些常见的类的专有方法和它们的用途:

  1. __init__(self, ...): 初始化方法,也称为构造函数。在创建类的实例时自动调用,用于初始化对象的属性。
  2. __str__(self): 字符串表示方法,用于返回对象的字符串表示。通常在使用str(obj)print(obj)时调用。
  3. __repr__(self): 返回对象的可打印表示。通常在交互式解释器中直接输入对象名称时调用。
  4. __len__(self): 返回对象的长度,通常用于支持len(obj)
  5. __getitem__(self, key): 获取对象的元素,通常用于支持索引访问,如obj[key]
  6. __setitem__(self, key, value): 设置对象的元素,通常用于支持索引赋值,如obj[key] = value
  7. __delitem__(self, key): 删除对象的元素,通常用于支持索引删除,如del obj[key]
  8. __iter__(self): 返回一个可迭代对象,通常用于支持迭代。
  9. __next__(self): 定义迭代过程中的下一个值,通常与__iter__一起使用。
  10. __eq__(self, other): 定义对象相等性比较,通常用于支持obj1 == obj2
  11. __ne__(self, other): 定义对象不相等性比较,通常用于支持obj1 != obj2
  12. __lt__(self, other): 定义小于比较,通常用于支持obj1 < obj2
  13. __le__(self, other): 定义小于等于比较,通常用于支持obj1 <= obj2
  14. __gt__(self, other): 定义大于比较,通常用于支持obj1 > obj2
  15. __ge__(self, other): 定义大于等于比较,通常用于支持obj1 >= obj2

这些专有方法可以让您自定义类的行为,使其更符合特定的需求。例如,您可以定义__eq__方法来使两个对象的比较更有意义,或者定义__str__方法以便在打印对象时提供易于理解的输出。
示例:

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

    def __str__(self):
        return f"MyClass instance with value: {self.value}"

    def __eq__(self, other):
        if isinstance(other, MyClass):
            return self.value == other.value
        return False

# 创建类的实例
obj1 = MyClass(42)
obj2 = MyClass(42)

# 使用专有方法
print(obj1)             # 输出:MyClass instance with value: 42
print(obj1 == obj2)     # 输出:True

4.8.7 重载

在面向对象编程中,方法重载是指在一个类中定义多个方法,这些方法具有相同的名称但不同的参数列表。在Python中,方法重载的概念与某些其他编程语言不同,因为Python不支持方法的多态参数类型,而是根据方法的名称来决定哪个方法被调用。这意味着在Python中,只有最后定义的方法会覆盖之前定义的同名方法。
以下是一个示例,演示了在Python中方法重载的原理:

class MyClass:
    def my_method(self, x):
        print(f"Method with one argument: {x}")

    def my_method(self, x, y):
        print(f"Method with two arguments: {x}, {y}")

obj = MyClass()
obj.my_method(1, 2)  # 输出:Method with two arguments: 1, 2

在上述示例中,MyClass定义了两个名为my_method的方法,一个接受一个参数,另一个接受两个参数。但是,由于Python只根据方法名称来选择方法,因此最后一个定义的方法会覆盖之前的方法。
要实现真正的方法重载,您可以使用不定长参数或默认参数。例如,您可以使用默认参数来处理不同数量的参数:

class MyClass:
    def my_method(self, x, y=None):
        if y is None:
            print(f"Method with one argument: {x}")
        else:
            print(f"Method with two arguments: {x}, {y}")

obj = MyClass()
obj.my_method(1)      # 输出:Method with one argument: 1
obj.my_method(1, 2)   # 输出:Method with two arguments: 1, 2

在这个示例中,my_method方法接受两个参数,其中y有一个默认值None,这样您可以根据参数的存在与否来执行不同的操作。这种方式允许您模拟方法重载的行为,根据传递的参数数量和类型执行不同的逻辑。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值