Files
Cloud-book/Python/Python面向对象/类空间问题及类的关系.md
2025-08-27 17:10:05 +08:00

384 lines
9.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 类的空间问题
## 添加类和对象的属性
在 Python 中,**对象属性**(实例属性)和**类属性**的添加可以分别在类的内部(定义类时)和外部(运行时)进行。
### 对象属性
- **内部添加**:在类的 `__init__` 方法中定义的属性,属于对象(实例),每个实例有自己独立的属性。
- **外部添加**:可以在实例化对象后,动态地为某个对象添加属性。
### 类属性
- **内部添加**:在类的定义中直接定义的属性,属于类本身,所有实例共享。
- **外部添加**:可以在类定义后,动态地添加类属性。
```python
class MyClass:
# 1. 类属性:内部添加
class_attr = "I am a class attribute"
def __init__(self, name):
# 2. 对象属性:内部添加
self.name = name
def add_instance_attr(self, age):
# 3. 对象属性:内部添加(通过方法动态添加)
self.age = age
# 创建实例
obj1 = MyClass("Object 1")
# 访问类属性和对象属性
print(obj1.name) # 输出: Object 1
print(MyClass.class_attr) # 输出: I am a class attribute
# 4. 对象属性:外部添加
obj1.gender = "Male" # 动态给 obj1 添加 gender 属性
print(obj1.gender) # 输出: Male
# 5. 类属性:外部添加
MyClass.new_class_attr = "I am a new class attribute"
print(MyClass.new_class_attr) # 输出: I am a new class attribute
# 创建另一个实例,验证类属性的共享性
obj2 = MyClass("Object 2")
print(obj2.name) # 输出: Object 2
print(obj2.new_class_attr) # 输出: I am a new class attribute
# 6. 在内部通过方法添加对象属性
obj1.add_instance_attr(25)
print(obj1.age) # 输出: 25
# 注意obj2 没有 age 属性,因为 age 是通过 obj1 的方法动态添加的
# print(obj2.age) # 访问时会报错,因为 obj2 没有 age 属性
```
## 对象如何找到类的属性
**对象查找属性的顺序**
1. 先从对象空间找
2. 类空间找
3. 父类空间找
4. 基类空间
**类名查找属性的顺序**
1. 先从本类空间找
2. 父类空间找
3. 基类空间
上面的顺序都是单向不可逆,类名不可能找到对象的属性。
# 类之间关系
类与类中存在以下关系:
- 依赖关系
- 关联关系
- 组合关系
- 聚合关系
- 实现关系
- 继承关系(类的三大特性之一:继承)
## 依赖关系
例:将大象装进冰箱,需要两个类, ⼀个是⼤象类, ⼀个是冰箱类
```python
class Elphant:
def __init__(self, name):
self.name = name
def open(self):
'''
开门
'''
pass
def go(self):
# 大象进入冰箱
pass
def close(self):
'''
关门
'''
pass
class Refrigerator:
def open_door(self):
print('冰箱门打开了')
def close_door(self):
print('冰箱门关上了')
```
将大象类和冰箱类进行依赖
```python
class Elphant:
def __init__(self,name):
self.name = name
def open(self,obj):
print(self.name + '开门')
obj.open_door()
def go(self):
print(f'{self.name}进到冰箱里')
def close(self,obj):
print(self.name + '关门')
obj.close_door()
class Refrigerator:
def __init__(self,name):
self.name = name
def open_door(self):
print(self.name + '门被打开了')
def close_door(self):
print(self.name+'门被关上了')
elphant = Elphant('小飞象')
refrigerator = Refrigerator('格力冰箱')
elphant.open(refrigerator)
elphant.go()
elphant.close(refrigerator)
```
## 关联-聚合-组合关系
其实这三个在代码上写法是⼀样的,但是从含义上是不⼀样的:
1. 关联关系:两种事物必须是互相关联的,但是在某些特殊情况下是可以更改和更换的。
2. 聚合关系属于关联关系中的⼀种特例侧重点是xxx和xxx聚合成xxx各⾃有各⾃的声明周期比如电脑电脑⾥有 CPU, 硬盘, 内存等等。电脑挂了, CPU 还是好的,还是完整的个体。
3. 组合关系:属于关联关系中的⼀种特例,写法上差不多,组合关系比聚合还要紧密。比如⼈的⼤脑,⼼脏,各个器官,这些器官组合成⼀个⼈。这时,⼈如果挂了,其他的东⻄也跟着挂了。
**关联关系**
```python
class Boy:
def __init__(self,name, girlfriend = None):
self.name = name
self.girlfriend = girlfriend
def dinner(self):
if self.girlfriend:
print('%s%s 一起共进晚餐' % (self.name, self.girlfriend.name))
else:
print('连女朋友都没有,还有心情吃饭')
class Girl:
def __init__(self, name):
self.name = name
boy = Boy('张三')
boy.dinner()
girl = Girl('如花')
boy2 = Boy('李四', girl)
boy2.dinner()
```
注意, 此时 Boy 和 Girl 两个类之间就是关联关系,两个类的对象紧密联系着,其中⼀个没有了,另⼀个就孤单的不得了,关联关系,其实就是,我需要你,你也属于我。
学校和老师之间的关系
```python
class School:
def __init__(self,name,address):
self.name = name
self.address = address
class Teacher:
def __init__(self,name,school):
self.name = name
self.school = school
s1 = School('镇江校区','北京')
s2 = School('常州校区','上海')
s3 = School('南京校区','深圳')
t1 = Teacher('T1',s1)
t2 = Teacher('T2',s2)
t3 = Teacher('T3',s3)
print(t1.school.name)
print(t2.school.name)
print(t3.school.name)
```
但是学校也是依赖于老师的,所以老师学校应该互相依赖。
```python
class School:
def __init__(self,name,address):
self.name = name
self.address = address
self.teacher_list = []
def append_teacher(self,teacher):
self.teacher_list.append(teacher)
class Teacher:
def __init__(self,name,school):
self.name = name
self.school = school
s1 = School('北京校区','北京')
s2 = School('上海校区','上海')
s3 = School('深圳校区','深圳')
t1 = Teacher('T1',s1)
t2 = Teacher('T2',s2)
t3 = Teacher('T3',s3)
s1.append_teacher(t1.name)
s1.append_teacher(t2.name)
s1.append_teacher(t3.name)
print(s1.teacher_list)
```
**组合:将一个类的对象封装到另一个类的对象的属性中,就叫组合。**
例:设计一个游戏,让游戏里面的人物互殴,加上一个武器类,让人使用武器攻击。
```python
class Gamerole:
def __init__(self,name,ad,hp,wea=None):
self.name = name
self.ad = ad
self.hp = hp
self.wea = wea
def attack(self,p1):
p1.hp -= self.ad
print('%s攻击%s,%s掉了%s血,还剩%s'%(self.name,p1.name,p1.name,self.ad,p1.hp))
def equip_weapon(self,wea):
self.wea = wea
wea.ad += self.ad
wea.owner_name = self.name
class Weapon:
def __init__(self,name,ad,owner_name = None):
self.name = name
self.owner_name = owner_name
self.ad = ad
def weapon_attack(self,p2):
p2.hp = p2.hp - self.ad
print('%s利用%s攻击了%s%s还剩%s血'%(self.owner_name,self.name,p2.name,p2.name,p2.hp))
man = Gamerole('人',10,100)
dog = Gamerole('狗',50,100)
stick = Weapon('木棍',40)
man.equip_weapon(stick)
man.wea.weapon_attack(dog)
# 人利用木棍攻击了狗狗还剩50血
```
## 案例王者荣耀3V3
```python
import time
import random
class Gamerole:
def __init__(self,name,ad,hp):
self.name = name
self.ad = ad
self.hp = hp
def attack(self,p1):
p1.hp -= self.ad
print('%s攻击%s,%s掉了%s血,还剩%s'%(self.name,p1.name,p1.name,self.ad,p1.hp))
def equip_weapon(self,wea):
self.wea = wea
wea.ad += self.ad
wea.owner_name = self.name
class Weapon:
def __init__(self,name,ad,owner_name = None):
self.name = name
self.owner_name = owner_name
self.ad = ad
def weapon_attack(self,p2):
p2.hp = p2.hp - self.ad
print('%s利用%s攻击了%s%s还剩%s血'%(self.owner_name,self.name,p2.name,p2.name,p2.hp))
sunwukong = Gamerole("孙悟空", 20, 500)
caocao = Gamerole("曹操", 20, 100)
anqila = Gamerole("安琪拉", 50, 80)
zhaoyun = Gamerole("赵云", 30, 450)
guanyu = Gamerole("关羽", 80, 200)
diaochan = Gamerole("貂蝉", 60, 150)
blue_list = [sunwukong, caocao, anqila]
red_list = [zhaoyun, guanyu, diaochan]
if __name__ == '__main__':
print("游戏开始加载")
# 打印一个菜单
for i in range(0, 101, 2):
time.sleep(0.1)
char_num = i // 2
per_str = '\r%s%% : %s\n' % (i, '*' * char_num) \
if i == 100 else '\r%s%% : %s' % (i, '*' * char_num)
print(per_str, end='', flush=True)
info = input("游戏加载完毕,输入任意字符开始!")
# 输出东邪吸毒阵营里的任务角色
print("蓝方阵营".center(20, '*'))
for i in blue_list:
print(i.name.center(20))
print("红方阵营".center(20, '*'))
for i in red_list:
print(i.name.center(20))
while True:
# 判断游戏结束的条件是某一方全部阵亡
if len(blue_list) == 0:
print("红方阵营胜利!!!")
break
if len(red_list) == 0:
print("蓝方阵营胜利!")
break
# 游戏逻辑,每次随机选择一名角色出击
index1 = random.randint(0, len(blue_list) - 1)
index2 = random.randint(0, len(red_list) - 1)
# 开始攻击
time.sleep(1)
role1 = blue_list[index1]
time.sleep(1)
role2 = red_list[index2]
time.sleep(1)
role1.attack(role2)
role2.attack(role1)
# 判断是否有英雄阵亡
if role1.hp <= 0:
print("%s阵亡!" % role1.name)
blue_list.remove(role1)
if role2.hp <= 0:
print("%s阵亡!" % role2.name)
red_list.remove(role2)
```