Python面向对象(上)
python之面对对象
-
面向对象前夕
-
面向对象编程思想
-
面向对象重要理论
-
面向对象代码实操
-
对象的独有数据
-
对象的独有方法
-
面对对象前夕
接下来主要看一下如果不使用面对对象的方式如何定义一些对象和会出现的问题
- 代码演示:人汪大战
在这一步可以推导出来,如果有很多的人和很多汪,我们则需要写很多次重复代码
# 实现步骤1,先定义人和汪汪
person1 ={
'name': 'wesley',
'age': 18,
'gender': 'male',
'p_type': '猛男',
'attack_val': 8000,
'life_val': 999999
}
person2 = {
'name': 'kevin',
'age': 28,
'gender': 'female',
'p_type': '淑女',
'attack_val': 1,
'life_val': 100
}
dog1 = {
'name': '小黑',
'd_type': '泰迪',
'attack_val': 100,
'life_val': 8000
}
dog2 = {
'name': '小白',
'd_type': '恶霸',
'attack_val': 2,
'life_val': 80000
}
- 继续向下推导,将产生人和汪星人的字典封装为函数,并封装人和汪星人的攻击函数
1. 创建一个可以传入人数据的函数
def create_person(name, age, gender, p_type, attack_val, life_val):
person_dict = {
'name': name,
'age': age,
'gender': gender,
'p_type': p_type,
'attack_val': attack_val,
'life_val': life_val
}
return person_dict
2. 创建一个可以传入汪星人数据的函数
def create_dog(name, d_type, attack_val, life_val):
dog_dict = {
'name': name,
'd_type': d_type,
'attack_val': attack_val,
'life_val': life_val
}
return dog_dict
3. 创建具体的2个人
p1 = create_person('jason', 18, 'male', '猛男', 8000, 99999999)
p2 = create_person('kevin', 28, 'female', '淑女', 100, 800)
4. 创建具体的两个汪星人
d1 = create_dog('小黑', '恶霸', 800, 900000)
d2 = create_dog('小白', '泰迪', 100, 800000)
print(p1, p2)
print(d1, d2)
# 定义出人打狗的动作 狗咬人的动作(推导目标实现)
def person_attack(person_dict, dog_dict):
print(f"人:{person_dict.get('name')}准备揍狗:{dog_dict.get('name')}")
dog_dict['life_val'] -= person_dict.get('attack_val')
print(f"人揍了狗一拳 狗掉血:{person_dict.get('attack_val')} 狗剩余血量:{dog_dict.get('life_val')}")
def dog_attack(dog_dict, person_dict):
print(f"狗:{dog_dict.get('name')}准备咬人:{person_dict.get('name')}")
person_dict['life_val'] -= dog_dict.get('attack_val')
print(f"狗咬了人一口 人掉血:{dog_dict.get('attack_val')} 人剩余血量:{person_dict.get('life_val')}")
person_attack(p1, d1)
dog_attack(d2, p2)
人:jason准备揍狗:小黑
人揍了狗一拳 狗掉血:8000 狗剩余血量:892000
狗:小白准备咬人:kevin
狗咬了人一口 人掉血:100 人剩余血量:700
- 经过上面的推导大概可以得知如果不使用面对对象进行一些特定场景的变成可能会变的特别麻烦,并且,如果在最后调用阶段将人和汪星人的位置掉换一下呢?
# 这里就会发现,在使用代码时会产生一些不可预判的后果
"""推导步骤3:人和狗的攻击混乱"""
# person_attack(d1, p1)
# dog_attack(p1, d2)
人:小黑准备揍狗:jason
人揍了狗一拳 狗掉血:800 狗剩余血量:99999199
狗:jason准备咬人:小白
狗咬了人一口 人掉血:8000 人剩余血量:792000
- 数据与功能的绑定
上面遗留的问题如何解决呢,这里还是python代码为例,使用功能和数据绑定的编程思想解决这个问题,达到我们想要人只能调用人的方法,汪星人只能调用汪星人的方法
"""推导步骤4:如何实现只有人只能调用的人的攻击动作 狗只能调用狗的攻击动作>>>:数据与功能的绑定"""
def get_person(name, age, gender, p_type, attack_val, life_val):
# 产生人的函数(功能)
def person_attack(person_dict, dog_dict):
print(f"人:{person_dict.get('name')}准备揍狗:{dog_dict.get('name')}")
dog_dict['life_val'] -= person_dict.get('attack_val')
print(f"人揍了狗一拳 狗掉血:{person_dict.get('attack_val')} 狗剩余血量:{dog_dict.get('life_val')}")
# 表示人的信息(数据)
person_dict = {
'name': name,
'age': age,
'gender': gender,
'p_type': p_type,
'attack_val': attack_val,
'life_val': life_val,
'person_attack': person_attack
}
return person_dict
def get_dog(name, d_type, attack_val, life_val):
def dog_attack(dog_dict, person_dict):
print(f"狗:{dog_dict.get('name')}准备咬人:{person_dict.get('name')}")
person_dict['life_val'] -= dog_dict.get('attack_val')
print(f"狗咬了人一口 人掉血:{dog_dict.get('attack_val')} 人剩余血量:{person_dict.get('life_val')}")
dog_dict = {
'name': name,
'd_type': d_type,
'attack_val': attack_val,
'life_val': life_val,
'dog_attack': dog_attack
}
return dog_dict
person1 = get_person('jason', 18, 'male', '猛男', 8000, 99999999)
dog1 = get_dog('小黑', '恶霸', 800, 900000)
person1.get('person_attack')(person1, dog1)
"""
面向对象核心思想:数据与功能的绑定
1. 这里可以看出来主要使用函数嵌套的方式将人的属性和功能绑定到一起
2. 汪星人同样使用函数嵌套的方式将数据和功能绑定到一起
3. 这样就事项了人只能调用人的功能和数据,反之亦然,达到了数据与功能的绑定
"""
- 编程思想
编程思想主要有2类
- 面向过程
- 面向对象
-
面向过程
面向过程的主要思想
像工厂流水线生产产品一样,越往下越简单,也越完善,即流程解决问题
优点:编写比较简单,流程清晰,一不都有严谨的思路
缺点:后期扩展或迭代不易 -
面向对象
什么是对象,在python中,数据和功能共融一体的容器就是对象,比如所数据类型可以存放一些数据 ,并且还有自己的一些方法,那这就是对象
面向对象的主要思想
把自己想象成造物主,需要什么就创造类与对象,后续只需要调用这个类中的对象即可
优点: 易扩展
缺点: 对新手不太友好,比较抽象
问题: -
多个具有相同属性和功能的对象被称为类
-
同一个类中的对象都可以调用这个类中的公共功能和数据
-
python中必须先定义类后才能定义对象
-
创造出来的对象 对于程序员来说 后期无法控制,无法向面向过程那样预测
-
类与对象详解
对象: 数据和功能的结合体
类: 具有多个具有相同数据和功能的对象
程序中如果想要产生对象 必须要先定义出类 -
类与对象的创建
面对对象并不是一门新的技术,但是为了方便区分,python中使用了新的语法来使用面向对象
- 类的语法结构
class 类名:
“”“类功能说明注释”“”
对象公共数据
对象公共功能
1. class 是定义类的关键字
2. 类名和变量名的定义并无太大区别,但是为了方便区分,首字母需要大写
3. 数据: 就是变量名和数据的绑定
4. 功能: 其实就是函数
5. 类在定义阶段调用,会执行类体代码,但是里面的函数名和变量名属于局部名称空间的不会执行
- 类与对象的实际应用
在面向对象中 类和对象访问数据或者功能 可以统一采用句点符
- 查看名称空间
# 查看当前类下空间里所有的名称
print(Student.__dict__)
# 查看定义的choice_course
print(Student.choice_course)
# 查看定义的choice_course的第二种方法
print(Student.__dict__.get('choice_course'))
# 查看定义的school_name
print(Student.__dict__.get('school_name'))
# 查看定义的school_name 的第二种方法
print(Student.school_name)
- 对象的产生
需要注意 每一次调用即产生新的对象,谁调用主人公就是谁
下列的代码也可以看出来内存地址不相同
# 类的调用 :返回值即是对象的产生
ojb1 = Student()
ojb2 = Student()
ojb3 = Student()
print(ojb1, ojb2, ojb3)
<__main__.Student object at 0x102729fd0>
<__main__.Student object at 0x102729fa0>
<__main__.Student object at 0x102729f10>
# 查询对象,新产生的对象什么都没有
print(ojb1.__dict__.get('school_name'))
None
# 调用公共数据
print(ojb1.school_name)
北京大学
print(ojb2.school_name)
北京大学
print(ojb2.school_name)
北京大学
# 如果想更改数据代码如下,需要注意,由于是公共数据,更改之后其他对象也会更改
Student.school_name = '家里蹲'
print(ojb1.school_name)
家里蹲
- 对象独有数据
# 推导流程1 每个对象手动添加独有数据
ojb1.__dict__['name'] = 'wesley'
ojb1.__dict__['age'] = 18
print(ojb2.__dict__)
print(ojb1.name)
print(ojb1.age)
# 这里可以看到上面ojb1对象已经有了自己的属性,ojb2由于没有添加还是为空
# 推导流程2:将添加对象独有数据的代码封装成函数
def init(ojb, name, age):
ojb.__dict__['name'] = name
ojb.__dict__['age'] = age
# 产生2个新对象
stu1 = Student()
stu2 = Student()
# 调用函数并将空对象赋值传入数据
init(stu1, 'wesley', 18)
init(stu2, 'andy', 28)
# 打印对象
print(stu1.__dict__)
print(stu2.__dict__)
{'name': 'wesley', 'age': 18}
{'name': 'andy', 'age': 28}
"""
这里就实现了不同的对象不同的数据
"""
- 如何给学生这个对象设置独有功能? 代码如下
class Student():
# 定义公共数据
school_name = '北京大学'
# 专门给学生添加的独有的数据功能
def init(ojb, name, age):
ojb.__dict__['name'] = name
ojb.__dict__['age'] = age
# 定义公共功能
def choice_course(self):
print('学生选课系统')
# 产生新对象
stu1 = Student()
# 调用类中的独有功能并插入数据
Student.init(stu1, 'wesley', 18)
# 产生第二个新对象
stu2 = Student()
# 调用类中的独有功能并插入数据
Student.init(stu2, 'andy', 28)
# 打印
print(stu1.__dict__)
print(stu2.__dict__)
{'name': 'wesley', 'age': 18}
{'name': 'andy', 'age': 28}
"""
这一步我们将定义学生属性的函数放入到类中,实现了这个功能只能学生使用
"""
- init 方法变形为__init__方法
__init__在定义对象时自动触发
class Student:
# 定义公共数据
school_name = '北京大学'
# 专门给学生添加的独有的数据功能
def __init__(ojb, name, age):
ojb.__dict__['name'] = name
ojb.__dict__['age'] = age
# 定义公共功能
def choice_course(self):
print('学生选课系统')
# 推导步骤4:init方法变形
stu1 = Student('wesley', 18)
print(stu1.__dict__)
print(stu1.name)
print(stu1.school_name)
- 推导步骤5:变量名修改
class Student:
# 定义公共数据
school_name = '北京大学'
# 专门给学生添加的独有的数据功能
def __init__(ojb, name, age):
ojb.name = name # ojb.__dict__['name'] = name
ojb.age = age # ojb.__dict__['age'] = age
# 定义公共功能
def choice_course(self):
print('学生选课系统')
sut1 =Student('wesley', 18)
print(sut1.name)
- 独享功能
class Student:
# 定义公共数据
school_name = '北京大学'
# 专门给学生添加的独有的数据功能
def __init__(ojb, name, age):
ojb.name = name # ojb.__dict__['name'] = name
ojb.age = age # ojb.__dict__['age'] = age
# 定义公共功能
def choice_course(self):
print(f'学生{self.name}正在选课')
# 定义独享功能,修改 类中的choice_course功能
"""
该功能如果被定义在全局中,那就是谁的可以调用的
定义在类中,类对外是公开的,但是受到谁来调用谁就是主人功的影响,又提供了独享功能的概念
定义在类中的功能 默认就是绑定给对象使用的 谁来调谁就是主人公
"""
stu1 = Student('wesley', 18)
stu2 = Student('andy', 48)
# 对象中的数据值修改,当数据值存在时则更改,不存在时则新建
stu1.name = 'wesley123123'
stu2.balance = 6666
print(stu1.__dict__)
print(stu2.__dict__)
{'name': 'wesley123123', 'age': 18}
{'name': 'andy', 'age': 48, 'balance': 6666}