|
文章目录

面向对象编程
1. 什么是面向对象
面向对象编程是一种编程思想,它将现实世界的概念和关系映射到代码中.
在面向对象编程中,我们通过创建对象来表示现实世界中的事物,并通过定义对象的属性和方法来描述它们的状态和行为.
面向对象编程强调了代码的模块化、封装、抽象、继承和多态等概念.
例如, 在现实世界中我们需要去记录一名学生的基本信息, 如果使用文本来记录: 例如
有一名学生叫张三, 来自北京, 性别男. 这样可以轻松记录一名学生的信息.
但是使用如下表格, 结构会更加的清晰.
姓名 | 张三 |
---|---|
年龄 | 20 |
籍贯 | 北京 |
性别 | 男 |
在现实世界中我们需要去记录一辆车的基本信息, 需要用到如下表格:
品牌 | |
---|---|
型号 | |
排量 | |
车架号 |
上述都表格都可以很清晰的描述学生和车辆的基本信息.
表格相当于是 一个蓝图或者模板. 每个学生都可以拿着这个表格, 填写自己对应的信息, 在程序中, 上面的表格就相当于是一个类, 通过这个类可以创建多个学生对象.
2. 类(class)
类和对象是面向对象编程的核心概念.
类是一个抽象的概念,用于描述对象的属性(数据)和方法(行为).
对象则是类的具体实例,表示一个具体的实体.
类(class)
类是一种模板或蓝图,用于创建对象.它定义了对象的属性和方法,描述了对象的状态和行为.类通过定义一组相关的属性和方法来封装数据和操作,从而提供了一种组织和管理代码的方式.
Python 中的一切对象都有各自的类型,比如:
整数对象 的类型是 int
字符串对象 的类型是 str
列表对象 的类型是 list
元组对象 的类型是 tuple
字典对象 的类型是 dict
Python 的内置函数type可以查看对象的类型:
>>> type(12)
<class 'int'> # 整数类型
>>> type('12')
<class 'str'> # 字符类型
>>> type([1,2])
<class 'list'> # 列表类型
>>> type((1,2))
<class 'tuple'> # 元组类型
>>> type({1:2})
<class 'dict'> # 字典类型
我们掌握了这些内置的数据类型,通常就可以开发Python程序了.
但是当我们要开发的软件系统 更加复杂的时候,尤其是系统里面的对象 和现实世界的对象 存在对应关系的时候,如果只能用这些内置类型,就会感觉很不方便.
比如,我们的程序要表示一个 奔驰汽车 这样的对象类型,属性有:品牌,国家,价格.
如果只用Python的内置类型,大家想想怎么表示.
当然,我们可以定义一个字典类型的对象,比如:
benzCar = {
'brand' : '奔驰',
'country' : '德国',
'price' : 300000
}
如果这个汽车对象还需要有自己特定的行为,比如 按喇叭会发出嘟嘟的声音。那又该怎么定义呢?
有人说,可以定义一个函数对象作为它的属性,像这样:
def pressHorn():
print('嘟嘟~~~~~~')
benzCar = {
'brand' : '奔驰',
'country' : '德国',
'price' : 300000,
'pressHorn' : pressHorn # 字典对象的值可以是一个函数对象
}
# 我可以这样执行它的行为
benzCar['pressHorn']()
似乎也可以.
但是这里 benzCar 更像是一个具体的对象,并不是一种 对象类型.
而且 这个 benzCar 汽车的 行为的定义 ,要在外面定义一个函数, 然后benzCar字典的内部去引用它,这样也比较麻烦.
为了解决这样的普遍问题,Python语言可以让我们 自己定义对象类型.
Python中自定义对象类型,就是 定义一个类 , 类 就是 类型 的意思.
比如 : 奔驰汽车, 可以这样定义:
使用 class
关键字定义一个类.类名通常使用大写字母开头,遵循大驼峰命名规范.
class BenzCar:
brand = '奔驰' # 品牌属性
country = '德国' # 产地属性
@staticmethod
def pressHorn():
print('嘟嘟~~~~~~')
定义一个类 用关键字 class 后面加 类的名称.
类名的规范 和 变量命名规范一样。 通常我们会把类名 首字母大写, 这里定义的类名就是 BenzCar
下面定义的 brand, country 都是 BenzCar 类的 属性.
这种属性被称为类属性
如果我们要得到属性的值可以这样用 类名.属性名 的方式,如下
print(BenzCar.brand)
而 pressHorn 则是该类型的一个 方法.
请注意上面的 @staticmethod 的修饰, 说明这是该类的一个 静态方法
要调用执行该类的静态方法,像这样就可以了:
BenzCar.pressHorn()
类的属性
类的属性是与类相关联的数据,用于描述对象的特征或状态.
类的属性可以通过类名或对象访问.
类属性在类级别上定义,被所有类的实例共享.
类属性的定义实际上就是写在类中的变量.
(成员变量) - 注意不是实例属性哦
class Student:
name = '张三'
age = 0
在上面的示例中, Student类定义了2个类属性, name
和age
,它被所有Student类的实例共享. 类属性可以通过类名或者实例对象访问.
class Student:
name = '张三'
age = 18
# 类属性可以通过**类名或者实例对象**访问
print(Student.name)
print(Student.age)
print("-----------------------------")
stu = Student()
print(stu.name)
print(stu.age)
类的方法
类的方法是与类相关联的函数,用于定义对象的行为.方法在类中定义,并通过对象调用.方法可以访问和操作对象的属性.
class Student:
name = '张三'
age = 0
def introduce(self):
print(f'大家好, 我的名字叫{self.name}, 今年{self.age}岁')
def study(self):
print(f'{self.name}正在努力学习.')
stu = Student()
stu.introduce()
stu.study()
以上示例在Student
类中定义了2个方法, introduce
和study
. 用于定义对象的2个行为: 自我介绍和学习.
上述示例中方法中第一个形参是self
的方法叫做实例方法
. 类属性可以通过实例对象self来访问.
3. 类的实例
Python中 类 是 某种对象的类型.
比如 int 是 整数对象的类型, str是字符串对象的类型, list是 列表对象的类型.
我们把一个个具体的 对象称为 该类型的 实例,
比如,我们可以说
数字对象 3 是 int 类型的的实例,具有int类型的特征
字符串对象 ‘abc’ 是 str 类型的实例,具有str类型的特性(比如可以执行str的所有方法,比如 find, split等)
列表对象 [1,2,3] 是 list 类型的的实例,具有list类型的特性(比如可以执行list的所有方法,比如 reverse,append等)
同样的,我们自定义的类,也可以产生该类的实例对象. 每个实例对象就是该类的一个实例,具有该类的一切特征.
要产生一个类的实例对象,只需要 在类名后面加上括号,就可以了,就会返回一个该类的实例对象.
比如:
car1 = BenzCar()
car1 变量就对应了一个 BenzCar 类型 的实例对象,具有 BenzCar 类的一切属性和方法.大家可以执行下面的代码试试。
class BenzCar:
brand = '奔驰'
country = '德国'
@staticmethod
def pressHorn():
print('嘟嘟~~~~~~')
car1 = BenzCar()
print(car1.brand)
car1.pressHorn()
同样,我们也可以用 type 函数查看 car1 这个实例的类型,如下所示:
>>> type(car1)
<class '__main__.BenzCar'>
说明 car1 是 __main__ 模块里面定义的 BenzCar 类型.
大家一定要搞清楚 类 和 实例 的关系.
比如 :
人 就是 一个 类, 而 关羽、张飞 就是 人 这个类的 具体实例.
狗 也是 一个 类, 而 你们家的阿黄 和 隔壁家的旺财 就是狗 这个类的 具体实例.
Python中 定义一个类型 就是描述 这些类型的实例的 公共特征. 后面根据这个类创建的实例 都具有这个类的 特征,就是 具体什么 属性、方法.
在面向对象编程中,类的对象(Class Object)是类的具体实例, 所以类的对象也叫做实例对象.类定义了对象的属性和方法,而对象是类的实体,具有自己的属性值和对类中方法的访问权限.
实例属性和实例方法
刚才我们定义的类里面的属性都是 类属性 ,里面的方法都是类的 静态方法 .
所有BenzCar类的实例对象,其 品牌名 brand ,对应的类属性应该是相同的.
就是说下面这样的两个实例:
car1 = BenzCar()
car2 = BenzCar()
car1 和 car2 的 brand属性 都是一样的 值, 都是字符串 ‘奔驰’
很好理解,因为品牌这样的属性 对于所有的 奔驰车都是一样的,都是 ‘奔驰’.
类属性 是类的共同特征属性.
但是有些属性,比如颜色、发动机编号 是每一辆奔驰车 都不同的.
所以,在我们定义的 类BenzCar 里面, 颜色、发动机编号 是 不应该 作为类属性的.
每个实例独有的属性,称之为 类的实例属性
实例属性通常是在类的 初始化方法 init 里面定义的.
比如:
class BenzCar:
brand = '奔驰'
country = '德国'
@staticmethod
def pressHorn():
print('嘟嘟~~~~~~')
# 初始化方法, 注意前后各有两个下划线
def __init__(self):
self.color = 'red' # 颜色
self.engineSN = '837873398' # 发动机编号
上面的初始化方法 __init__ ,就创建了两个实例属性 color 和 engineSN。
为什么 __init__ 方法 叫初始化方法呢?
解释器在执行 像下面这样的 实例化类对象 的代码时,
car1 = BenzCar()
首先,解释器会 在内存中 创建一个该类 的 实例对象;
然后,解释器会查看这个类是否有 __init__方法,如果有,就会去调用它.
__init__ 是 创建好实例后 立即就要 执行 的方法,所以称之为初始化方法.
通常我们会在__init__方法里面 执行一些初始化的动作,主要就是创建该实例的 实例属性.
__init__ 方法的第一个参数是 self, 它 是干什么用的呢?
刚才说了, 解释器执行实例化代码,会先在内存中创建该类实例对象,然后调用类 的__init__方法.
调用 __init__方法时,就将实例对象 传递给 self参数.
self 参数变量 指向的 就是 实例对象 本身
, 所以下面的代码就是创建该实例的属性color 和 engineSN 了
self.color = 'red' # 颜色
self.engineSN = '8378738398' # 发动机编号
类的静态方法要在方法定义 上面加上 @staticmethod 的修饰.
而 类的 实例方法 不需要任何修饰.
通常类的实例方法,都是要 访问类的实例属性的. 包括: 创建、修改、删除 类的实例属性.
因为 实例方法 就是要操作 实例独有的属性,否则不操作任何实例属性的话,就应该定义为 类方法.
比如 __init__ 初始化方法,就是一个实例方法,它通常要创建一些实例属性.
而 pressHorn 方法是类的静态方法, 静态方法是不能访问实例属性的.
有时候,实例属性的取值,不是固定写在初始化方法的代码里面.
比如这里,每辆车的颜色、发动机号都是不同的,我们应该作为参数传进去.
所以修改代码为这样:
class BenzCar:
brand = '奔驰'
country = '德国'
@staticmethod
def pressHorn():
print('嘟嘟~~~~~~')
def __init__(self,color,engineSN):
self.color = color # 颜色
self.engineSN = engineSN # 发动机编号
这样我们在创建实例的时候,就可以根据需要指定不同的实例属性了,比如:
car1 = BenzCar('白色','24503425527866')
car2 = BenzCar('黑色','34598423586877')
print(car1.color)
print(car2.color)
print(car1.engineSN)
print(car2.engineSN)
虽然定义的时候, init 方法 有3个参数 : self,color,engineSN
但是我们这样调用 BenzCar() 实例化的时候, 只需要传入后面两个参数即可,
因为self 参数 需要传入实例对象本身,解释器会自动帮我们传入.
其它的 实例方法也是这样, 比如我们定义一个 修改车身颜色的方法 changeColor:
class BenzCar:
brand = '奔驰'
country = '德国'
@staticmethod
def pressHorn():
print('嘟嘟~~~~~~')
def __init__(self,color,engineSN):
self.color = color # 颜色
self.engineSN = engineSN # 发动机编号
def changeColor(self,newColor):
self.color = newColor
car1 = BenzCar('白色','24503425527866')
car1.changeColor('黑色')
print (car1.color)
调用 changeColor方法的时候,只需要传入参数 newColor 对应新的颜色即可.
不需要我们传入self参数,self 参数是实例对象本身,解释器会自动帮我们传入.
注意: 如果你的实例属性名称 和 静态属性(类属性) 重复了 ,通过类实例访问该属性,访问的是实例属性通过类名访问该属性,访问的是类属性.
比如:
class Car:
brand = '奔驰'
name = 'Car'
def __init__(self):
# 可以通过实例访问到类属性
print(self.brand)
# 定义实例属性和类属性重名
self.name = 'benz car'
c1 = Car()
print(f'通过实例名访问name:{c1.name}')
print(f'通过类名 访问name:{Car.name}')
一旦创建了 和类属性同名的 实例属性,通过实例访问的就是实例属性了
实例方法是指定义在类中的方法, 它可以访问和操作对象的实例属性, 并且在调用时会自动传入对象自身(通常用 self
来表示)作为第一个参数.
实例方法是与类的实例(对象)关联的, 并且可以访问和修改对象的状态.
使用实例方法时, 需要先创建类的实例(对象), 然后通过对象调用方法, 在调用实例方法时, 不需要手动传入 self
参数, Python会自动将对象本身传递给方法.
关于self
在实例方法中, 第一个参数通常是 self, 表示对象自身.
定义实例方法时, 必须将 self 作为方法的第一个参数.通过 self, 方法可以访问对象的属性和其他方法.- 在创建类的实例(对象)时, Python会自动传递 self 参数给实例方法, 不需要手动传入.当调用对象的方法时, 无需显式传递 self, Python会自动将对象本身传递给方法.
- 在实例方法内部, 可以通过 self 来访问对象的属性和方法.例如,
self.attribute
可以访问对象的属性,self.method()
可以调用对象的其他方法
4. 对象的初始化
__init__
是Python中一个特殊的方法, 用于初始化对象的属性.它是在创建对象时自动调用的构造方法, 也叫做魔法方法.
在类的定义中, __init__
方法用于初始化对象的属性.通常, 在创建对象时需要对对象的属性进行初始化操作, 比如设置默认值或接收外部传入的参数.
__init__
方法的命名是固定的, 必须使用双下划线 __
前缀和后缀.在调用类创建对象时, Python会自动调用类的 __init__
方法来初始化对象的属性.
注意: __init__
方法只能返回None, 不能有其他返回值.
实例属性
实例属性是指定义在类的实例(对象)中的属性, 每个对象都有自己独立的实例属性.实例属性用于存储对象的状态和数据, 并且在类的实例化过程中被赋予特定的值.
在Python中, 实例属性通常是在类的构造方法 __init__
中使用 self
关键字定义的.(类的实例属性在类外(或者说是__init__方法外定义的实例属性)也有定义的情况)
每个实例属性都是一个对象独有的变量, 不同的对象之间互不干扰.
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
def introduce(self):
print(f"大家好, 我的名字叫{self.name}, 今年{self.age}岁")
self.study_course('英语')
def study_course(self, course):
print(f"{self.name}正在努力学习{course}")
stu1 = Student("李四", 18)
stu1.introduce()
stu1.study_course("english")
stu2 = Student("张三", 20)
stu2.introduce()
stu2.study_course("maths")
实例属性和类属性总结
定义位置:
- 实例属性:实例属性是定义在类的方法中(通常是在构造函数
__init__
中)通过self
关键字定义的,每个实例(对象)都有自己的一份实例属性.
类属性:类属性是定义在类的方法之外的属性, 直接在类的内部定义的, 属于整个类, 所有实例共享同一份类属性.
- 实例属性:实例属性是定义在类的方法中(通常是在构造函数
存储位置:
实例属性:每个实例(对象)都有自己独立的实例属性, 存储在对象中.
类属性:类属性属于整个类, 存储在类中.
值的独立性:
- 实例属性:不同实例的同名实例属性是相互独立的, 一个实例的实例属性修改不会影响其他实例.
- 类属性:所有实例共享同一份类属性, 但是通过一个实例修改类属性时, 这个修改不会影响其他实例的类属性.类属性是属于类的, 而不是属于实例的, 因此每个实例都拥有独立的类属性副本, 互不影响.
访问方式:
实例属性:通过对象访问, 使用表达式
对象名.属性名
.类属性:可以通过类名访问, 也可以通过对象访问.使用表达式
类名.属性名
或对象名.属性名
.
5. __str__
__str__
是Python中的特殊方法(魔法方法), 用于定义类的实例对象的字符串表示.
当我们使用print函数或str()函数打印一个类的实例对象时, 实际上是调用了该对象的__str__方法来获取其字符串表示.
如果在类中定义了__str__
方法, 那么当我们打印该类的实例时, 会输出__str__
方法返回的字符串.这对于自定义类的字符串表示非常有用, 可以让我们以更加直观和可读的方式展示对象的内容.
主要用途包括:
- 打印:当你使用
print
函数打印一个对象时, 实际上是调用该对象的__str__
方法来获取其字符串表示, 从而以更直观和易读的方式显示对象的信息. - 字符串转换:当你使用
str()
函数来将一个对象转换为字符串时, 同样会调用该对象的__str__
方法, 以获得其字符串表示. - 字符串格式化:在字符串格式化时, 如果包含了对象, Python会自动调用对象的
__str__
方法, 以便获取对象的字符串表示.
class Student:
# 类属性
gender = '男'
def __init__(self, name, age):
# 实例属性
self.name = name
self.age = age
def introduce(self):
print(f"大家好, 我的名字叫{self.name}, 今年{self.age}岁")
self.study_course()
def study_course(self, course="英语"):
print(f"我正在努力学习{course}")
def __str__(self):
return f"学生: {self.name}, {self.age}, {self.gender}"
# 1. 打印
stu = Student("李四", 18)
print(stu)
# 2. 字符串转换
stu_string1 = str(stu)
print(stu_string1)
# 3. 字符串格式化
stu_string2 = f'{stu}'
print(stu_string2)
# 输出结果:
学生: 李四, 18, 男
学生: 李四, 18, 男
学生: 李四, 18, 男
6. 类之间的关系
继承关系
真实世界中,类型之间 可能存在 范围 包含关系.
比如:人 这个类型 和 亚洲人 这个类型.
人 是包括了 亚洲人 的。 如果 某人 是一个 亚洲人,那么它必定是一个 人.
这种关系,编程语言中称之为 继承关系.
比如上面的例子, 亚洲人 这个类 就 继承 了 人 这个类.
通常我们把被继承的类称之为 父类 或者叫 基类.
把继承类称之为 子类 或者 派生类.
同样的,以车为例, 上面我们定义了奔驰车 这个类, 我们还可以定义两个 子类: 奔驰2016 和 奔驰2018 对应两种不同款的奔驰车.
如下所示:
class BenzCar:
brand = '奔驰'
country = '德国'
@staticmethod
def pressHorn():
print('嘟嘟~~~~~~')
def __init__(self,color,engineSN):
self.color = color # 颜色
self.engineSN = engineSN # 发动机编号
def changeColor(self,newColor):
self.color = newColor
class Benz2016(BenzCar):
price = 580000
model = 'Benz2016'
class Benz2018(BenzCar):
price = 880000
model = 'Benz2018'
大家可以发现定义子类的时候,必须指定它的父类是什么.
指定的方法就是在类名的后面的括号里写上父类的名字.
大家注意: 子类会自动拥有父类的一切属性和方法
为什么? 因为一个子类的实例对象 ,必定也是一个父类的实例对象. 当然需要拥有父类的一切属性和方法.
就像 一个亚洲人 当然 拥有一个 人 所应该具有的一切特性.
比如,执行下面的代码:
car1 = Benz2016('red','234234545622')
car2 = Benz2018('blue','111135545988')
print (car1.brand)
print (car1.country)
car1.changeColor('black')
print (car2.brand)
print (car2.country)
car2.pressHorn()
输出结果如下:
奔驰
德国
奔驰
德国
嘟嘟~~~~~~
一个子类在继承父类的一切特性的基础上,可以有自己的属性和方法.
比如:
class Benz2018(BenzCar):
price = 880000
model = 'Benz2018'
def __init__(self,color,engineSN,weight):
# 先调用父类的初始化方法
BenzCar.__init__(self,color,engineSN)
self.weight = weight # 车的重量
self.oilweight = 0 # 油的重量
# 加油
def fillOil(self, oilAdded):
self.oilweight += oilAdded
self.weight += oilAdded
这里 子类 Benz2018 ,新增了两个 类属性
价格: price
型号: model
新增了两个实例属性
整车重量:weight
油的重量:oilweight
新增了一个实例方法 fillOil , 对应 加油这个行为.
这个行为会导致 实例属性 weight 和 oilweight 变化,所以必须是 实例方法.
这样定义好了以后, 就可以创建该类的实例,并访问其新的方法和属性了.
car2 = Benz2018('blue','111135545988',1500)
print (car2.oilweight)
print (car2.weight)
car2.fillOil(50)
print (car2.oilweight)
print (car2.weight)
要特别注意的是, 子类的初始化方法里面,如果有一部分的初始化代码和父类的初始化相同(通常都是这样),需要显式的 调用父类的初始化方法 __init__
而且要传入相应的参数, 像上面那样,然后可以加上自己的特有的初始化代码. 如下所示:
def __init__(self,color,engineSN,weight):
# 先调用父类的初始化方法
BenzCar.__init__(self,color,engineSN)
self.weight = weight
self.oilweight = 0
如果子类 没有 自己的初始化方法,实例化子类对象时,解释器会自动调用父类初始化方法,如下:
class Rect:
def __init__(self):
print('初始化 rect')
class Squre(Rect):
pass
s = Squre()
运行结果,会打印出 ‘初始化 rect’
但是,如果子类 有自己 的初始化方法,实例化子类对象时,解释器就不会自动化调用父类的初始化方法,如下
class Rect:
def __init__(self):
print('初始化 rect')
class Square(Rect):
def __init__(self):
print('初始化 square')
s = Squre()
运行结果只会打印 初始化 square.
调用父类的方法,除了直接用父类的名字 BenzCar, 还可以使用 函数 super()
像这样:
def __init__(self,color,engineSN,weight):
# 同样是调用父类的初始化方法
super().__init__(color, engineSN)
self.weight = weight
self.oilweight = 0
这样使用的时候,方法参数中 不需要加上 self 参数.
使用 super 的好处之一就是:子类中调用父类的方法,不需要 显式指定 父类的名字. 代码的可维护性更好.
想象一下,如果 BenzCar 有很多子类,如果哪一天 BenzCar 类改了名字,采用 super 这样的写法,就不需要修改子类的代码了.
注意 super不仅仅可以调用父类的初始化方法,也可以调用父类的其他方法.
一个子类,同时还可以是另一个类的父类,
比如 亚洲人 可以是 人 的子类, 同时可以是 中国人 的父类.
因为一个中国人,一定是一个亚洲人, 当然也一定是一个 人.
同样的,上面的车的例子, 我们还可以定义 奔驰2018混合动力 作为 奔驰2018 的 子类.
定义的语法还是一样的:
class Benz2018Hybrid(Benz2018):
model = 'Benz2018Hybrid'
price = 980000
def __init__(self,color,engineSN,weight):
Benz2018.__init__(self,color,engineSN,weight)
同样,类 Benz2018Hybrid 也会拥有其父类 Benz2018 的一切属性和方法,自然也包括 父类的父类 BenzCar 的一切属性和方法
car2 = Benz2018Hybrid('blue','111135545988',1500)
print (car2.oilweight)
print (car2.weight)
car2.fillOil(50)
print (car2.oilweight)
print (car2.weight)
组合关系
除了上面的继承关系, 类之间还有一种常见的组合关系.
所谓组合关系,就是一个类实例的属性里面包含另外一个类实例.
比如:
class BenzCar:
brand = '奔驰'
country = '德国'
def __init__(self,color,engineSN):
self.color = color # 颜色
self.engineSN = engineSN # 发动机编号
这样的定义,类 BenzCar 中
brand 属性就是一个字符串对象 奔驰
country 属性就是一个字符串对象 德国
而该类的实例对象中,就包含了 两个属性 color 和 engineSN, 都是字符串对象
我们可以说 该类由 一些字符串对象 组合 而成.
甚至还可以包含 我们自己定义的类的实例,比如:
# 轮胎
class Tire:
def __init__(self,size,createDate):
self.size = size # 尺寸
self.createDate = createDate # 出厂日期
class BenzCar:
brand = '奔驰'
country = '德国'
def __init__(self,color,engineSN,tires):
self.color = color # 颜色
self.engineSN = engineSN # 发动机编号
self.tires = tires
# 创建4个轮胎实例对象
tires = [Tire(20,'20160808') for i in range(4)]
car = BenzCar('red','234342342342566',tires)
上面的例子里,奔驰汽车对象就 包含 了4个轮胎 Tire 对象.
我们可以说奔驰汽车对象是由 4个轮胎对象 组合 而成,形成了对象的组合关系.
对象的 属性 变量 保存了 组合它的那些对象.
组合关系,可以通过上层对象的属性一步的访问到内部对象的属性
比如,我们可以通过 BenzCar 对象 访问其内部的轮胎对象
print(car.tires[0].size)
Python解释器对这个表达式 car.tires[0].size 是从左到右依次执行的,如下所示:
car.tires # BenzCar实例的tires属性,得到一个列表,里面是四个 Tire 实例对象
car.tires[0] # 得到BenzCar实例的tires属性列表里面的第1个Tire 实例对象
car.tires[0].size # 得到BenzCar实例的tires属性列表里面的第1个Tire 实例对象的size属性
7. 补充练习
"""
创建一个简单的学生管理系统,包含以下功能:
定义一个Student类,包含以下属性:学号(number),姓名(name),年龄(age),性别(gender)和成绩(score)。
实现类的初始化方法__init__,用于初始化学生的属性。
实现类的__str__方法,用于返回学生信息的字符串表示,格式为:学号:[学号],姓名:[姓名],年龄:[年龄],性别:[性别],成绩:[成绩]。
定义一个学生管理类StudentManager,用于管理学生信息。该类应该包含以下功能:
添加学生:能够添加一个学生的信息到学生列表中。
显示所有学生:能够打印出所有学生的信息。
因为之前我们已经做过了类似的管理系统, 所以这里就不再做很复杂的功能, 只做两个小功能达到练习的目的即可.
"""
# 学生类
class Student:
def __init__(self, number, name, age, gender, score):
self.number = number
self.name = name
self.age = age
self.gender = gender
self.score = score
def __str__(self):
return f"学号:[{self.number}],姓名:[{self.name}],年龄:[{self.age}],性别:[{self.gender}],成绩:[{self.score}]"
# 学生管理类
class StudentManager:
def __init__(self):
self.stu_list = []
def add_stu(self, student):
self.stu_list.append(student)
print(f'添加学生{student.name}成功')
def show_all_stu(self):
for stu in self.stu_list:
print(stu)
def main():
# 主流程
student_manager = StudentManager()
print('欢迎进入学生管理系统')
while True:
print('1: 添加学生')
print('2: 展示所有学生')
print('0: 退出系统')
choice = int(input("请输入操作编号: "))
if choice == 1:
number = input('请输入学生学号')
name = input('请输入学生姓名')
age = input('请输入学生年龄')
gender = input('请输入学生性别')
score = input('请输入学生分数')
student = Student(number, name, age, gender, score)
student_manager.add_stu(student)
elif choice == 2:
student_manager.show_all_stu()
elif choice == 0:
print(f"退出学生管理系统")
break
else:
print('您输入的指令是无效指令')
if __name__ == '__main__':
main()
|
|