19. 面向对象编程
1. 面向对象编程引入
1.0 分析属性
做一款人狗大战的小游戏
人的属性:
人的姓名
人的性别
人的年龄
人的生命值
人的攻击力
狗的属性:
狗的名字
狗的年龄
狗的生命值
狗的攻击力
狗的品种
1.1 方式一:面条版 使用字典定义属性
# 定义人和狗的参数
dog1 = {
'name': '小黑',
'age': 3,
'hp': 100,
'power': 30,
'breed': '土'
}
dog2 = {
'name': '旺财',
'age': 10,
'hp': 100,
'power': 20,
'breed': '洋'
}
person1 = {
'name': 'kevin',
'gender': 'male',
'age': 32,
'hp': 1000,
'power': 40,
}
person2 = {
'name': 'leo',
'gender': 'male',
'age': 37,
'hp': 1000,
'power': 30
}
print(f"{person2['name']}这个人打了狗{dog1['name']},狗掉了{person2['power']}hp,还剩{dog1['hp'] - person2['power']}hp")
# leo这个人打了狗小黑,狗掉了30hp,还剩70hp
1.2 方式二:函数版 封装成函数,减少代码冗余
解耦合:将某部分拆成小的部分,又将小的部分合并在一起
将人的属性、狗的属性,人打狗、狗咬人都定义函数
def init_person(name, gender, age, hp, power):
info1 = {"name": name, "gender": gender, "age": age, "hp": hp, "power": power}
return info1
def init_dog(name, age, hp, power, breed):
info2 = {"name": name, "age": age, "hp": hp, "power": power, "breed": breed}
return info2
def dog_attack_person(dog, person):
"""
狗咬人函数
:param dog:
:param person:
:return:
"""
person["hp"] -= dog["power"] # 人剩余的hp等于人的hp减狗的攻击力
print(f"狗{dog['name']}咬了人{person['name']},人{person['name']}掉了{dog['power']}hp,还剩{person['hp']}hp")
def person_attack_dog(person, dog):
"""
人打狗函数
:param person:
:param dog:
:return:
"""
dog["hp"] -= person["power"]
print(
f"{person['name']}这个人打了狗{dog['name']},狗掉了{person['power']}hp,还剩{dog['hp']}hp")
person1 = init_person(name='kevin', gender='male', age=32, hp=1000, power=40)
person2 = init_person(name='leo', gender='male', age=37, hp=1000, power=30)
dog1 = init_dog(name='小黑', age=3, hp=1000, power=30, breed='土')
dog2 = init_dog(name='旺财', age=4, hp=1000, power=20, breed='洋')
# 小黑咬了kevin
dog_attack_person(dog=dog1, person=person1) # 狗小黑咬了人kevin,人kevin掉了30hp,还剩970hp
# 小黑咬了leo
dog_attack_person(dog=dog1, person=person2) # 狗小黑咬了人leo,人leo掉了30hp,还剩970hp
1.3 方式三:聚合版
只有人能调用人打狗函数,将人的属性、人打狗两个函数定义成一个函数
只有狗能调用狗咬人函数,将狗的属性,狗咬人两个函数定义成一个函数
将动作函数放在字典中
def init_person(name, gender, age, hp, power):
def person_attack_dog(person, dog):
dog["hp"] -= person["power"]
print(f"{person['name']}这个人打了狗{dog['name']},狗掉了{person['power']}hp,还剩{dog['hp']}hp")
info1 = {"name": name, "gender": gender, "age": age,
"hp": hp, "power": power,
'person_attack_dog': person_attack_dog}
return info1
def init_dog(name, age, hp, power, breed):
def dog_attack_person(dog, person):
person["hp"] -= dog["power"] # 人剩余的hp等于人的hp减狗的攻击力
print(f"狗{dog['name']}咬了人{person['name']},人{person['name']}掉了{dog['power']}hp,还剩{person['hp']}hp")
info2 = {"name": name, "age": age, "hp": hp,
"power": power, "breed": breed,
'dog_attack_person': dog_attack_person}
return info2
person1 = init_person(name='kevin', gender='male', age=32, hp=1000, power=40)
person2 = init_person(name='leo', gender='male', age=37, hp=1000, power=30)
dog1 = init_dog(name='小黑', age=3, hp=1000, power=30, breed='土')
dog2 = init_dog(name='旺财', age=4, hp=1000, power=20, breed='洋')
# 小黑咬了leo
dog1['dog_attack_person'](dog1, person2) # 狗小黑咬了人leo,人leo掉了30hp,还剩970hp
# kevin打了小黑
person1['person_attack_dog'](person1, dog1) # kevin这个人打了狗小黑,狗掉了40hp,还剩960hp
1.4 总结
以上操作就是将数据与功能进行绑定
将数据与功能整合到一起的思想就是面向对象编程的思想
2. 面向过程与面向对象的概念
2.1 面向过程
过程的含义是将程序流程化,过程是流水线,按步骤解决问题
2.2 面向对象
面向对象的核心在于对象两个字,对象的含义是一个整体
对象就是容器,用来盛放数据和功能
面向对象的优点:解决了程序的扩展性,对某一个对象单独修改,会立刻反映到整个体系中
3. 类与对象
3.1 类的概念
类就是类别、种类的意思,是面向对象分析和设计的基石
类和对象哪个先产生?
对于程序来说先有类才能有对象,对于人类的逻辑来说先有对象才能抽象出某一个类
3.2 定义类的语法
class 类名(参数):
代码体
# 类名建议使用大驼峰体
# 参数的括号可以不写
# 类中可以有任意python代码,这些代码在类定义阶段便会执行
# 因为会产生新的名称空间,用来存放类的变量名与函数名,可以通过类名.__dict__查看
# 点是访问属性的语法,类中定义的名字,都是类的属性
类的定义与使用举例
class Student:
school = 'California' # 定义学生类的数据
grade = 3
def reading(self): # 定义学生类的功能
print('读书')
def rest(self):
print('休息')
# 1.定义类之后,如何产生对象
stu1 = Student() # <__main__.Student object at 0x000001FEAD21A110>
print(stu1)
# 2.查看对象的内置方法和属性
# print(dir(stu1))
# ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'exercise', 'grade', 'reading', 'school']
# 3.查看对象的名称空间
print(stu1.__dict__) # {}
stu1.__dict__.update({'school': 'MIT'})
print(stu1.__dict__) # {'school': 'MIT'}
# 4.调用对象中的属性
print(stu1.school) # MIT
print(stu1.grade) # 3
stu1.reading() # 读书
stu1.rest() # 休息
3.3 类的实例化---产生对象
调用类的过程称为将类实例化
拿到的返回值就是程序中的对象,或称为一个实例
3.4 修改对象的属性
(1)通过类的名称空间修改对象的属性
举例:初始化对象的独有属性
class Student:
name = ''
gender = ''
grade = None
school = 'California' # 定义学生类的数据---数据属性
def reading(self): # 定义学生类的功能---功能属性
print('读书')
def rest(self):
print('休息')
stu1 = Student()
print(stu1.__dict__) # {}
stu1.__dict__.update({'name': 'clinton', 'gender': 'male', 'grade':1})
print(stu1.__dict__) # {'name': 'clinton', 'gender': 'male', 'grade': 1}
print(stu1.school) # California
print(stu1.grade) # 1
(2)通过函数来操作类的名称空间修改对象的属性---封装成函数
方法一:
将生成的对象和属性值传递给函数,由函数来修改属性
从类中得到的是一个空的对象
class Student:
name = ''
gender = ''
grade = None
school = 'California' # 定义学生类的数据---数据属性
def reading(self): # 定义学生类的功能---功能属性
print('读书')
def rest(self):
print('休息')
def revise_obj(obj, name, gender, grade):
obj.__dict__.update({'name': name, 'gender': gender, 'grade': grade})
stu1 = Student() # 生成对象
revise_obj(stu1, name='clinton', gender='male', grade=1) # 将对象和属性传递给函数进行修改属性,返回值可以是空的
stu2 = Student()
revise_obj(stu2, name='robert', gender='male', grade=2)
方法二:
将类传递给函数,在函数中先产生空对象,再在函数中修改属性值,将对象返回给调用函数的变量名
从类中得到的是一个具有自身属性的对象
class Student:
name = ''
gender = ''
grade = None
school = 'California' # 定义学生类的数据---数据属性
def reading(self): # 定义学生类的功能---功能属性
print('读书')
def rest(self):
print('休息')
def create_obj(cls, name, gender, grade):
stu_obj = cls()
stu_obj.__dict__.update({'name': name, 'gender': gender, 'grade': grade})
return stu_obj
stu1 = create_obj(cls=Student, name='messi', gender='male', grade=1) # 将类传递给函数,由类加括号产生对象然后修改属性值
print(stu1.__dict__) # {'name': 'messi', 'gender': 'male', 'grade': 1}
(3)封装到类中的方法
方法一:将以上方法一修改对象属性的函数,封装成类中的一个方法
由类产生一个空的对象,调用类中的方法给对象修改属性
class Student:
name = ''
gender = ''
grade = None
school = 'California' # 定义学生类的数据---数据属性
def reading(self): # 定义学生类的功能---功能属性
print('读书')
def rest(self):
print('休息')
def revise_obj(self, name, gender, grade): # 将修改属性函数放在类中
print(id(self)) # 1601271512992
self.__dict__.update({'name': name, 'gender': gender, 'grade': grade})
stu1 = Student() # 生成对象
stu1.revise_obj(name='clinton', gender='male', grade=1)
print(stu1.__dict__) # {'name': 'clinton', 'gender': 'male', 'grade': 1}
print(id(stu1)) # 1601271512992
# 对象stu1与类中self的内存地址一致,因此self就是当前对象
方法二:
方法一的基础上在修改属性函数里将self即对象返回出去,调用该函数时,就会得到一个对象
方法一与方法二的区别是修改属性函数有无返回值,调用函数能否直接得到对象
class Student:
name = ''
gender = ''
grade = None
school = 'California' # 定义学生类的数据---数据属性
def reading(self): # 定义学生类的功能---功能属性
print('读书')
def rest(self):
print('休息')
def revise_obj(self, name, gender, grade):
self.__dict__.update({'name': name, 'gender': gender, 'grade': grade})
return self # 有返回值,并且返回值是带有自身属性的对象
stu1 = Student().revise_obj(name='monica', gender='female', grade=2)
print(stu1.__dict__) # {'name': 'monica', 'gender': 'female', 'grade': 2}
(4)总结
给对象修改属性有两大方法
第一种是按方法一通过类的名称空间赋值的方法修改属性
第二种是将修改属性的函数封装在类里面,在给类传值生成对象时,对象就拿到这些值有了自身的属性
3.5 类的init方法---构造对象方法
方法一:
与上面将修对象属性的函数封装到类中相比,区别是修改属性函数名换成了_ _ init _ _,并且无法从_ _ init _ _返回值
class Student:
# 不再需要将个人的变量名放在这里
school = 'California' # 定义学生类的数据---数据属
def reading(self): # 定义学生类的功能---功能属性
print('读书')
def rest(self):
print('休息')
def __init__(self, name, gender, grade):
self.__dict__.update({'name': name, 'gender': gender, 'grade': grade})
# 无法从__init__返回值
stu1 = Student(name='avril', gender='female', grade=3)
print(stu1.__dict__) # {'name': 'avril', 'gender': 'female', 'grade': 3}
# 对象.属性名取值 或对象.属性名=属性值的替换值
stu1.grade = 4
print(stu1.__dict__) # {'name': 'avril', 'gender': 'female', 'grade': 4}
方法二:
与方法一相比,区别是方法一修改属性是在_ _init_ _中,给对象的属性字典更新一个自身信息的字典,实现修改对象属性
而方法二是通过 对象.属性名 赋值的方法,实现修改对象属性
class Student:
# 不再需要将个人的变量名放在这里
school = 'California' # 定义学生类的数据---数据属性
def reading(self): # 定义学生类的功能---功能属性
print('读书')
def rest(self):
print('休息')
def __init__(self, name, gender, grade):
self.name = name
self.gender = gender
self.grade = grade
stu1 = Student(name='lavigne', gender='female', grade=2)
print(stu1.__dict__) # {'name': 'lavigne', 'gender': 'female', 'grade': 2}
3.6 类属性与对象属性
class Student:
school = 'California University' # 数据属性
# 函数属性
def __init__(self, name, gender, grade):
self.name = name
self.gender = gender
self.grade = grade
def lab(self):
print(f'{self.name}正在做实验')
# 给类传入参数,实例化类得到一个对象
stu1 = Student(name='lavigne', gender='female', grade=2)
# 查看对象的属性字典
print(stu1.__dict__) # {'name': 'lavigne', 'gender': 'female', 'grade': 2}
# 查看类的属性字典
print(Student.__dict__)
# {'__module__': '__main__', 'school': 'California University', '__init__': <function Student.__init__ at 0x000001F2208F3370>,
'lab': <function Student.lab at 0x000001F220B61750>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__':
<attribute '__weakref__' of 'Student' objects>, '__doc__': None}
3.7 类的其它方法
print(dir(Person)) # 查看类的所有属性和方法 print(Person.__doc__) # 查看类的注释 print(Person.__name__) # 查看类的名字 print(Person.__module__) # 查看类所在的模块名字 print(Person.__bases__) # 查看当前类进程的所有父类 print(Person.__base__) # 查看当前类继承的第一个父类 print(Person.__class__) # 查看当前对应的类type产生了每一个基类

浙公网安备 33010602011771号