python31 -面向对象的推导-类-对象
今日学习
代码优化总结
编程思想
对象与类的概念
对象与类的创建
对象独有的数据
面向对象前戏
案例推导:人狗大战
1.'创造'人狗
-==================#推导直接手动模拟一个个人和狗==================================
person1 = {
'name':'李白',
'p_type':'刺客',
'attack_val':800,
'life_val':200
}
person2 = {
'name':'盾山',
'P_type':'坦克',
'attack_val':'100',
'life_val':1200
}
dog1 = {
'name':'小黑狗',
'd_type':'泰迪',
'attack_val':'500',
'life_val':800
}
dog2 = {
'name':'小舔狗',
'd_type': '比特',
'attack_val':800,
}
---------总结-------------------------------------------------------
###如果定义人和狗的数量很多,这样写,太烦了。需要不停的写重复操作,所以封装成函数
#推导2,这个层是一整个例子。
==============------先定义人-----------==============================================
def get_person(name, gender, age, p_type, attack_val, life_val):
"""
专用用于产生用户字典(创造人)
:param name: 姓名
:param gender: 性别
:param age: 年龄
:param d_type: 类型
:param attack_val:攻击力
:param life_val: 生命值
:return: 人的字典(人)
"""
person_obj = {
'name': name,
'gender': gender,
'age': age,
'p_type': p_type,
'attack_val': attack_val,
'life_val': life_val
}
return person_obj
=========--------定义狗-------------===================================================
def get_dog(name, d_type, attack_val, life_val):
"""
专门用于产生狗字典(狗)
:param name: 狗的名字
:param d_type: 狗的类型
:param attack_val: 狗的攻击力
:param life_val: 狗的生命值
:return: 狗的字典(狗)
"""
dog_obj = {
'name': name,
'd_type': d_type,
'attack_val': attack_val,
'life_val': life_val
}
return dog_obj
# d1 = get_dog('小黄狗','中华田园犬',800, 5000)
# d2 = get_dog('小奶狗','哈士奇',100, 200)
"""推导步骤3: 让人和狗具备攻击的能力 本质其实就是定义两个函数供人和狗调用"""
=========================让人具备攻击能力===================================
def person_attack(person_obj, dog_obj):
"""
专用提供给人调用 攻击狗
:param person_obj: 传人数据(字典)
:param dog_obj: 传狗数据(字典)
"""
print('即将被攻击的狗:%s 当前血量:%s' % (dog_obj.get('name'), 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.get('life_val')))
def dog_attack(dog_obj, person_obj):
"""
专用提供给狗调用 攻击人
:param dog_obj: 传狗数据(字典)
:param person_obj: 传人数据(字典)
"""
print('即将被攻击的人:%s 当前血量:%s' % (person_obj.get('name'), 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.get('life_val')))
# 调用产生人和狗的函数
p1 = get_person('张飞', 'male', 18, '猛男', 8000, 90000)
p2 = get_person('李逵', 'female', 28, '淑女', 10, 200)
d1 = get_dog('小黄狗', '恶霸犬', 800, 8000)
d2 = get_dog('小黑狗', '巴哥犬', 200, 500)
# 调用攻击彼此的函数
# person_attack(p1, d1)
-------------执行结果1-----------------------------------------
# 即将被攻击的狗:小黄狗 当前血量:8000
# 人:张飞 锤了 狗:小黄狗 狗掉血:8000 剩余血量:0
dog_attack(p2, d2)
================执行结果2===========================================
即将被攻击的人:小黑狗 当前血量:500
狗:李逵 咬了 人:小黑狗 人掉血:10 剩余血量:490
#是不是发现乱套了。 被攻击的人:小黑狗,函数被随意调用了。
面向对象
-
本质:将特定的数据与特定的功能绑定到一起 将来只能彼此相互使用
从上面的例子
将人的数据跟人的功能绑定到一起
只有人可以调用人的功能
将狗的数据跟狗的功能绑定到一起
只有狗可以调用狗的功能
我们将数据与功能绑定到一起的操作起名为:'面向对象编程'
编程思想 面向对象|面向过程
面向过程是面向对象的基础,面向过程过程是解决唯一的不重复的工作,面向对象是尽可能的避免冗余的工作。
面向过程编程||
============
截止昨天 我们所编写的代码都是面向过程编程
过程其实就是流程 面向过程编程其实就是在执行一系列的流程
eg: 注册功能 登录功能 冻结账户 ...
就是按照指定的步骤依次执行 最终就可以得到想要的结果
---------------------------------------------------------------------------------------
面向对象编程||
============
核心就是'对象'二字
对象其实就是一个容器 里面将数据和功能绑定到了一起
eg: 游戏人物 ...
只负责创造出该人物以及该人物具备的功能 至于后续战绩如何无人知晓
"""
面向过程编程相当于让你给出一个问题的具体解决方案
面向对象编程相当于让你创造出一些事物之后不用你管
"""
上述两种编程思想没有优劣之分 仅仅是使用场景不同
甚至很多时候是两者混合使用
类别 | 定义 |
---|---|
面向对象编程 | 面向对象是把整个需求按照特点、功能划分,将这些存在共性的部分封装成类(类实例化后才是对象),创建了对象不是为了完成某一个步骤,而是描述某个事物在解决问题的步骤中的行为 |
面向过程编程 | 可以说面向过程是一种基础的方法。. 它考虑的是实际地实现。. 一般的面向过程是从上往下步步求精,是一种以事件为中心的编程思想,编程的时候把解决问题的步骤分析出来,然后用函数把这些步骤实现,在一步一步的具体步骤中再按顺序调用函数。 |
对象与类的概念
-
对象:数据与功能的结合体
-
类:多个对象相同的数据和功能的结合体
=====================
类:0
"""
类比学习法
一个人 对象
多个人 人类
一条狗 对象
多条狗 犬类
"""
类主要用于记录多个对象相同的数据和功能
对象则用于记录多个对象不同的数据和功能
ps:在面向对象编程中 类仅仅是用于节省代码 对象才是核心
对象与类的问题:
1.如何定义类
2.如何定义对象
3.如何查看对象
对象与类的创建
-
创建类的完整语法
-
定义类名,不用加小括号
-
Pople类名,首字符大写。方便跟函数名做区分//
-
定义即调用,就是说在定义时候就已经处于调用。
-
类加括号就是产生一个对象|函数加括号就是调用
-
类里面的定义的变量功能,所有的对象都可以去访问
# 类 例子
class People: #People定义类名
# 学生对象的公共数据
school = '清华大学'
# 学生对象的公共方法
def choice_course(self):
print('正在选课')
#查看People的名称空间
print(People.__dict__)
-------------------------------------
1.class是定义类的关键字
2.People是类的名字
3.类体代码
公共的数据\公共的方法
---------------再次敲重点-----------------------------------------
ps:类体代码在类定义阶段就会执行!!!People类为了跟函数命名区分,首字符会大写 跟函数有很大区别嗷。!!!!!!!!!
-----------------#1. 查看名称空间的方法 #比较麻烦-------------------------------------
print(People.__dict__) # 使用该方法查看名称空间 可以看成是一个字典
------执行结果---------------
{'__module__': '__main__', 'school': '清华大学', 'choice_course': <function People.choice_course at 0x0000029788D98940>, '__dict__': <attribute '__dict__' of 'People' objects>, '__weakref__': <attribute '__weakref__' of 'People' objects>, '__doc__': None}
-----------------------#2.取值- 比较麻烦-----------------------------------------
print(People.__dict__['school']) # 使用字典的取值方式获取名字
--------执行结果------------
清华大学
-------------------------------------------------------------------------------------
print(People.__dict__.get('choice_course')) # 使用字典的取值方式获取名字
<function People.choice_course at 0x000001CEC9F98940>
-
---总结-------
-
'''在面向对象编程中 想要获取名称空间中的名字 可以采用句点符,python简化操作'''
-
print(People.school) #相当于print(People.__dict__['school']) 清华大学
class People: #People定义类名
# 学生对象的公共数据
school = '清华大学'
# 学生对象的公共方法
def choice_course(self):
print('正在选课')
#查看People的名称空间
print(Student.school)
print(Student.choice_course)
-----------------------------------------------------------------------------------
'''类实例化产生对象>>>: 类名加括号''' |函数体 加括号就是调用函数代码
-----------------------------------------------------------------------------------
stu1 = Student()
stu2 = Student()
print(stu1.school)
print(stu2.school)
--------------------------------------------------------------------------------------
print(stu1) #类加括号就是产生一个对象
----执行结果-----------
<__main__.Student object at 0x000001D923B04A60>
print(stu2) #类加括号就是产生一个对象
-----执行结果-----------
# <__main__.Student object at 0x0000025E8A48F130>
--------------------------------------------------------------------------------------
# print(stu1.__dict__, stu2.__dict__) # {} {}
# print(stu1.school)
# print(stu2.school)
# print(stu1.choice_course)
# print(stu2.choice_course)
------------------------------------------------------------------------------------
Student.school = '北京大学' # 修改school键对应的值
print(stu1.school)
print(stu2.school)
-------------------------------------------------------------------------------------
"""
我们习惯将类或者对象句点符后面的东西称为属性名或者方法名 函数叫方法名。.school叫属性名
"""
对象独有的数据
1.什么叫对象独有的数据?
在对象自己的名称空间里有一些名字
# 学生类
class Student:
# 学生对象的公共数据
school = '清华大学'
# 学生对象的公共方法
def choice_course(self):
print('正在选课')
--------------------------------------------------------------------------
'''推导思路1: 直接利用__dict__方法朝字典添加键值对'''
--------------------------------------------------------------------------
obj1 = Student()
print(obj1.__dict__)
-----执行结果-----------
{} #对象是空值
print(obj1.name)
---执行结果----------- #因为obj1对象 没有name的名字,会在类里找,类里也没有会报错
AttributeError: 'Student' object has no attribute 'name'
------对象如何拥有名字--【给obj1对象定义赋值】-------
obj1.__dict__['name'] = 'jason' # 等价于 obj1.name = 'jason'
obj1.__dict__['age'] = 18 # 等价于 obj1.age = 18
obj1.__dict__['gender'] = 'male' # ...
--------打印【对象】里的内容----------------
print(obj1.__dict__)
----执行结果---------------
{'name': 'jason', 'age': 18, 'gender': 'male'}
print(obj1.name)
----执行结果---------------
jason
print(obj1.age)
----执行结果---------------
18
print(obj1.gender)
----执行结果---------------
male
print(obj1.school)
------执行结果--------------
清华大学
----------生成obj2对象,并产生内容-----------
obj2 = Student()
obj2.__dict__['name'] = 'kevin'
obj2.__dict__['age'] = 28
obj2.__dict__['gender'] = 'female'
print(obj2.name)
print(obj2.age)
print(obj2.gender)
print(obj2.school)
=====================================
!!如果给100个学生生成数据,岂不是很麻烦?
!!需要优化
!!定义函数,进行传参,将学生的基本信息设置成形参,传参赋值。参考推导思路2
=====================================
-----------------------------------------------------------------------------
'''推导思路2: 将添加独有数据的代码封装成函数'''
-----------------------------------------------------------------------------
def init(obj,name,age,gender):
obj.__dict__['name'] = name
obj.__dict__['age'] = age
obj.__dict__['gender'] = gender
stu1 = Student()
stu2 = Student()
init(stu1,'jason',18,'male') #通过init函数调用赋值传参。
init(stu2, 'kevin',28,'female')
print(stu1.__dict__)
-------执行结果-----------------
# {'name': 'jason', 'age': 18, 'gender': 'male'}
-------执行结果-----------------
print(stu2.__dict__)
# {'name': 'kevin', 'age': 28, 'gender': 'female'}
============================
!!!! 1.这样只要每个学生进行定义传参,对象就会产生相对应的数据。
!!!!2.确实方便了很多。
!!!!3.但是在学生类里,本来产生的是学生对象数据,如果把狗,猫类的小动物调用,也会产生数据
!!!!4.所以接下来需要绑定 学生只能创建学生对象独有的数据,其他类别的不能调用
=========================
-------------------------------------------------------------------------------------
'''推导思路3: init函数是专用给学生对象创建独有的数据 其他对象不能调用>>>:面向对象思想 将数据和功能整合到一起
将函数封装到学生类中 这样只有学生类产生的对象才有资格访问
'''
-------------------------------------------------------------------------------------
class Student:
"""
1.先产生一个空对象
2.自动调用类里面的__init__方法 将产生的空对象当成第一个参数传入
3.将产生的对象返回出去
"""
def __init__(self, name, age, gender):
self.name = name # obj.__dict__['name'] = name
self.age = age # obj.__dict__['age'] = age
self.gender = gender # obj.__dict__['gender'] = gender
# 左右两边的名字虽然一样 但是意思不一样 左边的其实是字典的键 右边的其实是实参
# 学生对象公共的数据
school = '清华大学'
# 学生对象公共的方法
def choice_course(self):
print('正在选课')
self | name | age |gender
stu1 = Student('jason', 18, 'male')
print(stu1.__dict__) # {'name': 'jason', 'age': 18, 'gender': 'male'}
stu2 = Student('kevin', 28, 'female')
print(stu2.__dict__) # {'name': 'kevin', 'age': 28, 'gender': 'female'}