Ⅰ 面向对象思想前戏
【一】人狗大战小游戏
【1】人狗大战小游戏描述
- 我们现在需要设计一个人狗大战的小游戏
- 人可以打狗,狗掉血,狗可以咬人,人掉血
【2】人狗大战小游戏实现
(1)分析
- 人的属性
- 人的名字
- 人的类型
- 人的年龄
- 人的攻击力
- 人的生命值
- 狗的属性
- 狗的名字
- 狗的类型
- 狗的攻击值
- 狗的生命值
(2)定义人和狗的参数
- 方式一:使用字典定义属性一个个描述
dog1 = {
'name': '小黑',
'type': '田园犬',
'attack_val': 30,
'life_val': 200
}
dog2 = {
'name': '小白',
'type': '恶霸犬',
'attack_val': 180,
'life_val': 500
}
person1 = {
'name': '小龙',
'type': '猛男',
'attack_val': 10,
'life_val': 1000
}
- 方式二:封装成函数,减少代码冗余
# 定义专门用来描述人和狗的函数(最好单独编写)
# 将人类的属性用函数声明
def get_person(name, gender, age, t_type, attack_val, life_val):
'''
param name: 人的名字
param gender: 人的性别
param age: 人的年龄
param t_type: 人的类型
param attack_val: 攻击值
param life_val: 生命值
'''
data_dict = {
'name': name,
'gender': gender,
'age': age,
't_type': t_type,
'attack_val': attack_val,
'life_val': life_val
}
return data_dict
# 将狗的属性用函数声明
def get_dog(name, t_type, attack_val, life_val):
'''
param name: 狗的名字
param t_type: 狗的类型
param attack_val: 攻击值
param life_val: 生命值
'''
data_dict = {
'name': name,
't_type': t_type,
'attack_val': attack_val,
'life_val': life_val
}
return data_dict
(3)大战功能的实现
# 定义专门用来描述人和狗的函数(最好单独编写)
def get_person(name, gender, age, t_type, attack_val, life_val):
data_dict = {
'name': name,
'gender': gender,
'age': age,
't_type': t_type,
'attack_val': attack_val,
'life_val': life_val
}
return data_dict
def get_dog(name, t_type, attack_val, life_val):
data_dict = {
'name': name,
't_type': t_type,
'attack_val': attack_val,
'life_val': life_val
}
return data_dict
p1 = get_person('dream', 'male', 18, '猛男', 800, 1000)
p2 = get_person('hope', 'female', 28, '淑女', 5, 100)
dog1 = get_dog('小黑', '松狮犬', 300, 500)
dog2 = get_dog('小白', '泰迪犬', 50, 200)
# 定义一个函数用来描述人和狗的攻击行为
def dog_attack(dog_obj, person_obj):
"""
:param dog_obj: 接收一条狗
:param person_obj: 接收一个人
"""
# 使用最简答的掉血逻辑 血量减去对方攻击力
print('当前人的血量是:%s' % person_obj.get('life_val'))
person_obj['life_val'] -= dog_obj.get('attack_val')
print("""狗:%s 咬了人:%s 一口 人掉血:%s 剩余血量:%s""" % (
dog_obj.get('name'), person_obj.get('name'), dog_obj.get('attack_val'), person_obj['life_val']))
def person_attack(person_obj, dog_obj):
"""
:param person_obj: 接收一个人
:param dog_obj: 接收一条狗
"""
print('当前狗的血量是:%s' % dog_obj.get('life_val'))
dog_obj['life_val'] -= person_obj.get('attack_val')
print("""人:%s 锤了狗:%s 一下 狗掉血:%s 剩余血量:%s""" % (
person_obj.get('name'), dog_obj.get('name'), person_obj.get('attack_val'), dog_obj['life_val']))
# 狗咬人
dog_attack(dog2, p1)
print(p1) # 狗:小白 咬了人:silence 一口 人掉血:50 剩余血量:950
# 人锤狗
person_attack(p2, dog1)
print(dog1) # 人:happy 锤了狗:小黑 一下 狗掉血:5 剩余血量:495
'''人调用了狗的攻击动作'''
dog_attack(p1, dog1)
'''狗调用了人的攻击工作'''
person_attack(dog2, p2)
【3】人狗大战小游戏优化
"""如何做到只有人可以调用人的攻击动作 狗调用狗的攻击动作"""
# 其实就是想让人的数据跟人的功能绑定 狗的数据跟狗的功能绑定
def get_person(name, gender, age, t_type, attack_val, life_val):
# 将人的攻击动作放在产生人的函数内
def person_attack(person_obj, dog_obj):
"""
:param person_obj: 接收一个人
:param dog_obj: 接收一条狗
"""
print('当前狗的血量是:%s' % dog_obj.get('life_val'))
dog_obj['life_val'] -= person_obj.get('attack_val')
print("""人:%s 锤了狗:%s 一下 狗掉血:%s 剩余血量:%s""" % (
person_obj.get('name'), dog_obj.get('name'), person_obj.get('attack_val'), dog_obj['life_val']))
data_dict = {
'name': name,
'gender': gender,
'age': age,
't_type': t_type,
'attack_val': attack_val,
'life_val': life_val,
'person_attack': person_attack
}
return data_dict
def get_dog(name, t_type, attack_val, life_val):
def dog_attack(dog_obj, person_obj):
"""
:param dog_obj: 接收一条狗
:param person_obj: 接收一个人
"""
# 使用最简答的掉血逻辑 血量减去对方攻击力
print('当前人的血量是:%s' % person_obj.get('life_val'))
person_obj['life_val'] -= dog_obj.get('attack_val')
print("""狗:%s 咬了人:%s 一口 人掉血:%s 剩余血量:%s""" % (
dog_obj.get('name'), person_obj.get('name'), dog_obj.get('attack_val'), person_obj['life_val']))
data_dict = {
'name': name,
't_type': t_type,
'attack_val': attack_val,
'life_val': life_val,
'dog_attack': dog_attack
}
return data_dict
p1 = get_person('silence', 'male', 18, '猛男', 800, 1000)
p2 = get_person('happy', 'female', 28, '淑女', 10, 100)
dog1 = get_dog('小黑', '松狮犬', 300, 500)
dog2 = get_dog('小白', '泰迪犬', 50, 200)
p1['person_attack'](p1, dog1)
dog1['dog_attack'](dog1, p2)
- 上述操作其实就是将数据与功能进行绑定
- 不再是所有的数据都可以调用任意的功能
上述将数据与功能整合到一起的操作其实就是 面向对象编程的思想
Ⅱ 面向过程和面向对象
【一】什么是面向对象和面向过程
【1】面向过程
关键就在于过程 意思就是将程序流程化
过程就是流水线,用到哪个功能就去写哪个功能 分步骤解决问题
好处在于逻辑清晰 先作什么后做什么 ...
缺点在于复杂的问体也流程化,生产一辆汽车
【2】面向对象
关键在于对象 , 将程序进行整合,整合成一个整体
对象其实就是一个“容器” 将数据与功能整合到一起
优点:能将所有的属性整合到一起,用什么拿什么
【二】面向对象例子
# 学校里面的学生和角色信息来说
# 学生 : 名字,年龄,性别,所在班级、能进行的运动(读书、写字、听音乐)
# 老师 : 名字,年龄,性别,班级可能不固定、能进行的运动(教书、批改作业、打乒乓球)
# 运动员:名字,年龄,性别,所在班级、能进行的运动(训练、打篮球)
# 将对象所有的属性封装到一起
def student(name, age, gender, class_id):
def read():
print(f"学生 {name} 可以读书")
return {
'name': name,
"age": age,
"gender": gender,
"class_id": class_id,
"read": read
}
student_one = student(name='silence',age=18,gender='male',class_id=1)
student_one['read']()
# 上面的定义不符合规范,而且不方便
# 将所有的属性封装到一起给学生这个人
Ⅲ 类和对象概念
对象:数据与功能的结合体
类:即类别,种类 相当于诸多对象共有的特征
'''
现实生活中
人 对象
一群人 人类
类只能描述出公共特征!! 不同的特征应该由对象自己描述
'''
ps:类其实也算对象>>>:一切皆对象
【一】类和对象的创建
对于程序来说:先有类才能有对象
先有学校才能有学生
对于现实来说:先有对象才能有类
先有学生才能有学校
【二】类的初识
# 学校里面的学生和角色信息来说
# 学校有名字
# 学生 : 名字,年龄,性别,所在班级、能进行的运动(读书、写字、听音乐)
# 老师 : 名字,年龄,性别,班级可能不固定、能进行的运动(教书、批改作业、打乒乓球)
# 运动员:名字,年龄,性别,所在班级、能进行的运动(训练、打篮球)
# 学校:清华
# 学生 : silence 18 male 1 read write listen
# 一类学生
# 老师 : happy 28 male 1 teach check pingpang
# 运动员 :natas 20 female 1 sport basketball
# 关键字class 声明一个类
# 在程序中特征用变量标识,技能用函数标识
# 因而在类中 函数名和变量名
# 数据属性和函数属性
# 【二】定义类
# 【1】类名 建议是驼峰体
# Student
class student(): # <class 'type'>
...
class Student(): # <class 'type'>
...
print(type(student))
print(type(Student))
# 方式一:class Student(object)
# 方式二:class Student()
# 方式三:class Student
class Student(object):
# 类名后面的 () 参数不写默认就是 object
# object :父类
# 直接定义数据属性
school_name = "清华"
# 函数属性
def read(self):
# self : 表示对象自己本身,
print(f"当前学校是 {self.school_name}")
def add():
...
res = add()
print(res)
# 函数() 得到的是函数的返回值
# 如果你自己写了那就是你写的,如果没写就是 None
# 类创建好后如何调用?#
# 通过类实例化得到一个对象
student = Student()
print(student) # <__main__.Student object at 0x000001F2074B1340>
# 想用类里面的属性和方法
print(student.school_name)
print(student.read()) # None
【三】类的定义和调用
【1】类的属性
class Student(object):
# 数据属性
school_name = "清华"
# 函数属性
def read(self):
age = 18
# self : 表示对象自己本身,
print(f"当前学校是 {self.school_name}")
student = Student()
print(student) # <__main__.Student object at 0x000001F2074B1340>
# 想用类里面的属性和方法
print(student.school_name)
print(student.read()) # None
【2】查看类的名称空间(dict)
class Student:
# 学生类公共的数据
school = '清华大学'
# 学生类公共的功能
def choose_course(self):
print('学生选课功能')
'''
类体代码无需调用就会执行 产生类的名称空间
语法结构
class 类名:
类体代码
1.class是定义类的关键字
2.类名类似于函数名 但是首字母推荐大写 用于区分
3.类体代码就是存放对象公共数据和功能的地方
数据: 变量名 = 变量值
功能: 函数
'''
# 查看名称空间的方法>>>:__dict__
print(Student.__dict__) # 返回值是一个字典
print(Student.__dict__['school']) # 清华大学 获取类中的属性
print(Student.__dict__['choose_course']) # 获取类中的属性
'''类获取数据和功能有一个简便的方式>>>:句点符'''
print(Student.school)
print(Student.choose_course())
''' 如何产生对象:类名加括号 '''
obj1 = Student() # 类名加括号就是在产生一个对象
obj2 = Student()
print(obj1.__dict__, obj2.__dict__) # {} {}
Ⅳ 对象实例化方法推导步骤
class Student:
# 学生类公共的数据
school = '清华大学'
# 学生类公共的功能
def choose_course(self):
print('学生选课功能')
obj1 = Student() # 目前对象没有自己独有的属性
obj2 = Student() # 目前对象没有自己独有的属性
# print(obj1.__dict__) # 大白话就是给字典添加键值对
# print(obj2.__dict__) # 大白话就是给字典添加键值对
'''方式一 逐步给对象添加独有的数据'''
obj1.__dict__['name'] = 'silence' # obj1.name = silence
obj1.__dict__['age'] = 18 # obj1.age = 18
obj1.__dict__['gender'] = 'male' # obj1.gender = male
obj2.__dict__['name'] = 'happy'
obj2.__dict__['age'] = 25
obj2.__dict__['gender'] = 'female'
print(obj1.__dict__, obj2.__dict__)
# {'name': 'silence', 'age': 18, 'gender': 'male'}
# {'name': 'happy', 'age': 25, 'gender': 'female'}
print(obj1.name) # silence
print(obj2.name) # happy
class Student:
# 学生类公共的数据
school = '清华大学'
# 学生类公共的功能
def choose_course(self):
print('学生选课功能')
obj1 = Student() # 目前对象没有自己独有的属性
obj2 = Student() # 目前对象没有自己独有的属性
# print(obj1.__dict__) # 大白话就是给字典添加键值对
# print(obj2.__dict__) # 大白话就是给字典添加键值对
'''方案二:将冗余的添加步骤封装成函数'''
def init(obj,name,age,gender):
obj.__dict__['name'] = name # obj1.name = name
obj.__dict__['age'] = age # obj1.age = age
obj.__dict__['gender'] = gender # obj1.gender = gender
init(obj1,'silence',18,'female')
print(obj1.name) # silence
'''方案三:简单的封装成函数没有体现出面向对象整合的精髓>>> 将函数写到类中'''
class Student:
def init(obj, name, age, gender):
obj.__dict__['name'] = name # obj1.name = name
obj.__dict__['age'] = age # obj1.age = age
obj.__dict__['gender'] = gender
# 学生类公共的数据
school = '清华大学'
# 学生类公共的功能
def choose_course(self):
print('学生选课功能')
obj1 = Student() # 目前对象没有自己独有的属性
obj2 = Student()
# def init(obj,name,age,gender):
# obj.__dict__['name'] = name # obj1.name = name
# obj.__dict__['age'] = age # obj1.age = age
# obj.__dict__['gender'] = gender # obj1.gender = gender
Student.init(obj1,'silence',18,'male')
print(obj1.name) # silence
'''方案四:类中针对给对象创建独有数据的函数名 专门定义了一个固定方法__init__'''
class Student:
def __init__(self, name, age, gender):
# ps:针对括号内第一个形参self就是一个普通的变量名而已
# 只不过该变量名将来专门接收对象的 所以给他起了一个固定的名字叫self
'''该方法就一个功能>>>:给对象添加独有的数据'''
self.__dict__['name'] = name # obj1.name = name
self.__dict__['age'] = age # obj1.age = age
self.__dict__['gender'] = gender
# 学生类公共的数据
school = '清华大学'
# 学生类公共的功能
def choose_course(self):
print('学生选课功能')
obj1 = Student('silence',18,'male')
print(obj1.__dict__) #{'name': 'silence', 'age': 18, 'gender': 'male'}
'''
类中的__init__方法会在类产生对象的时候自动执行
类产生对象的具体步骤:
1.先创建一个没有独有数据的空对象 {}
2.将空对象和类括号内传入的数据一并交给__init__执行
__init__的第一个参数就是对象本身
__init__(obj, name, age, gender)
3.将创建好的对象自动返回
'''
【3】实例化类得到对象
# 得到的对象每一次都是新的
student_one = Student()
student_two = Student()
print(id(student_one))
# 1853725687376
print(id(student_two))
# 1853726139200
【4】如何修改对象的属性
# 【1】通过类的名称空间修改属性
# 类的名称空间不允许修改属性
space_class = Student.__dict__
print(space_class, type(space_class)) # <class 'mappingproxy'>
print(space_class['school_name'])
print(space_class.get('school_name'))
# print(space_class.school_name) # 'mappingproxy' object has no attribute 'school_name'
Student.__dict__['school_name'] = '北大'
print(Student.__dict__['school_name'])
class Student(object):
# 数据属性
school_name = "清华"
# 函数属性
def read(self):
age = 18
# self : 表示对象自己本身,
print(f"当前学校是 {self.school_name}")
# 【2】修改对象的属性
student = Student()
student_one = Student()
obj_space = student.__dict__
obj_space['name'] = 'silence'
print(obj_space, type(obj_space)) # <class 'dict'>
print(obj_space['name']) # silence
print(student.school_name)
print(student.name) # silence
print(student_one.school_name) # silence
# print(student_one.name) # silence
# 【3】批量修改属性
student_one = Student()
student_two = Student()
# 方式一:通过民称空间字典替换
student_one.__dict__['name'] = "silence"
# 方式二:通过对象.属性名=属性值替换
student_one.name = 'silence'
student_one.age = 18
student_one.gender = 'male'
student_two.name = 'opp'
student_two.age = 19
student_two.gender = 'female'
# 批量想对象中添加各自独有的属性值和属性名
def init_obj(obj,name,age,gender):
obj.name = name
obj.age = age
obj.gender = gender
student_one = Student()
student_two = Student()
init_obj(obj=student_one,name='silence',age=18,gender='male')
init_obj(obj=student_two,name='happy',age=19,gender='female')
print(student_one.name)
print(student_two.name)
# 【4】在类内部初始化自己的参数
class Student(object):
# 数据属性
school_name = "清华"
def init_obj(self, name, age, gender):
# self 就是这个类的对象本身
self.name = name
self.age = age
self.gender = gender
# 函数属性
def read(self):
print(f"当前学校是 {self.school_name}")
print(f"当前学生姓名是 {self.name}")
print(f"当前学生年龄是 {self.age}")
print(f"当前学生性别是 {self.gender}")
student = Student()
# 'Student' object has no attribute 'name'
student.init_obj(name='dream',age=18,gender='male')
student.read()
# 【五】魔法方法值初始化方法 __init__
class Student(object):
# 数据属性
school_name = "清华"
def __init__(self, name, age, gender):
# self 就是这个类的对象本身
self.name = name
self.age = age
self.gender = gender
# 函数属性
def read(self):
print(f"当前学校是 {self.school_name}")
print(f"当前学生姓名是 {self.name}")
print(f"当前学生年龄是 {self.age}")
print(f"当前学生性别是 {self.gender}")
def write(self):
print(f"当前学生 :>>> {self.name} 可以写作业!")
# 初始化类得到对象
student = Student(name='silence', age=18, gender='male')
print(student.__dict__)
student.read()
student.write()
student_one = Student(name='happy', age=28, gender='female')
student_one.read()
student_one.write()
【5】属性查找顺序
class BaseStudent(object):
school_name = '北大'
class Student(BaseStudent):
# 数据属性
# school_name = "清华"
# 实例化对象的时候就会被触发 Student() 一定会报错
def __init__(self, name, age, gender):
# self 就是这个类的对象本身
self.name = name
self.age = age
self.gender = gender
def set_info(self,class_id):
self.class_id = class_id
# 函数属性
def read(self):
print(f"当前学校是 {self.school_name}")
print(f"当前学生姓名是 {self.name}")
print(f"当前学生年龄是 {self.age}")
print(f"当前学生性别是 {self.gender}")
print(f"当前学生课程ID是 {self.class_id}")
def write(self):
print(f"当前学生 :>>> {self.name} 可以写作业!")
# 初始化类得到对象
student = Student(name='silence', age=18, gender='male')
# print(student.name)
student.set_info(class_id=1)
student.read()
student.name = 'happy' # student.__dict__['name'] = 'happy'
print(student.name)
# 属性查找顺序
print(student.name)
print(student.school_name)
# 查找顺序
# 首先在自己的对象中查找
# 自己找不到就去父类里面找
# 如果父类里面找不到,就去基类里面找
# 如果基类里面也没有,就去 object 里面找
# 如果还是找不到则报错
【6】列表特性回顾
num_one_list = [1, 2, 3, 4]
num_two_list = [4, 5, 6, 7]
num_one_list.append(9)
# 每一个列表都是一个单独的对象
print(num_one_list)
print(num_two_list)
class Student:
def __init__(self, name):
self.name = name
s1 = Student(name='silence')
print(id(s1)) #
s1.name = 'happy'
print(id(s1))
【四】类的属性扩展
# 【一】定义类
class Animal(object):
animal_name = ''
class Duck(Animal, object):
'''
这是一条注释
'''
# 这是一条注释
def __init__(self, name, age):
self.name = name
self.age = age
def speak(self):
print(f"这是一只鸭子 叫 {self.name} 已经 {self.age} 岁了!")
def speak(obj):
print(f"obj.__class__.__name__ :>>>> {obj.__class__.__name__}")
duck = Duck(name='唐老鸭', age=2)
speak(obj=duck)
# 【二】属性介绍
# 【1】获取当前类的名字
print(Duck.__name__)
# 【2】获取类中的文档字符串
print(Duck.__doc__)
# 【3】获取类的父类
print(Duck.__base__) # <class '__main__.Animal'>
# 【4】获取类的所有父类
print(Duck.__bases__) # (<class '__main__.Animal'>, <class 'object'>)
# 【5】获取当前类的名称空间
print(Duck.__dict__)
# 【6】获取类定义所在的模块名
print(Duck.__module__) # __main__
Ⅴ 绑定方法
'''
在类中定义的函数默认都是绑定给对象使用的
即对象来调 会自动将对象当作第一个参数传入
'''
class Student:
school = '清华大学'
# __init__不要自己去调用
def __init__(self, name, age):
self.name = name
self.age = age
def func(self):
print('%s正在调用func方法' % self.name)
def index(self):
print('%s正在调用index方法' % self.name)
obj1 = Student('silence', 18)
obj2 = Student('happy', 25)
'''
# 类调用类中函数, 有几个参数就要传几个参数
Student.func(123,222) # 123
print(obj1) # <__main__.Student object at 0x0000021635C6AE60>
# 对象调用类中函数,会将当前调用的对象当作第一个参数自动传入
# 就如def func(self,xxx) Student.func(123,222) 需要两个参数
# obj1.func(123) 只需一个 他会将self当前调用的对象当成第一个参数
obj1.func(123) # <__main__.Student object at 0x0000021635C6AE60>
'''
obj1.func() # silence正在调用func方法
obj2.func() # happy正在调用func方法
标签:__,obj,name,self,面向对象,print,age
From: https://www.cnblogs.com/zyb123/p/18166668