【一】人狗大战小游戏
【1】游戏前提分析
- 人可以打狗,狗掉血,狗可以咬人,人掉血
- 人的属性有名字、年龄、伤害、血量、类型
- 狗的属性有名字、年龄、伤害、血量、类型
【2】游戏实现
(1)定义人和狗的属性
# 【1】用字典定义,代码较冗余
dog1 = {
'name': '狗蛋',
'd_type': '中华田园犬',
'age': 2,
'attack': 30,
'blood': 150
}
dog2 = {
'name': '小七',
'd_type': '拉布拉多',
'age': 3,
'attack': 60,
'blood': 250
}
person1 = {
'name': '诺米',
'p_type': '青年人',
'age': 20,
'attack': 100,
'blood': 1000
}
# 【2】用函数封装
def get_dog(name, d_type, age, attack, blood):
dog_data_dict = {
'name': name,
'd_type': d_type,
'age': age,
'attack': attack,
'blood': blood
}
return dog_data_dict
def get_person(name, t_type, age, attack, blood):
person_data_dict = {
'name': name,
't_type': t_type,
'age': age,
'attack': attack,
'blood': blood
}
return person_data_dict
(2)人狗互咬功能实现
def get_dog(name, d_type, age, attack, blood):
dog_data_dict = {
'name': name,
'd_type': d_type,
'age': age,
'attack': attack,
'blood': blood
}
return dog_data_dict
def get_person(name, p_type, age, attack, blood):
person_data_dict = {
'name': name,
'p_type': p_type,
'age': age,
'attack': attack,
'blood': blood
}
return person_data_dict
def dog_attack_person(dog_dict, person_dict):
person_dict['blood'] -= dog_dict['attack']
print(
f"{dog_dict['name']} 咬了 {person_dict['name']} 掉了{dog_dict['attack']}滴血,人还剩{person_dict['blood']}滴血")
def person_attack_dog(dog_dict, person_dict):
dog_dict['blood'] -= person_dict['attack']
print(
f"{person_dict['name']} 咬了 {dog_dict['name']} 掉了{person_dict['attack']}滴血,狗还剩{dog_dict['blood']}滴血")
dog1 = get_dog(name='狗蛋', d_type='中华田园犬', age=2, attack=30, blood=150)
dog2 = get_dog(name='小七', d_type='拉布拉多', age=3, attack=60, blood=250)
person1 = get_person(name='诺米', p_type='青年人', age=20, attack=100, blood=1000)
dog_attack_person(dog_dict=dog1, person_dict=person1)
person_attack_dog(dog_dict=dog2, person_dict=person1)
# 狗蛋 咬了 诺米 掉了30滴血,人还剩970滴血
# 诺米 咬了 小七 掉了100滴血,狗还剩150滴血
(3)代码优化
# 狗的属性和狗的功能定义在一起
def get_dog(name, d_type, age, attack, blood):
def dog_attack_person(dog_dict, person_dict):
person_dict['blood'] -= dog_dict['attack']
print(
f"{dog_dict['name']} 咬了 {person_dict['name']} 掉了{dog_dict['attack']}滴血,人还剩{person_dict['blood']}滴血")
dog_data_dict = {
'name': name,
'd_type': d_type,
'age': age,
'attack': attack,
'blood': blood,
'dog_attack_person': dog_attack_person
}
return dog_data_dict
#人的属性和人的功能定义在一起
def get_person(name, p_type, age, attack, blood):
def person_attack_dog(dog_dict, person_dict):
dog_dict['blood'] -= person_dict['attack']
print(
f"{person_dict['name']} 咬了 {dog_dict['name']} 掉了{person_dict['attack']}滴血,狗还剩{dog_dict['blood']}滴血")
person_data_dict = {
'name': name,
'p_type': p_type,
'age': age,
'attack': attack,
'blood': blood,
'person_attack_dog': person_attack_dog
}
return person_data_dict
dog1 = get_dog(name='狗蛋', d_type='中华田园犬', age=2, attack=30, blood=150)
dog2 = get_dog(name='小七', d_type='拉布拉多', age=3, attack=60, blood=250)
person1 = get_person(name='诺米', p_type='青年人', age=20, attack=100, blood=1000)
person1['person_attack_dog'](dog_dict=dog1, person_dict=person1)
dog2['dog_attack_person'](dog_dict=dog2, person_dict=person1)
# 诺米 咬了 狗蛋 掉了100滴血,狗还剩50滴血
# 小七 咬了 诺米 掉了60滴血,人还剩940滴血
(4)小结
- 上面的操作其实就是将数据与功能进行绑定,不再是所有的数据都可以调用任意的功能
- 上述将数据与功能整合到一起的操作其实就是 面向对象编程的思想
【二】什么是面向过程和面向对象
【1】面向过程
- 面向过程关键在于过程两个字,过程最终就是将程序流程化
- 过程类似于流水线,分步骤来解决问题
- 优点是将复杂的问题流程化,就是先干什么再干什么,逻辑比较清晰
- 缺点是一套流水线或者流程就是用来解决一个问题,例如生产汽车
【2】面向对象
- 面向对象关键在于对象两个字,过程最终就是将程序整合起来,对象用来盛放数据和功能
(1)面向对象的例子
- 例如我们在学校,每一个角色都会对应其具有的责任和功能:
- 比如一个学生具有姓名、年龄、性别、所在班级等,能做的活动有读书、写作、跑步、打篮球等
- 比如一个老师也具有姓名、年龄、性别、所教学的班级等,能做的活动有教书、批改作业等
- 比如一个运行员也具有姓名、年龄、性别、所在班级等,能做的活动有参加训练、比赛等
- 当我们的角色和功能构建好以后,我们又需要创建几个学生、一些老师和运行员,让他们进行各项活动
- 比如一个学生可以上课、写作业、运动
- 比如一个老师可以教课、批改作业
- 比如一个运动员可以训练、参加比赛
(2)面向对象的优缺点
- 优点是将所有的功能和属性整合到一起,用什么拿什么,解决了程序的扩展性
- 缺点是编程的复杂度远高于面向过程,不了解面向对象而立即上手基于它设计程序,极容易出现过度设计的问题
【3】类与对象
-
类即类别、种类,是面向对象设计最重要的概念,对象是特征与技能的结合体,而类则是一系列对象相似的特征与技能的结合体
-
类的好处就是我们可以把同一类对象相同的数据与功能存放到类里,而无需每个对象都重复存一份,这样每个对象里只需存自己独有的数据即可,极大地节省了空间
-
所以说,对象其实就是用来存放数据与功能的容器,类则是用来存放多个对象相同的数据与功能的容器
(1)现实中
- 在现实世界中:先有对象,再有类
- 世界上肯定是先出现各种各样的实际存在的物体,然后随着人类文明的发展,人类站在不同的角度总结出了不同的种类,如人类、动物类、植物类等概念
- 也就说,对象是具体的存在,而类仅仅只是一个概念,并不真实存在
(2)程序中
- 在程序中:务必保证先定义类,后产生对象
- 这与函数的使用是类似的,先定义函数,后调用函数,类也是一样的,在程序中需要先定义类,后调用类
- 不一样的是,调用函数会执行函数体代码返回的是函数体执行的结果,而调用类会产生对象,返回的是对象
【三】面向对象编程
【1】类的定义
- class关键字声明一个类
- 在程序中定义出类,然后调用类产生对象
# 在程序中,我们要先声明一个类,在类中创建一个个对象
# 在程序中特征用变量标识,技能用函数标识
# 因而类中最常见的无非是:变量和函数的定义
# 方式一:
class Student(object)
# 方式二:
class Student()
# 方式三:
class Student
# 类名后面的 () 参数不写默认就是 object
class Student(object):
school = "清华大学"
def read(self):
# self : 表示对象自己本身,
print(f"我的学校是{self.school}")
# 通过类实例化得到一个对象
student = Student()
print(student) # <__main__.Student object at 0x000001F2074B1340>
# 想用类里面的属性和方法
print(student.school_name)
print(student.read()) # None
【2】类的使用
(1)查看类的名称空间
- 可以打印
Student.__dict__
来查看类的名称空间
class Student(object):
school = '北京大学'
def play(self):
print(f"{self.school}的学生正在玩游戏!")
print(Student.__dict__)
# {'__module__': '__main__', 'school': '北京大学', 'play': <function Student.play at 0x000002BBDD83A7A0>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None}
(2)对象的实例化
- 调用类的过程称为将类实例化,拿到的返回值就是程序中的对象,或称为一个实例
class Student(object):
school = '北京大学'
def play(self):
print(f"{self.school}的学生正在玩游戏!")
# 每实例化一次Student类就得到一个新的对象
student1 = Student()
student2 = Student()
print(id(student1)) # 1690943387872
print(id(student2)) # 1690943135248
(3)修改对象的属性
[1] 通过类的名称空间修改属性
class Student(object):
school = '北京大学'
def play(self):
print(f"{self.school}的学生正在玩游戏!")
obj1 = Student()
print(obj1.__dict__) # {}
obj1.__dict__['name'] = 'ligo'
obj1.__dict__['age'] = 18
obj1.__dict__['sex'] = '男'
print(obj1.__dict__) # {'name': 'ligo', 'age': 18, 'sex': '男'}
print(obj1.name) # ligo
[2] 封装成函数
class Student(object):
school = '北京大学'
def play(self):
print(f"{self.school}的学生正在玩游戏!")
def set_info(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
obj1 = Student()
set_info(obj1, name='ligo', age=18, sex='男')
print(obj1.name) # ligo
[3]封装成类的方法
class Student(object):
school = '北京大学'
def set_info(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
def play(self):
print(f"{self.school}的学生{self.name}正在玩游戏!")
obj1 = Student()
Student.set_info(obj1, name='ligo', age=18, sex='男')
print(obj1.name) # ligo
obj1.play() # 北京大学的学生ligo正在玩游戏!
[4]类的魔法方法 __init__
class Student(object):
school = '北京大学'
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
def choose(self, classroom):
self.classroom = classroom
def student_info(self):
print(f'''
-----学生信息如下----
姓名:{self.name}
年龄:{self.age}
性别:{self.sex}
班级:{self.classroom}
''')
def play(self):
print(f"{self.school}的学生{self.name}正在玩游戏!")
student = Student(name='ligo', age=18, sex='男')
print(student.__dict__) # {'name': 'ligo', 'age': 18, 'sex': '男'}
print(student.name) # ligo
student.classroom = '软件212'
print(student.classroom) # 软件212
# 修改年龄
student.age = 20
student.student_info()
# -----学生信息如下----
# 姓名:ligo
# 年龄:20
# 性别:男
# 班级:软件212
【3】属性访问
- 类有两种属性:数据属性和函数属性,可以通过
__dict__
访问属性的值 - 类属性
class Student(object):
school = '北京大学'
def __init__(self, name, age, sex, classroom):
self.name = name
self.age = age
self.sex = sex
self.classroom = classroom
def student_info(self):
print(f'''
-----学生信息如下----
姓名:{self.name}
年龄:{self.age}
性别:{self.sex}
班级:{self.classroom}
''')
def play(self):
print(f"{self.school}的学生{self.name}正在玩游戏!")
print(Student.__dict__)
# {'__module__': '__main__', 'school': '北京大学', '__init__': <function Student.__init__ at 0x000002146A2AA7A0>, 'student_info': <function Student.student_info at 0x000002146A578B80>, 'play': <function Student.play at 0x000002146A5784C0>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None}
print(Student.school) # 北京大学
print(Student.play)
# <function Student.play at 0x000002146A5784C0>
- 对象属性
class Student(object):
school = '北京大学'
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
def choose(self, classroom):
self.classroom = classroom
def student_info(self):
print(f'''
-----学生信息如下----
姓名:{self.name}
年龄:{self.age}
性别:{self.sex}
班级:{self.classroom}
''')
def play(self):
print(f"{self.school}的学生{self.name}正在玩游戏!")
student = Student(name='ligo', age=18, sex='男')
print(student.__dict__) # {'name': 'ligo', 'age': 18, 'sex': '男'}
print(student.name) # ligo
student.classroom = '软件212'
print(student.classroom) # 软件212
# 修改年龄
student.age = 20
student.student_info()
# -----学生信息如下----
# 姓名:ligo
# 年龄:20
# 性别:男
# 班级:软件212
【4】属性查找
- 对象的名称空间里只存放着对象独有的属性,而对象们相似的属性是存放于类中的。
- 对象在访问属性时,会优先从对象本身的
__dict__
中查找,未找到,则去类的__dict__
中查找
# 查找顺序
# 首先在自己的对象中查找
# 自己找不到就去父类里面找
# 如果父类里面找不到,就去基类里面找
# 如果基类里面也没有,就去 object 里面找
# 如果还是找不到则报错
class Student(object):
school = '北京大学'
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
def choose(self, classroom):
self.classroom = classroom
def student_info(self):
print(f'''
-----学生信息如下----
姓名:{self.name}
年龄:{self.age}
性别:{self.sex}
班级:{self.classroom}
''')
def play(self):
print(f"{self.school}的学生{self.name}正在玩游戏!")
student = Student(name='ligo', age=18, sex='男')
print(student.__dict__) # {'name': 'ligo', 'age': 18, 'sex': '男'}
print(student.name) # ligo
student.classroom = '软件212'
print(student.classroom) # 软件212
# 修改年龄
student.age = 20
student.student_info()
# -----学生信息如下----
# 姓名:ligo
# 年龄:20
# 性别:男
# 班级:软件212
student.play()
# 北京大学的学生ligo正在玩游戏!
#类中定义的变量是类的数据属性,是共享给所有对象用的,指向相同的内存地址
print(id(student.school)) # 1948832565264
print(id(Student.school)) # 1948832565264
【5】list方法回顾
num_list1 = [1, 2, 3, 4, 5]
num_list2 = [6, 7, 8, 9, 10]
num_list1.append(3)
num_list2.append(1)
# 只会给指定的对象添加元素,不会给其他对象添加
print(num_list1) # [1, 2, 3, 4, 5, 3]
print(num_list2) # [6, 7, 8, 9, 10, 1]
class NumList(object):
def __init__(self, num):
self.num = num
num1 = NumList(num=1)
print(id(num1)) # 2629054930544
# 修改num的值不会改变num的id
num1.num = 2
print(id(num1)) # 2629054930544
【四】类的特殊属性
类名.__name__
:类的名字(字符串)类名.__doc__
:类的文档字符串类名.__base__
:类的第一个父类类名.__bases__
:类所有父类构成的元组类名.__dict__
:类的字典属性类名.__module__
:类定义所在的模块类名.__class__
:实例对应的类(仅新式类中)
class Animal(object):
...
class People(Animal):
'''这是一个人类的注释'''
def __init__(self, name, age):
self.name = name
self.age = age
def run(self):
print(f"{self.name} can run!")
print(People.__name__)
# People
print(People.__doc__)
# 这是一个人类的注释
print(People.__base__)
# <class '__main__.Animal'>
print(People.__bases__)
# (<class '__main__.Animal'>,)
print(People.__dict__)
# {'__module__': '__main__', '__doc__': '这是一个人类的注释', '__init__': <function People.__init__ at 0x00000131B53C35B0>, 'run': <function People.run at 0x00000131B5631990>}
print(People.__module__)
# __main__
print(People.__class__)
# <class 'type'>
标签:__,进阶,Python,self,dict,面向对象编程,print,age,name
From: https://www.cnblogs.com/ligo6/p/18183504