学习任务
1.理解面向过程编程和面向对象编程思想
2.明确类和对象的关系,会独立设计和使用类
3.会使用类创建对象,并添加属性
4.掌握类的属性和方法
5.掌握构造方法和析构方法的使用
重点
1.self的使用
2.构造方法和析构方法
3.类属性和实例属性
4.方法的重载
引入
面向过程:先分析解决问题的步骤,使用函数把这些步骤以此实现,使用的时候需要逐个调用函数 。
面向对象:把解决问题的事物分为多个对象 ,对象具备解决问题过程中的行为。
我认为面向过程,就好像自己亲力亲为做一件事,先做什么再做什么。
面向对象就好像自己培养有能力的人来为你做这件事。
面向对象概述
1:面向对象编程有两个非常重要的概念:类和对象。
2:对象是面向对象编程的核心。
3:具有相似特征和行为的事物的集合统称为类
4:对象是根据类创建的,一个类可以对应多个对象。
理解起来类就像是一个模具,而对象就是依据类这个模具生产出来的东西。
对象
对象的定义 某种事物的抽象(功能)
抽象原则包括数据抽象和过程抽象两个方面
1:数据抽象-定义对象属性;
2:过程抽象-定义对象操作。
封装、继承和多态
封装 | 把客观事物抽象并封装成对象 |
继承 | 允许使用现有类的功能,并在无需重新改写原来的类的情况下,对这些功能进行扩展 |
多态 | 对象可以表示多个类型的能力 |
类和对象
类的名称 | 类名,首字母必须大写,比如Person |
类的属性 | 一组数据,比如性别 |
类的方法 | 允许进行操作的方法,比如说话 |
使用class关键字来声明一个类,基本格式如下
class 类名:
类的属性
类的方法
根据类创建对象的语法格式如下:
对象名 = 类名()
要想给对象添加属性,可以通过如下方式:
对象名.新的属性名 = 值
代码演示
class Person1:#定义类Person1
pass#为空语句占位
p1=Person1()
print(Person1,type(Person1),id(Person1))
print(p1,type(p1),id(p1))
<class '__main__.Person1'> <class 'type'> 2085640536560
<__main__.Person1 object at 0x000001E59A917AA0> <class '__main__.Person1'> 2085652363936
这段代码定义了一个名为 Person1
的类,然后创建了一个该类的实例 p1
。
-
print(Person1, type(Person1), id(Person1))
:Person1
的值是<class '__main__.Person1'>
,表示Person1
是一个类对象。type(Person1)
返回的是<class 'type'>
,表示Person1
的类型是类对象的类型,即 type 类型。id(Person1)
返回的是2085640536560
,这是Person1
的内存地址,用于标识Person1
在内存中的位置。
-
print(p1, type(p1), id(p1))
:p1
的值是<__main__.Person1 object at 0x000001E59A917AA0>
,表示p1
是一个 Person1 类的对象,并给出了该对象的内存地址。type(p1)
返回的是<class '__main__.Person1'>
,表示p1
的类型是 Person1 类的实例。id(p1)
返回的是2085652363936
,这是p1
的内存地址,用于标识p1
在内存中的位置。
总体来说,这段代码显示了类对象 Person1
和类实例对象 p1
的信息,包括它们的类型和内存地址。
id()
内存地址是计算机在内存中存储变量数据的位置。在 Python 中,id()
函数返回的是对象的内存地址,它是唯一的,用于标识一个对象。
属性--实例属性
通过“实例.属性”添加的属性都是实例属性
通过self.变量名定义的属性。
定义类,定义成员变量。
def __init__(self):
#实例属性
self.age = 1
在 Python 中,实例属性是与特定类的每个实例相关联的属性。self
参数在类的方法中用于引用这些实例属性。当你创建类的实例时,每个实例都会有自己的一组属性,而这些属性的值可能因实例而异。为了使每个实例都能访问和修改其自己的属性,Python 使用 self
参数来引用实例本身。
在类的方法中,通过 self
参数可以访问实例的属性和方法。当你调用一个实例方法时,Python 会自动将调用该方法的实例传递给 self
参数,使得方法内部能够访问实例的属性。这种机制使得类的方法能够操作特定实例的数据,而不是类本身的数据。
例如,在下面的代码中,self.name
和 self.age
分别表示 Person
类的实例的姓名和年龄属性:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def print_info(self):
print("Name:", self.name)
print("Age:", self.age)
# 创建一个 Person 实例
person1 = Person("Alice", 30)
# 调用实例方法
person1.print_info()
在 __init__()
方法中,self.name
和 self.age
将姓名和年龄属性绑定到创建的实例上。在 print_info()
方法中,通过 self.name
和 self.age
可以访问实例的姓名和年龄属性,并将它们打印出来。
class Person2: #定义类Person2
def __init__(self, name,age): #__init__方法
self.name = name #初始化self.name,即成员变量name(域)
self.age = age #初始化self.age,即成员变量age(域)
def say_hi(self): #定义类Person2的函数say_hi()
print('您好, 我叫', self.name) #在实例方法中通过self.name读取成员变量name(域)
#测试代码
p1 = Person2('张三',25) #创建对象
p1. say_hi () #调用对象的方法
print(p1.age) #通过p1.age(obj1.变量名)读取成员变量age(域)
补充
1:定义类,定义成员变量 是什么意思
在面向对象编程中,定义类是指创建一个类,这个类描述了一个抽象的概念或实体,其中包含了一组属性和方法。类是对象的模板,它定义了对象应该具有的特征和行为。
定义成员变量则是在类中定义变量,这些变量被称为类的成员变量或实例变量。成员变量存储在对象中,并且每个对象都有自己的一组成员变量的副本。成员变量用于描述对象的状态或特征。
下面是一个简单的例子,演示了如何在 Python 中定义一个类和成员变量:
class Person:
def __init__(self, name, age):
self.name = name # 定义一个成员变量 name
self.age = age # 定义一个成员变量 age
# 创建一个 Person 实例
person1 = Person("Alice", 30)
# 访问成员变量并打印
print("Name:", person1.name)
print("Age:", person1.age)
在上面的例子中,Person
类具有两个成员变量 name
和 age
,它们分别表示人的姓名和年龄。在 __init__()
方法中,通过 self.name
和 self.age
将传递给构造函数的参数值赋给这两个成员变量。然后,创建一个 Person
类的实例 person1
,并通过 person1.name
和 person1.age
访问和打印这两个成员变量的值。
2:成员变量与类的属性的关系
成员变量与类的属性是相关的概念,它们通常在面向对象编程中用来描述对象的特征或状态。
在 Python 中,成员变量通常被称为实例变量,因为它们是与特定类的每个实例相关联的变量。而类的属性则是指属于类本身的变量,它们可以在类的所有实例之间共享。
在一个类中定义的变量可以是类的属性,也可以是实例的成员变量。当变量被定义为类的属性时,它属于类本身,可以通过类名直接访问。而当变量被定义为实例的成员变量时,它属于类的每个实例,必须通过实例对象来访问。
下面是一个示例,演示了类的属性和实例的成员变量的区别:
class MyClass:
class_attr = "I am a class attribute" # 类的属性
def __init__(self, instance_attr):
self.instance_attr = instance_attr # 实例的成员变量
# 访问类的属性
print(MyClass.class_attr)
# 创建实例并访问实例的成员变量
instance1 = MyClass("Instance attribute 1")
print(instance1.instance_attr)
instance2 = MyClass("Instance attribute 2")
print(instance2.instance_attr)
在上面的示例中,class_attr
是类的属性,可以通过类名直接访问;而 instance_attr
是实例的成员变量,必须通过实例对象来访问。
属性--类属性
类属性是类所拥有的属性,它需要在类中进行显示地定义(位于类内部,方法的外面),它被所有类的实例对象所共有,在内存中只存在一个副本
类属性示例代码:
class Cat(object):
#类属性
num = 0
类属性:类本身的变量
代码演示
class Person3:
count = 0 #定义属性count,表示计数
name = "Person" #定义属性name,表示名称
#测试代码
Person3.count += 1 #通过类名访问,将计数加1
print(Person3.count) #类名访问,读取并显示类属性
print(Person3.name) #类名访问,读取并显示类属性
p1 = Person3() #创建实例对象1
p2 = Person3() #创建实例对象2
print((p1.name, p2.name)) #通过实例对象访问,读取成员变量的值
Person3.name = "雇员" #通过类名访问,设置类属性值
print((p1.name, p2.name)) #读取成员变量的值
p1.name = "员工" #通过实例对象访问,设置实例对象成员变量的值
print((p1.name, p2.name)) #读取成员变量的值
运行结果
1
Person
('Person', 'Person')
('雇员', '雇员')
('员工', '雇员')
解释
内存中只存在一个副本
"只存在一个副本"意味着类属性在内存中只有一份拷贝,不论有多少个类的实例对象被创建,它们都共享相同的类属性。当类属性被修改时,所有实例对象所看到的该属性的值都会随之改变,因为它们都指向相同的内存地址。
这种共享特性使得类属性非常适合用于描述类的特征或状态,例如描述某个类的所有实例对象所共有的特性。
代码演示
class MyClass:
class_attr = "I am a student"
# 创建实例对象
obj1 = MyClass()
obj2 = MyClass()
# 访问类属性
print(obj1.class_attr) # 输出:"I am a student"
print(obj2.class_attr) # 输出:"I am a student"
# 修改类属性
MyClass.class_attr = "I am a teacher"
# 打印修改后的类属性
print(obj1.class_attr) # 输出:"I am a teacher"
print(obj2.class_attr) # 输出:"I am a teacher"
属性--私有属性和公有属性
-
私有属性:
- 私有属性是指在类的内部定义的属性,其命名通常以双下划线
__
开头,例如__private_attr
。 - 私有属性只能在类的内部访问,无法在类的外部直接访问。这意味着在类外部不能直接通过实例对象或类名来访问私有属性,而只能在类的内部使用。
- 通过在方法内部定义或使用私有属性,可以帮助实现数据隐藏和封装,提高类的封装性和安全性。
- 私有属性是指在类的内部定义的属性,其命名通常以双下划线
-
公有属性:
- 公有属性是指在类的内部定义的属性,其命名通常不以双下划线开头,或者以单下划线
_
开头,例如public_attr
或_protected_attr
。 - 公有属性可以在类的内部和外部直接访问,可以通过实例对象或类名来访问。
- 公有属性的访问权限更开放,可以被外部代码直接访问和修改,但也可能导致数据的不安全性和代码的耦合性增加。
- 公有属性是指在类的内部定义的属性,其命名通常不以双下划线开头,或者以单下划线
代码展示;
class MyClass:
def __init__(self):
self.public_attr = "I am a student" # 公有属性
self.__private_attr = "I am a teacher" # 私有属性
def get_private_attr(self):
return self.__private_attr # 在类的内部访问私有属性
# 创建实例对象
obj = MyClass()
# 访问公有属性
print(obj.public_attr) # 输出:"I am a student"
# 访问私有属性(会导致错误)
#print(obj.__private_attr) # 会抛出 AttributeError: 'MyClass' object has no attribute '__private_attr'
# 通过方法访问私有属性
print(obj.get_private_attr()) # 输出:"I am a teacher"
通过方法访问私有属性
class MyClass:
def __init__(self):
self.__private_attr = "I am a teacher" # 私有属性
def get_private_attr(self):
return self.__private_attr # 通过方法获取私有属性的值
def set_private_attr(self, value):
self.__private_attr = value # 通过方法设置私有属性的值
# 创建实例对象
obj = MyClass()
# 通过方法获取私有属性的值
print(obj.get_private_attr()) # 输出:"I am a teacher"
# 通过方法设置私有属性的值
obj.set_private_attr("New value")
print(obj.get_private_attr()) # 输出:"New value"
在上面的示例中,get_private_attr()
方法用于获取私有属性 __private_attr
的值,而 set_private_attr(value)
方法用于设置私有属性的值。通过这种方式,可以在类的外部间接地访问和修改私有属性,而不直接暴露私有属性本身
补充
实例属性与私有属性的关系
实例属性和私有属性是两个不同的概念,它们之间并不完全相同。
实例属性是属于类的实例的属性,它们存储在实例的命名空间中,并且可以通过实例访问和修改。实例属性通常在类的 __init__
方法中初始化,但也可以在任何地方动态添加。
私有属性是一种访问限制,用于防止直接访问和修改类的属性。在Python中,可以通过在属性名前添加双下划线 __
来定义私有属性。私有属性只能在类的内部访问,无法在类的外部直接访问。
尽管实例属性通常不会被定义为私有属性,但你可以在实例属性前添加双下划线来模拟私有属性的效果。然而,这种做法并不是Python推荐的做法,因为Python并没有严格的私有属性机制,双下划线只是一种名称修饰约定,而不是真正意义上的私有属性。
总的来说,实例属性是类实例的属性,而私有属性是一种访问限制。尽管可以将实例属性定义为私有属性,但这并不是实例属性的本质,而是一种访问控制的手段。
属性--属性装饰器
常用的属性装饰器包括 @property
、@<property_name>.setter
、@<property_name>.deleter
等。这些装饰器可以帮助我们实现属性的封装、计算属性、属性值的验证等功能。
-
封装属性访问:属性装饰器可以将类的方法转换为属性,从而隐藏属性的具体实现细节,使得属性的访问更加简洁和直观。通过使用
@property
装饰器,可以将方法转换为只读属性,而使用@<property_name>.setter
装饰器则可以定义属性的设置方法。 -
计算属性:属性装饰器还可以用于计算属性的值。通过定义只读属性的方法,可以在访问属性时动态计算其值,而无需存储额外的数据。这种方式可以节省内存空间,并且可以确保属性的值始终是最新的。
-
属性值验证:属性装饰器还可以用于对属性值进行验证。通过在属性的设置方法中添加验证逻辑,可以确保属性的值符合预期的范围或格式,从而提高代码的健壮性和可靠性。如果属性值不满足验证条件,可以引发异常或采取其他适当的处理方式。
-
属性删除:除了获取和设置属性值外,属性装饰器还可以用于定义属性的删除方法。通过使用
@<property_name>.deleter
装饰器,可以定义在删除属性时执行的操作,例如释放资源或执行清理操作。 -
增强属性的功能:属性装饰器还可以用于增强属性的功能。例如,可以在属性的设置方法中添加日志记录、缓存更新等额外的逻辑,从而使属性具有更多的功能和用途。
属性--自定义属性
自定义属性是指在类中定义的用于描述类实例特征或状态的变量。在Python中,可以通过在类的方法中直接操作类的实例变量来定义自定义属性。
代码解释
class Person:
def __init__(self,name,age):
self.name = name
self.age = age
def introduce(self):
print(f"大家好,我叫{self.name},今年{self.age}岁。")
person=Person("张三",25)
print(person.name)
print(person.age)
person.introduce()
张三
25
大家好,我叫张三,今年25岁。
补充
实例属性与自定义属性的关系
实例属性和自定义属性是相关但不完全相同的概念,它们之间有一定的关系,但并不等价。
实例属性是指属于类的实例的属性,它们存储在实例的命名空间中,并且每个实例都有自己的一组实例属性。实例属性通常在类的 __init__
方法中初始化,并且可以在任何地方通过实例访问和修改。
自定义属性是指在类中显式定义的属性,它们可以是实例属性,也可以是类属性。自定义属性通常用于描述类的特征或状态,例如一个人的姓名、年龄等。自定义属性的定义通常在类的定义中进行,并且可以通过类的实例访问和修改。
因此,实例属性是自定义属性的一种,而自定义属性不仅限于实例属性,还可以是类属性。类属性是属于类本身的属性,在类的所有实例之间共享。与实例属性不同,类属性的值在所有实例之间是共享的,可以通过类名或实例访问和修改。
总的来说,实例属性是类实例特有的属性,而自定义属性是在类中显式定义的属性,可以是实例属性也可以是类属性。实例属性是自定义属性的一种形式,而自定义属性则是描述类的特征和状态的一种机制。
方法--实例方法
实例方法是面向对象编程中的一种方法,它与特定类的实例相关联,并且可以访问该类的实例变量和其他实例方法。
声明方式
def 方法名(self,[形参列表]):
函数体
调用格式
对象.方法名([实参列表])
假设我们有一个名为Car
的类,它表示汽车,其中包含实例变量color
和speed
,以及两个实例方法accelerate()
和brake()
。实例方法通过在方法定义中使用self
参数来访问实例变量。
class Car:
def __init__(self, color, speed):
self.color = color
self.speed = speed
def accelerate(self, increase):
self.speed += increase
def brake(self, decrease):
self.speed -= decrease
# 创建一个名为my_car的Car实例
my_car = Car("red", 0)
# 使用实例方法加速
my_car.accelerate(10)
print("当前速度:", my_car.speed) # 输出: 当前速度: 10
# 使用实例方法减速
my_car.brake(5)
print("当前速度:", my_car.speed) # 输出: 当前速度: 5
在上面的示例中,accelerate()
和brake()
方法都是实例方法,它们可以访问Car
类的实例变量speed
,并根据传入的参数增加或减少速度。
总结一下,实例方法是与特定类的实例相关联的方法,它们可以访问并操作该类的实例变量。
方法--静态方法
声明属于与类的对象实例无关的方法
静态方法不对特定实例进行操作,在静态方法中访问对象实例会导致错误
静态方法通过装饰器@staticmethod来定义
@staticmethod
def 静态方法名([形参列表]):
函数体
静态方法一般通过类名来访问,也可以通过对象实例来调用
类名.静态方法名([实参列表])
静态方法是不依赖于类的实例而存在的方法,它们与特定类相关联,但在调用时不传递类实例。静态方法通常与类的某些功能相关联,但不需要访问类的实例变量。
假设我们有一个名为MathUtils
的类,其中包含一个静态方法add()
,用于执行简单的加法操作。这个方法不依赖于MathUtils
类的任何实例。
class MathUtils:
@staticmethod
def add(x, y):
return x + y
# 调用静态方法,不需要创建MathUtils类的实例
result = MathUtils.add(3, 5)
print("加法结果:", result) # 输出: 加法结果: 8
在上面的示例中,add()
方法是一个静态方法,它不需要通过实例来调用,而是直接通过类名MathUtils
调用。静态方法通常用于执行与类相关的一些通用功能,而不需要访问类的实例变量。
总结一下,静态方法是与类相关联的方法,但在调用时不需要传递类的实例,它们通常用于执行一些与类相关的通用功能。
方法--类方法
允许声明属于类本身的方法,即类方法
类方法不对特定实例进行操作,在类方法中访问对象实例属性会导致错误
类方法通过装饰器@classmethod来定义,第一个形式参数必须为类对象本身,
@classmethod
def 类方法(cls,[形参列表]):
函数体
类方法一般通过类名来访问,也可通过对象实例来调用
类名.类方法名([实参列表])
类方法是与类本身相关联的方法,而不是与类的实例相关联的方法。类方法可以访问类变量,但不能直接访问实例变量。它们通常用于执行与类相关的操作,而不需要访问或修改特定实例的状态。
假设我们有一个名为Employee
的类,其中包含一个类方法get_company_name()
,用于返回公司的名称。这个方法不依赖于Employee
类的任何实例,但它可以访问类变量company_name
。
class Employee:
company_name = "ABC Corp" # 类变量
@classmethod
def get_company_name(cls):
return cls.company_name
# 调用类方法,不需要创建Employee类的实例
company = Employee.get_company_name()
print("公司名称:", company) # 输出: 公司名称: ABC Corp
在上面的示例中,get_company_name()
方法是一个类方法,它通过@classmethod
装饰器来声明。在方法内部,通过cls
参数可以访问类变量company_name
。
总结一下,类方法是与类本身相关联的方法,它们可以访问类变量,但不需要类的实例。通常用于执行与类相关的操作,而不需要访问特定实例的状态。
方法--构造方法
__init__方法即构造函数(构造方法),用于执行类的实例的初始化工作。创建完对象后调用,初始化当前对象的实例,无返回值,这个方法的第一个参数通常是self
,它表示正在创建的实例对象本身,然后可以接受其他参数用于初始化实例的各个属性。
Python示例来说明构造方法
class Car:
def __init__(self, color, brand):
self.color = color
self.brand = brand
# 创建一个名为my_car的Car对象,并传入颜色和品牌信息
my_car = Car("red", "Toyota")
# 打印对象的属性
print("颜色:", my_car.color) # 输出: 颜色: red
print("品牌:", my_car.brand) # 输出: 品牌: Toyota
__new__方法是一个类方法,创建对象时调用,返回当前对象的一个实例,一般无需重载该方法
它是在 __init__
方法之前调用的。与 __init__
方法不同,__new__
方法是一个类方法,而不是实例方法,并且必须返回一个新创建的实例。通常情况下,你不需要自己定义 __new__
方法,因为 Python 提供的默认实现通常就足够了。
__new__
方法通常在以下情况下被用到:
-
自定义对象的创建过程:当你需要控制对象的创建过程时,可以重写
__new__
方法。例如,你可能想要在创建对象之前执行某些额外的逻辑,或者根据不同的条件返回不同的实例。 -
不可变类型的实现:对于不可变类型(例如 int、str、tuple 等),
__new__
方法可以用来创建新的实例。这些类型的实例在创建后不可更改,因此需要在__new__
方法中进行适当的处理。
class MySingleton:
_instance = None
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super().__new__(cls, *args, **kwargs)
return cls._instance
# 创建两个 MySingleton 的实例
singleton1 = MySingleton()
singleton2 = MySingleton()
print(singleton1 is singleton2) # 输出: True,因为它们是同一个实例
在上面的示例中,MySingleton
类使用 __new__
方法来实现单例模式。__new__
方法检查类变量 _instance
是否为 None,如果是,则创建一个新的实例,并将其赋值给 _instance
,否则返回已存在的实例。
总之,__new__
方法是在 Python 中用于创建对象实例的特殊方法,它允许你在对象创建过程中进行一些额外的控制或逻辑处理。
方法--析构方法
析构方法(Destructor Method)是一个在对象被销毁(即被垃圾收集器回收)时自动调用的特殊方法。在 Python 中,析构方法由 __del__
方法实现。与 __init__
方法和 __new__
方法类似,__del__
方法也是一个特殊方法,用于在对象即将被销毁时执行清理工作。
当对象不再被引用,且没有任何变量指向它时,Python 的垃圾收集器会自动回收该对象的内存空间。在这个回收过程中,如果对象定义了 __del__
方法,那么该方法会被调用,允许对象执行一些清理工作,例如关闭文件、释放资源等。
虽然 __del__
方法提供了执行清理工作的机会,但是在实际编程中,你可能不需要经常使用它,因为 Python 的垃圾收集器通常会很好地管理对象的生命周期。此外,由于垃圾收集器的工作机制可能会导致 __del__
方法的调用时间不确定,因此不应该依赖于 __del__
方法来释放关键资源。
class MyClass:
def __init__(self, name):
self.name = name
def __del__(self):
print(f"对象 {self.name} 被销毁了")
# 创建一个对象实例
obj = MyClass("example")
# 手动删除对象的引用
del obj
# Python 的垃圾收集器会自动回收对象,触发析构方法的调用
方法--私有方法和公有方法
-
私有方法:
- 私有方法是类中仅供内部使用的方法,外部无法直接访问。
- 在Python中,通过在方法名前加上双下划线
__
来定义私有方法,例如def __private_method(self):
。 - 私有方法只能在类的内部使用,不能在类的外部直接调用。
- 通常情况下,私有方法用于实现类的内部逻辑,或者作为公有方法的辅助函数。
-
公有方法:
- 公有方法是类中可以被外部访问和调用的方法。
- 在Python中,如果方法名没有以双下划线
__
开头,那么它就是一个公有方法。 - 公有方法可以被类的实例调用,也可以通过类名直接调用。
- 公有方法通常用于对外提供类的功能接口,供其他类或模块使用
class MyClass:
def __init__(self, name):
self.name = name
def __private_method(self):
print("这是一个私有方法")
def public_method(self):
print("这是一个公有方法")
self.__private_method() # 在公有方法中调用私有方法
# 创建一个对象实例
obj = MyClass("example")
# 调用公有方法
obj.public_method()
# 尝试调用私有方法,会引发错误
# obj.__private_method() # 这行代码会引发 AttributeError
# 通过内部调用公有方法来间接调用私有方法
# obj._MyClass__private_method() # 这行代码会成功执行,但不建议这样做
在上面的示例中,__private_method()
是一个私有方法,只能在类的内部调用,而public_method()
是一个公有方法,可以被外部调用
方法--方法重载
方法重载(Method Overloading)是指在同一个类中,可以定义多个方法具有相同的名称但参数列表不同的情况。在Python中,方法重载并不是一种直接支持的特性,因为Python不支持方法的参数签名或类型检查。但是,可以通过一些技巧来实现类似的功能。
在Python中,方法重载通常通过使用默认参数值、可变参数或关键字参数来实现
补充
__str__用法
__str__ 方法是另一个特殊方法,在 Python 中用于定义对象的字符串表示形式。当你尝试打印对象时,Python 解释器会自动调用该对象的 __str__ 方法,以获取其字符串表示形式。
class Teacher(SchoolMember):
# 其他方法...
def __str__(self):
return f"Teacher: {self.name}, ID: {self.id}, Department: {self.department}"
class Student(SchoolMember):
# 其他方法...
def __str__(self):
return f"Student: {self.name}, ID: {self.id}, Grade: {self.grade}"
这样,当我们打印 Teacher 或 Student 对象时,就会使用定义的 __str__ 方法来显示对象的信息。