面向对象 Object Oriented

概述

面向过程

1.分析出解决问题的步骤,然后逐步实现。例如:婚礼筹办-- 发请柬(选照片、措词、制作)-- 宴席(场地、找厨师、准备桌椅餐具、计划菜品、购买食材)-- 婚礼仪式(定婚礼仪式流程、请主持人)
2.公式:程序 = 算法 + 数据结构
3.优点:所有环节、细节自己掌控。
4.缺点:考虑所有细节,工作量大。

面向对象

1.找出解决问题的人,然后分配职责。
例如:婚礼筹办-- 发请柬:找摄影公司(拍照片、制作请柬)-- 宴席:找酒店(告诉对方标准、数量、挑选菜品) -- 婚礼仪式:找婚庆公司(对方提供司仪、制定流程、提供设备、帮助执行)
2.公式:程序 = 对象 + 交互
3.优点
(1)思想层面:-- 可模拟现实情景,更接近于人类思维。-- 有利于梳理归纳、分析解决问题。
(2)技术层面:-- 高复用:对重复的代码进行封装,提高开发效率。-- 高扩展:增加新的功能,不修改以前的代码。-- 高维护:代码可读性好,逻辑清晰,结构规整。
4.缺点:学习曲线陡峭。

类和对象

1.类:一个抽象的概念,即生活中的”类别”。
2.对象:类的具体实例,即归属于某个类别的”个体”。
3.类是创建对象的”模板”。-- 数据成员:名词类型的状态。-- 方法成员:动词类型的行为。
4.类与类行为不同,对象与对象数据不同。

语法

定义类

1.代码
class 类名:“””文档说明”””def _init_(self,参数列表):self.实例变量 = 参数
方法成员2.  说明
-- 类名所有单词首字母大写.
--  _init_ 也叫构造函数,创建对象时被调用,也可以省略。
--  self 变量绑定的是被创建的对象,名称可以随意。
"""类和对象现实事物  -抽象化->  类  -实例化-> 对象
"""class Wife:"""抽象的老婆"""# 数据:姓名、颜值、钱....def __init__(self, name, face_score, money):self.name = nameself.face_score = face_scoreself.money = money# 方法(函数):玩...def play(self):print(self.name, "在玩耍")jg = Wife("金刚",6,5000)
jg.play()
"""创建1个狗类数据:爱称,年龄,颜色,品种行为:吃、坐下创建2个狗对象,调用相应的方法画出代码内存图
"""class Dog:"""狗"""def __init__(self, name, age=0, color="", breed=""):self.pet_name = nameself.age = ageself.color = colorself.breed = breeddef eat(self):print(self.pet_name, "在吃")def sit(self):print(self.pet_name, "坐下")mx = Dog("米咻", 4, "黄", "拉布拉多")
hm = Dog("黑米", 3, "黑", "拉布拉多")
mx.sit()
hm.sit()# 练习1:
mx = Dog("米咻", 4, "黄", "拉布拉多")
d01 = mx
d01.pet_name = "咻咻"
mx.age = 5
print(d01.pet_name)
print(d01.age)
print(mx.pet_name)
print(mx.age)# 练习2:
# 17:00
def func01(p1, p2):p1 = Dog("小白", 5)p2.pet_name = "小黑"p2.age = 6mx = Dog("米咻", 4)
hm = Dog("黑米", 3)
func01(mx, hm)
print(mx.pet_name, mx.age)  # ?
print(hm.pet_name, hm.age)  # "小黑"   6
class Wife:def __init__(self, name, face_score, money):self.name = nameself.face_score = face_scoreself.money = moneydef print_self(self):print("%s--%d--%d" % (self.name, self.face_score, self.money))w01 = Wife("建宁", 86, 999999)
list_wifes = [w01,Wife("双儿", 95, 5000),Wife("苏荃", 98, 10000),Wife("阿珂", 100, 6000),Wife("铁锤", 80, 0),
]# 练习1:定义函数,在老婆列表中查找双儿对象
#       测试:调用双儿对象的print_self方法
def find01():for item in list_wifes:if item.name == "双儿2":return item# 测试:
result = find01()
# 如果找到了
if result:result.print_self()# 练习2:定义函数,在老婆列表中查找所有老婆的姓名
#       测试:打印列表
def find02():# list_result = []# for item in list_wifes:#     list_result.append(item.name)# return list_resultreturn [item.name for item in list_wifes]print(find02())

创建对象(实例化)

变量 = 构造函数 (参数列表)

实例成员

实例变量

1.语法(1)定义:对象.变量名(2)调用:对象.变量名 2.说明(1)首次通过对象赋值为创建,再次赋值为修改.w01 = Wife()w01.name = “丽丽”w01.name = “莉莉”(2)通常在构造函数(_init_)中创建。w01 = Wife(“丽丽”,24)print(w01.name)(3)每个对象存储一份,通过对象地址访问。3.作用:描述某个对象的数据。
4.__dict__:对象的属性,用于存储自身实例变量的字典。

实例方法

1.语法(1) 定义:  def 方法名称(self, 参数列表):方法体(2) 调用: 对象地址.实例方法名(参数列表)不建议通过类名访问实例方法
2.说明(1) 至少有一个形参,第一个参数绑定调用这个方法的对象,一般命名为"self"。(2) 无论创建多少对象,方法只有一份,并且被所有对象共享。
3.作用:表示对象行为。
"""实例成员实例变量:对象不同的数据实例方法:对象相同行为核心逻辑:对象.?
"""# 1. 标准写法
class Wife:def __init__(self, name):# 创建实例变量:对象.变量名 = 数据self.name = namedef print_self(self):print("我叫:", self.name)def play(self):print("在玩耍")# 对象.方法名()self.print_self()w01 = Wife("双儿")
w02 = Wife("阿珂")# 读取实例变量:?  = 对象.变量名
print(w01.name)# 内置实例变量
# -- 获取当前对象所有实例变量
print(w01.__dict__)w01.play()
w02.play()# 2. 不建议(实例变量应该由类的定义者决定)
# class Wife:
#     pass
#
# w01 = Wife()
# # 创建实例变量:对象.变量名 = 数据
# w01.name = "双儿"
# # 读取实例变量:?  = 对象.变量名
# print(w01.name)# 3. 不建议(实例变量应该直接在init中定义)
# class Wife:
#     def __init__(self):
#         pass
#
#     def func01(self,name):
#         # 创建实例变量:对象.变量名 = 数据
#         self.name = name
#
# w01 = Wife()
# w01.func01("双儿")
# # 读取实例变量:?  = 对象.变量名
# print(w01.name)dict01 = {}
dict01["name"] = "双儿"
dict01["name"] = "双双"
"""创建类:敌人类实例变量:姓名,血量,防御力,攻击力方法:受伤 - 血量减少打印自身信息 - 打印所有实例变量创建敌人列表(3)-- 定义函数,在敌人列表中找出所有活的敌人-- 定义函数,在敌人列表中找出攻击力大于50的敌人名称与攻击力-- 定义函数,在敌人列表中找出防御力最小的敌人-- 定义函数,在敌人列表中删除血量大于50的所有敌人-- 定义函数,根据攻击力进行降序排列体会:对象.?
"""class Enemy:def __init__(self, name="", hp=0, defense=0, atk=0):self.name = nameself.hp = hpself.defense = defenseself.atk = atkdef damage(self):self.hp -= 10print(self.name, "被攻击,血量减少10", )def print_self(self):print("我是%s血量%d防御力%d攻击力%d" % (self.name, self.hp, self.defense, self.atk))list_enemys = [Enemy("成昆", 0, 10, 90),Enemy("玄冥一老", 90, 8, 80),Enemy("玄冥二老", 95, 9, 95),
]# 练习1
def find01():list_result = []for item in list_enemys:if item.hp > 0:list_result.append(item)return list_result# 测试
# for item in find01():
#     item.print_self()for item in find01():item.damage()# 练习2
def find02():list_result = []for item in list_enemys:if item.atk > 50:list_result.append((item.name, item.atk))return list_result# 测试    11:30
for item in find02():print(item)# 练习3
def get_min_by_defense():min_value = list_enemys[0]for i in range(1, len(list_enemys)):if min_value.defense > list_enemys[i].defense:min_value = list_enemys[i]return min_value# 测试
result = get_min_by_defense()
result.damage()# 练习3  -- 定义函数,在敌人列表中删除血量大于50的所有敌人
def delete_all_by_hp():count = 0for i in range(len(list_enemys) - 1, -1, -1):if list_enemys[i].hp > 50:del list_enemys[i]count += 1return count# print(delete_all_by_hp())# 定义函数,根据攻击力进行降序排列
def sort():for r in range(len(list_enemys) - 1):for c in range(r + 1, len(list_enemys)):if list_enemys[r].atk < list_enemys[c].atk:list_enemys[r], list_enemys[c] = list_enemys[c], list_enemys[r]sort()
for item in list_enemys:item.print_self()

类成员

类变量

1.语法(1)定义:在类中,方法外定义变量。class 类名:变量名 = 表达式(2)调用:类名.变量名不建议通过对象访问类变量
2.说明(1) 存储在类中。(2) 只有一份,被所有对象共享。
3.作用:描述所有对象的共有数据。

类方法

1.语法(1)定义:@classmethoddef 方法名称(cls,参数列表):方法体(2)调用:类名.方法名(参数列表) 不建议通过对象访问类方法
2.说明(1) 至少有一个形参,第一个形参用于绑定类,一般命名为'cls'(2) 使用@classmethod修饰的目的是调用类方法时可以隐式传递类。(3) 类方法中不能访问实例成员,实例方法中可以访问类成员。
3.作用:操作类变量。
"""类成员类变量:大家的数据类方法:大家的行为核心逻辑:类.?
"""class ICBC:# 总行的钱total_money = 1000000@classmethoddef print_total_money(cls):print("总行的钱:", cls.total_money)def __init__(self, name="", money=0):# 实例变量self.name = name# 支行的钱self.money = money# 从总行扣除当前支行需要的钱ICBC.total_money -= moneyi01 = ICBC("天坛支行", 100000)
i02 = ICBC("陶然亭支行", 200000)
# print("总行的钱:",ICBC.total_money)
ICBC.print_total_money()  # print_total_money(ICBC)

静态方法

1.语法(1)定义:@staticmethoddef 方法名称(参数列表):方法体(2)调用:类名.方法名(参数列表) 不建议通过对象访问静态方法
2.说明(1) 使用@ staticmethod修饰的目的是该方法不需要隐式传参数。(2) 静态方法不能访问实例成员和类成员
3.作用:定义常用的工具函数。
"""静态方法可以独立存在的工具函数
"""
class Vector2:"""二维向量"""def __init__(self, x, y):self.x = xself.y = y@staticmethoddef get_right():return Vector2(0, 1)@staticmethoddef get_up():return Vector2(-1, 0)@staticmethoddef get_left():return Vector2(0, -1)list01 = [["00", "01", "02", "03"],["10", "11", "12", "13"],["20", "21", "22", "23"],["30", "31", "32", "33"],
]# 位置
pos = Vector2(1, 2)
# 方向
# right = Vector2(0, 1)
right = Vector2.get_right()
# 需求:沿着某个方向移动
pos.x += right.x
pos.y += right.yprint(pos.x,pos.y)# 练习1:创建向上的静态方法
# 练习2:创建向左的静态方法
# 测试:让某个位置沿着该方向移动
up = Vector2.get_up()
pos.x += up.x
pos.y += up.y
print(pos.x,pos.y)

三大特征

封装

"""封装目标:保障数据有效性原理1. 私有化数据(不隐藏在类外就可以随意操作,无法进行限制)2. 提供读取与写入方法(数据验证)
"""class Wife:def __init__(self, name="", age=0):self.name = name# self.__age = ageself.set_age(age)def set_age(self, value):if 22 <= value <= 32:self.__age = valueelse:raise Exception("我不要")def get_age(self):return self.__agew01 = Wife("双儿", 25)
print(w01.name)
# print(w01.__age) # 不能访问私有变量
print(w01.get_age()) # 通过方法读取数据

数据角度讲

1.定义:将一些基本数据类型复合成一个自定义类型。
2.优势:将数据与对数据的操作相关联。代码可读性更高(类是对象的模板)。

行为角度讲

1.定义:类外提供必要的功能,隐藏实现的细节。
2.优势:简化编程,使用者不必了解具体的实现细节,只需要调用对外提供的功能。
3.私有成员:(1)作用:无需向类外提供的成员,可以通过私有化进行屏蔽。(2)做法:命名使用双下划线开头。(3)本质:障眼法,实际也可以访问。私有成员的名称被修改为:_类名__成员名,可以通过_dict_属性或dir函数查看。
4.属性@property:公开的实例变量,缺少逻辑验证。私有的实例变量与两个公开的方法相结合,又使调用者的操作略显复杂。而属性可以将两个方法的使用方式像操作变量一样方便。(1)定义:@propertydef 属性名(self):return self.__属性名@属性名.setterdef 属性名(self, value):self.__属性名= value(2)调用:对象.属性名 = 数据变量 = 对象.属性名(3)说明:通常两个公开的属性,保护一个私有的变量。@property 负责读取,@属性名.setter 负责写入只写:属性名= property(None, 写入方法名)

设计角度讲

1.定义:(1) 分而治之将一个大的需求分解为许多类,每个类处理一个独立的功能。 (2) 变则疏之变化的地方独立封装,避免影响其他类。(3) 高 内 聚类中各个方法都在完成一项任务(单一职责的类)。 (4) 低 耦 合 类与类的关联性与依赖度要低(每个类独立),让一个类的改变,尽少影响其他类。
2.优势:便于分工,便于复用,可扩展性强。案例:信息管理系统

需求

 实现对学生信息的增加、删除、修改和查询。

分析

界面可能使用控制台,也可能使用Web等等。
1.识别对象:界面视图类     逻辑控制类     数据模型类2.分配职责:
界面视图类:负责处理界面逻辑,比如显示菜单,获取输入,显示结果等。
逻辑控制类:负责存储学生信息,处理业务逻辑。比如添加、删除等
数据模型类:定义需要处理的数据类型。比如学生信息。3.建立交互:
界面视图对象  <----> 数据模型对象   <---->  逻辑控制对象

设计

 数据模型类:StudentModel   数据:编号 id,姓名 name,年龄 age,成绩 score 逻辑控制类:StudentManagerController   数据:学生列表 __stu_list 行为:获取列表 stu_list,添加学生 add_student,删除学生remove_student,修改学生update_student,根据成绩排序order_by_score。界面视图类:StudentManagerView数据:逻辑控制对象__manager行为:显示菜单__display_menu,选择菜单项__select_menu_item,入口逻辑main,
输入学生__input_students,输出学生__output_students,删除学生__delete_student,修改学生信息__modify_student
"""封装目标:保障数据有效性property 核心逻辑:拦截1. 创建实例变量2. 提供读取与写入方法(数据验证)3. 创建类变量(与实例变量名称相同),存储property对象
"""class Wife:def __init__(self, name="", age=0):self.name = name# self.set_age(age)self.age = agedef set_age(self, value):if 22 <= value <= 32:self.__age = valueelse:raise Exception("我不要")def get_age(self):return self.__age# property(读取方法,写入方法)age = property(get_age, set_age)w01 = Wife("双儿", 25)
print(w01.name)
# print(w01.get_age())
print(w01.age)
"""封装目标:保障数据有效性property 核心逻辑:拦截1. 创建实例变量2. 提供读取与写入方法(数据验证)3. 创建类变量(与实例变量名称相同),存储property对象
"""class Wife:def __init__(self, name="", age=0):self.name = nameself.age = age@property  # age = property(读取方法, None)def age(self):return self.__age@age.setter  #def age(self, value):if 22 <= value <= 32:self.__age = valueelse:raise Exception("我不要")w01 = Wife("双儿", 25)
print(w01.name)
# print(w01.get_age())
print(w01.age)
"""创建对象计数器提示:统计__init__被调用的次数画出内存图
"""class Wife:count = 0@classmethoddef print_count(cls):print("总共娶了%d个老婆" % cls.count)def __init__(self, name=""):self.name = nameWife.count += 1w01 = Wife("")
w02 = Wife("")
w03 = Wife("")
w04 = Wife("")
w05 = Wife("")
w06 = Wife("")
Wife.print_count()
"""属性练习创建敌人类数据:姓名,血量(0--500),攻击力(10,--100)创建敌人对象,体会拦截的核心逻辑.
"""class Enemy:def __init__(self, name="", hp=0, atk=0):self.name = nameself.hp = hpself.atk = atkdef set_hp(self, value):if 0 <= value <= 500:self.__hp = valueelse:raise Exception("血量超过范围")def get_hp(self):return self.__hphp = property(get_hp, set_hp)def set_atk(self, data):if 10 <= data <= 100:self.__atk = dataelse:raise Exception("攻击力超过范围")def get_atk(self):return self.__atkatk = property(get_atk, set_atk)e01 = Enemy("灭霸", 500, 100)
print(e01.name)
print(e01.hp)
print(e01.atk)
e01.a = 9999999
"""python 属性全部语法核心逻辑:拦截目标:保护数据
"""# 1.  读 + 写属性 快捷键:props + 回车
# class Wife:
#     def __init__(self, age=0):
#         self.age = age
#
#     @property
#     def age(self):
#         return self.__age
#
#     @age.setter
#     def age(self, value):
#         self.__age = value
#
# w01 = Wife(25)
# print(w01.age)# 2. 读 属性   快捷键:prop + 回车
# class Wife:
#     def __init__(self):
#         # 数据从何而来,无所谓(可以从参数来、某个方法来、写死).
#         self.__age = 25
#
#     @property
#     def age(self):
#         return self.__age
#
# w01 = Wife()
# print(w01.age)
#
# w01.age = 222# 3. 写 属性   快捷键:prop + 回车
# class Wife:
#     def __init__(self, age=0):
#         self.age = age
#
#     age = property()#     @age.setter# age.setter(..)
#     def age(self, value):
#         self.__age = value
class Wife:def __init__(self, age=0):self.age = agedef age(self, value):self.__age = valueage = property(None,age)# w01 = Wife(25)
# print(w01.__dict__)
# print(w01.age)
"""封装设计思想分而治之:划分为多个类变则疏之:识别变化点(行为)-------------高内聚:类有且只要一个变化点(原因)低耦合:类与类的关系松散
"""
# 类与类行为不同
# 对象与对象数据不同# 需求:老张开车去东北
# 变化:老张、老李、老王...   --> 数据不同
#      划船、骑车、飞机...   --> 行为不同
#      西北、南北...        --> 数据不同# 写法1
# 语义:老张去东北创建一辆新车
#   老张无论去哪里,都会创建一辆新车
# class Person:
#     def __init__(self, name=""):
#         self.name = name
#
#     def go_to(self,position):
#         print(self.name,"去",position)
#         car = Car()
#         car.run()
#
# class Car:
#     # 实例成员:对象.?
#     def run(self):
#         print("汽车行驶")
#
# lz = Person("老张")
# lz.go_to("东北")# 一辆新车
# lz.go_to("家")# 又一辆新车# 写法2
# 语义:老张开车自己的车去东北
# class Person:
#     def __init__(self, name=""):
#         self.name = name
#         self.car = Car()
#
#     def go_to(self,position):
#         print(self.name,"去",position)
#         self.car.run()
#
# class Car:
#     def run(self):
#         print("汽车行驶")# lz = Person("老张")
# lz.go_to("东北")
# lz.go_to("家")# 写法3
# 语义:老张通过传递的参数,决定如何去东北.
class Person:def __init__(self, name=""):self.name = namedef go_to(self,vehicle,position):print(self.name,"去",position)vehicle.run()class Car:def run(self):print("汽车行驶")lz = Person("老张")
bm = Car()
lz.go_to(bm,"东北")
"""需求:小明在银行取钱现象:人的钱多了   银行的钱少了
"""
class Person:def __init__(self,money):self.money = moneyclass Bank:def __init__(self,money):self.money = moneydef draw_money(self,person,value):self.money -= value# 银行钱少了person.money += value# 人钱多了xm = Person(0)
zsyh = Bank(100000)
zsyh.draw_money(xm,5000)
print("小明的钱:",xm.money)
print("银行的钱:",zsyh.money)
"""需求:玩家(攻击力)攻击敌人(血量),敌人受伤(减血)后可能死亡(播放死亡动画).
"""
class Player:def __init__(self, atk=0):self.atk = atkdef attack(self,enemy):print("玩家打敌人")enemy.damage( self.atk )class Enemy:def __init__(self, hp=0):self.hp = hpdef damage(self,atk):self.hp -= atkprint("额~受伤啦")if self.hp <= 0:self.__death()def __death(self):print("播放死亡动画")p01 = Player(50)
e01 = Enemy(100)
p01.attack(e01)
p01.attack(e01)
"""张无忌教赵敏九阳神功赵敏教张无忌化妆张无忌上班挣了8000赵敏上班挣了10000元
"""
class Person:def __init__(self, name=""):self.name = namedef teach(self,person_other,skill):print(self.name,"教",person_other.name,skill)def work(self,salary):print(self.name,"上班挣了",salary,"元")zwj = Person("张无忌")
zm = Person("赵敏")zwj.teach(zm,"九阳神功")
zm.teach(zwj,"化妆")zwj.work(8000)
zm.work(10000)

继承

语法角度讲

继承方法

 1.代码:class 父类:def 父类方法(self):方法体class 子类(父类):def 子类方法(self):方法体儿子 = 子类()儿子.子类方法()儿子.父类方法()2.说明:子类直接拥有父类的方法.
"""继承语法 -- 方法财产:钱不用孩子挣,但是可以花.皇位:江山不用孩子打,但是可以坐.代码:代码不用子类写,但是可以用.
"""# 设计角度:现有子,再有父.
# 编码角度:现有父,再有子.class Person:def say(self):print("说话")class Student(Person):def study(self):print("学习")class Teacher(Person):def teach(self):print("教学")# 创建父类对象
p01 = Person()
# 只能访问父类成员
p01.say()# 创建子类对象
s01 = Student()
# 既能访问父类成员,也能访问子类成员
s01.say()
s01.study()t01 = Teacher()
# 不能访问兄弟类成员
# t01.study()# 内置函数
# ?对象 是一种?类型
# 人对象是一种人类型
print(isinstance(p01, Person))  # True
# 学生对象是一种人类型
print(isinstance(s01, Person))  # True
# 人对象是一种学生类型
print(isinstance(p01, Student))  # False
# 学生对象是一种老师类型
print(isinstance(s01, Teacher))  # False# ?类型 是一种?类型
# 人类型是一种人类型
print(issubclass(Person, Person))  # True
# 学生类型是一种人类型
print(issubclass(Student, Person))  # True
# 人类型是一种学生类型
print(issubclass(Person, Student))  # False
# 学生类型是一种老师类型
print(issubclass(Student, Teacher))  # False# ?类型是?类型
# 人(对象的)类型是人类型
print(type(p01) == Person)  # True
# 学生类型是人类型
print(type(s01) == Person)  # False

内置函数

isinstance(对象, 类型)
返回指定对象是否是某个类的对象。
issubclass(类型,类型)
返回指定类型是否属于某个类型。

继承数据

1.代码
class 子类(父类):def __init__(self,参数列表):super().__init__(参数列表)self.自身实例变量 = 参数
2.说明
子类如果没有构造函数,将自动执行父类的,但如果有构造函数将覆盖父类的。此时必须通过super()函数调用父类的构造函数,以确保父类实例变量被正常创建。
"""继承语法 -- 数据
"""
class Person:def __init__(self, name=""):self.name = nameclass Student(Person):# 子类构造函数(父类构造函数参数,子类构造函数参数)def __init__(self,name = "", score=0):# 调用父类构造函数super().__init__(name)self.score = score# 创建子类对象,执行子类构造函数.
s01 = Student("悟空",100)
print(s01.name)

定义

重用现有类的功能,并在此基础上进行扩展。
说明:子类直接具有父类的成员(共性),还可以扩展新功能。

优点

一种代码复用的方式。

缺点

 耦合度高:父类的变化,直接影响子类。

设计角度讲

定义

 将相关类的共性进行抽象,统一概念,隔离变化。

适用性

 多个类在概念上是一致的,且需要进行统一的处理。

相关概念

父类(基类、超类)、子类(派生类)。
父类相对于子类更抽象,范围更宽泛;子类相对于父类更具体,范围更狭小。
单继承:父类只有一个(例如 Java,C#)。
多继承:父类有多个(例如C++,Python)。
Object类:任何类都直接或间接继承自 object 类。

多继承

一个子类继承两个或两个以上的基类,父类中的属性和方法同时被子类继承下来。
同名方法的解析顺序(MRO, Method Resolution Order):
类自身 --> 父类继承列表(由左至右)--> 再上层父类A/ \/   \B     C\   /\ /D
"""继承设计思想
"""# 需求:老张开车去东北
# 变化点:飞机、火车、轮船...
# 违反面向对象设计原则
#   开闭原则:允许增加新功能,但是不允许改变之前的代码.
#            对扩展开放,对修改关闭
#   依赖倒置:使用class Person:def go_to(self, vehicle, postion):print("去", postion)if type(vehicle) == Car:vehicle.run()elif type(vehicle) == Airplane:vehicle.fly()class Car:def run(self):print("嘟嘟嘟...")class Airplane:def fly(self):print("嗖嗖嗖...")p01 = Person()
c01 = Car()
a01 = Airplane()
p01.go_to(c01, "东北")
p01.go_to(a01, "东北")
"""继承设计思想
"""# 需求:老张开车去东北
# 变化点:飞机、火车、轮船...
# 违反面向对象设计原则
#   开闭原则:允许增加新功能,但是不允许改变之前的代码.
#            对扩展开放,对修改关闭
#   依赖倒置:使用
# 多态
#     调用父一个方法,在不同的子类上有不同的实现。
#class Person:def go_to(self, vehicle, postion):print("去", postion)# 用交通工具的运输功能vehicle.transport()class Vehicle:"""交通工具"""def transport(self):pass
# ---------------------------------------class Car(Vehicle):def transport(self):print("嘟嘟嘟...")class Airplane(Vehicle):def transport(self):print("嗖嗖嗖...")p01 = Person()
c01 = Car()
a01 = Airplane()
p01.go_to(c01, "东北")
p01.go_to(a01, "东北")
"""手雷爆炸,伤害玩家、敌人生命.变化点:还可能伤害房子,鸭子....要求:增加新事物,不影响手雷类.体会:开闭原则、依赖倒置、继承(设计思想)、多态(设计思想)强调调用谁             强调执行/实现子类不同逻辑
"""class Granade:"""手雷"""def __init__(self, atk=0):self.atk = atkdef explode(self, target):print("手雷爆炸啦")target.damage(self.atk)class Target:def damage(self, value):pass# ------------------------------------------
class Player(Target):def __init__(self, hp=0):self.hp = hpdef damage(self, value):print("玩家受伤,屏幕碎屏")self.hp -= valueclass Enemy(Target):def __init__(self, hp=0):self.hp = hpdef damage(self, value):print("敌人受伤,掉下装备")self.hp -= valueg01 = Granade()
g01.explode(Player())
g01.explode(Enemy())

多态

设计角度讲

定义

 父类的同一种动作或者行为,在不同的子类上有不同的实现。

作用

1.在继承的基础上,体现类型的个性化(一个行为有不同的实现)。
2.增强程序扩展性,体现开闭原则。

语法角度讲

重写

子类实现了父类中相同的方法(方法名、参数)。
在调用该方法时,实际执行的是子类的方法。

快捷键

Ctrl + O

内置可重写函数

Python中,以双下划线开头、双下划线结尾的是系统定义的成员。我们可以在自定义类中进行重写,从而改变其行为。
"""内置可重写函数
"""class Wife:def __init__(self, name, face_score, money):self.name = nameself.face_score = face_scoreself.money = money# 重写__str__作用是:定义当前对象转换的字符串格式#                  显示对象时使用(没有格式限制)def __str__(self):return "臣妾%s,颜值%d,存款%f." % (self.name, self.face_score, self.money)# 重写__repr__作用是:定义当前对象转换的字符串格式#                   克隆当前对象(python语法格式)def __repr__(self):return 'Wife("%s", %d, %f)' % (self.name, self.face_score, self.money)w01 = Wife("双儿", 100, 50000)
message = w01.__str__()
print(message)  # <__main__.Wife object at 0x7ff8a3224cf8>
w02 = Wife("阿珂", 150, 20000)
print(w02)str_code = w01.__repr__()
# eval:将字符串作为python代码执行
w03 = eval(str_code)  # 克隆老婆对象
w01.name = "双双"
print(w03.name)  #

转换字符串

__str__函数:将对象转换为字符串(对人友好的)
__repr__函数:将对象转换为字符串(解释器可识别的)

运算符重载

定义:让自定义的类生成的对象(实例)能够使用运算符进行操作。
"""运算符重载
"""class Vector2:def __init__(self, x=0, y=0):self.x = xself.y = ydef __str__(self):return "向量的x分量为%d,y分量为%d" % (self.x, self.y)def __add__(self, other):return Vector2(self.x + other.x, self.y + other.y)def __iadd__(self, other):self.x += other.xself.y += other.yreturn self# 比较相同def __eq__(self, other):return self.x == other.x and self.y == other.y# 比较大小def __lt__(self, other):return self.x < other.xpos = Vector2(10, 25)
dir = Vector2(1, 0)
print(pos + dir)  # pos.__add__(dir)
pos += dir
print(pos)# list01 = [10]
# list01 += [20]# 在原有对象中添加新元素(在原有可变对象上修改)
# print(list01)  # [10, 20]
#
# list02 = [10]
# list02 = list02 + [20] # 创建了新对象
# print(list02)  # [10, 20]v01 = Vector2(100, 200)
v02 = Vector2(100, 200)
print(v01 == v02)  #
list_vectors = [Vector2(200, 200),Vector2(400, 400),Vector2(100, 100),Vector2(300, 300),Vector2(500, 500),
]
print(list_vectors.count(Vector2(100, 100)))
for item in sorted(list_vectors):print(item)

算数运算符

复合运算符重载

比较运算重载

设计原则

开-闭原则(目标、总的指导思想)

Open Closed Principle
对扩展开放,对修改关闭。
增加新功能,不改变原有代码。

类的单一职责(一个类的定义)

Single Responsibility Principle
一个类有且只有一个改变它的原因。

依赖倒置(依赖抽象)

Dependency Inversion Principle
客户端代码(调用的类)尽量依赖(使用)抽象。
抽象不应该依赖细节,细节应该依赖抽象。

组合复用原则(复用的最佳实践)

Composite Reuse Principle
如果仅仅为了代码复用优先选择组合复用,而非继承复用。
组合的耦合性相对继承低。

里氏替换(继承后的重写,指导继承的设计)

Liskov Substitution Principle
父类出现的地方可以被子类替换,在替换后依然保持原功能。
子类要拥有父类的所有功能。
子类在重写父类方法时,尽量选择扩展重写,防止改变了功能。
"""里氏替换
"""class Granade:def __init__(self, atk=0):self.atk = atkdef explode(self, target):print("手雷爆炸啦")target.damage(self.atk)class Target:def __init__(self, hp=0):self.hp = hpdef damage(self, value):self.hp -= value# ------------------------------------------
class Player(Target):def damage(self, value):super().damage(value)print("玩家受伤,屏幕碎屏")class Enemy(Target):def damage(self, value):super().damage(value)print("敌人受伤,掉下装备")g01 = Granade()
g01.explode(Player())
g01.explode(Enemy())

迪米特法则(类与类交互的原则)

Law of Demeter
不要和陌生人说话。
类与类交互时,在满足功能要求的基础上,传递的数据量越少越好。因为这样可能降低耦合度。
"""创建图形管理器记录所有图形提供计算所有图形总面积的功能圆形:pi * r ** 2矩形:l * w...要求:增加新图形,管理器不变.写出体现:三大特征封装:根据需求分为图形管理器、圆形、矩形.继承:创建图形类,隔离图形管理器与具体图形的变化多态:图形管理器计算面积时,调用图形,执行圆形、矩形计算方法。通过重写做计算面积方法设计原则开闭原则:增加新图形,图形管理器不变.依赖倒置:调用图形,不调用圆形、矩形."""
class GraphicManager:def __init__(self):self.__list_graphics = []def add_graphics(self, graphic):self.__list_graphics.append(graphic)def get_total_area(self):total_area = 0for item in self.__list_graphics:total_area += item.calculate_area()return total_areaclass Graphic:def calculate_area(self):pass# --------------------------
class Circle(Graphic):def __init__(self,r):self.r = rdef calculate_area(self):return 3.14 * self.r ** 2class Rectanle(Graphic):def __init__(self, l = 0,w = 0):self.l = lself.w = wdef calculate_area(self):return self.l * self.wmanager = GraphicManager()
manager.add_graphics(Circle(5))
manager.add_graphics(Rectanle(2,3))
print(manager.get_total_area())
"""多继承有多种变化需要隔离(不是代码复用)
"""class A:def func01(self):print("A -- func01")class B(A):def func01(self):print("B -- func01")class C(A):def func01(self):print("C -- func01")class D(C, B):def func01(self):print("D -- func01")# 1. 如何调用某一个同名方法B.func01(self)d = D()
d.func01()
# 2. 同名方法解析顺序
print(D.mro())
"""技能系统叙述三大特征:六大原则:
"""class ImpactEffect:"""影响效果,隔离技能释放器与具体效果(眩晕,降低速度...)"""def impact(self):passclass CostSPEffect(ImpactEffect):def __init__(self, value=0):self.value = valuedef impact(self):super().impact()print("消耗%d法力" % self.value)class DamageEffect(ImpactEffect):def __init__(self, value=0):self.value = valuedef impact(self):super().impact()print("伤害%d生命" % self.value)class LowerDeffenseEffect(ImpactEffect):def __init__(self, value=0, duration=0):self.value = valueself.duration = durationdef impact(self):super().impact()print("降低%f防御力,持续%d秒" % (self.value, self.duration))class SkillDeployer:"""技能释放器"""def __init__(self, name=""):self.name = nameself.__config_file = self.__load_config_file()self.__list_effects = self.__create_impact_effects()def __load_config_file(self):# 模拟配置文件读取后的数据结构return {"毁天灭地":["CostSPEffect(200)","DamageEffect(800)"],"降龙十八掌":["CostSPEffect(150)","DamageEffect(600)","LowerDeffenseEffect(0.5,10)"],}def __create_impact_effects(self):# 技能名称k ---> 效果名称列表vlist_effect_names = self.__config_file[ self.name ]# 创建子类对象()# list_effect_objects = []# for itme in list_effect_names:#     effect_obj = eval(itme)#     list_effect_objects.append(effect_obj)# return list_effect_objectsreturn [eval(itme) for itme in list_effect_names]def deploy_skill(self):print(self.name,"释放啦")for item in self.__list_effects:# 调用父类(影响效果)item.impact()xlsbz = SkillDeployer("降龙十八掌")
xlsbz.deploy_skill()
xlsbz.deploy_skill()
"""一家公司有如下几种岗位:程序员:底薪 + 项目分红测试员:底薪 + Bug * 5....创建员工管理器记录所有员工提供计算总工资的功能叙述:三大特征:封装:根据需求划分为员工管理器、程序员、测试员继承:创建员工类,隔离员工管理器与具体员工的变化多态:员工管理器调用员工,具体员工重写员工的计算薪资方法,添加具体员工对象(调父)             (重写)                 (创建子类对象)总结多态步骤:面对变化点,需要使用3步进行处理。价值(作用):程序灵活(扩展性强 = 开闭原则)六大原则:开闭原则:增加员工种类,员工管理器不变.单一职责:员工管理器:统一管理所有员工(薪资...)程序员:定义该员工的薪资算法(底薪 + 项目分红)测试员:定义该员工的薪资算法(底薪 + Bug * 5)依赖倒置:员工管理器调用员工,不调用程序员/测试员组合复用:员工管理器通过组合关系,使用各种员工的薪资算法.里氏替换:向员工管理器添加的是员工子类对象员工子类先调用员工类计算薪资方法返回底薪,再添加自己的薪资逻辑.迪米特:每个具体员工类之间低耦合员工管理器与具体员工之间低耦合"""class EmployeeManager:def __init__(self):self.__list_employees = []def add_employee(self, emp):self.__list_employees.append(emp)def get_total_salary(self):total_salary = 0for item in self.__list_employees:# 调用父类total_salary += item.calculate_salary()return total_salaryclass Employee:def __init__(self, base_salary=0):self.base_salary = base_salarydef calculate_salary(self):return self.base_salary# --------------------------
class Programmer(Employee):def __init__(self, base_salary=0, bonus=0):super().__init__(base_salary)self.bonus = bonus# 重写def calculate_salary(self):return super().calculate_salary() + self.bonusclass Tester(Employee):def __init__(self, base_salary=0, bug_count=0):super().__init__(base_salary)self.bug_count = bug_countdef calculate_salary(self):return super().calculate_salary() + self.bug_count * 5manager = EmployeeManager()
# 创建子类对象
manager.add_employee(Programmer(8000, 20000))
manager.add_employee(Tester(5000, 100))
print(manager.get_total_salary())
"""1. 创建技能对象,直接print到终端中。格式:xx技能的持续时间是xxx,攻击力是xxx,消耗法力是xxx.2. 克隆技能对象,修改其中一个对象变量,查看另外一个对象变量.
"""class Skill:def __init__(self, name="", duration=0, atk=0, cost_sp=0):self.name = nameself.duration = durationself.atk = atkself.cost_sp = cost_spdef __str__(self):return "%s技能的持续时间是%d,攻击力是%d,消耗法力是%d."%(self.name,self.duration,self.atk,self.cost_sp)def __repr__(self):return 'Skill("%s",%d,%d,%d)'%(self.name,self.duration,self.atk,self.cost_sp)s01 = Skill("降龙十八掌",50,500,600)
print(s01)s02 = eval(s01.__repr__())
s01.name = "降龙"
print(s02)
print(s01)

python基础笔记二_面向对象相关推荐

  1. Python基础笔记(二) List、tuple、循环语句

    一.List Python内置的一种数据类型是列表:list. list是一种有序的集合,可以随时添加和删除其中的元素.list是数学意义上的有序集合,也就是说,list中的元素是按照顺序排列的.构造 ...

  2. Python基础(二)完结

    今天分享又来了呀.ღ( ´・ᴗ・` ) 一起学习进步ღゝ◡╹)ノ♡ 关注公众号,回复"资料全集",不定期最新大数据业内资讯. ❤:在这里跟我一起学习技术.职场.人生.原理.健身.摄 ...

  3. Python 基础笔记

    Python 基础笔记 内置函数 print() 打印输出 type() 数据类型查询 isinstance() 判断数据是否是已知类型 input() 接受键盘输入 range() 函数 forma ...

  4. Python基础(二)--数据类型,运算符与流程控制

    目录 Python基础(二)--数据类型,运算符与流程控制 1 数据类型 1.1 Python中的数据类型 1.2 整数类型(int) 1.3 布尔类型 1.4 浮点类型 1.5 复数类型 1.6 类 ...

  5. Python基础 笔记(一) Python的介绍

    Python基础 笔记(一) Python的介绍 您好! 欢迎来到木易巷! 接下来,让我们一起来了解Python,走进Python~ 1.编程语言 编程语言(programming language) ...

  6. python学习笔记(二) 基本运算

    python学习笔记(二) 基本运算 1. 条件运算 基本语法 if condition1: do somethings1elif condition2: do somethings2else: do ...

  7. python 基础复习二

    这里写自定义目录标题 python 基础复习二 1.数据类型 2.数据的应用 3.数据的转换 总结 python 基础复习二 1.数据类型 最常用的数据类型有三种--字符串(str).整数(int)和 ...

  8. Python基础十五:面向对象编程四:高级特性

    Python基础十五:面向对象编程四:高级特性 Python基础系列内容为学习廖雪峰老师Python3教程的记录,廖雪峰老师官网地址:廖雪峰Python3教程 Author:yooongchun Em ...

  9. 廖雪峰Python基础练习(二)

    #廖雪峰Python基础练习(二)# 请利用Python内置的hex()函数把一个整数转换成十六进制表示的字符串: 答: # -*- coding: utf-8 -*-n1 = 255 n2 = 10 ...

最新文章

  1. 201621123068 作业08-集合
  2. LeetCode刷题-两数之和(持续更新)
  3. Qt C++中 Map 和 List 转换到 QML 中使用
  4. idea内置junit5_JUnit 5和Selenium –使用Selenium内置的`PageFactory`实现页面对象模式
  5. 立足优势,你的网站会更精彩
  6. 符江职高计算机教什么,高县符江职高具体地址
  7. 云网络的守护神:主动链路监控
  8. 大学计算机老师都是IT行业顶尖,却不做程序员,你知道为什么吗
  9. envi栅格TIF数据进行分割_常用水文气象数据读取及其可视化(二进制、HDF5、NetCDF)以GLDAS、MODIS、GSMaP为例...
  10. cisco独臂路由(即单臂路由)的配置
  11. 老司机心得之时间管理入坑
  12. Win7 环境下 IE8 升级到 IE11 后 F12 工具无法使用
  13. C语言-概念-文件指针
  14. WSL Ubuntu忘记root密码和用户密码
  15. 跨平台APP----对Cordova,APPCan,DCloud,APICloud四大平台的分析(系列二)
  16. pAdTy_3 构建地理位置和地图的应用程序
  17. UOS下使用HHDESK文本编辑功能
  18. 移动GPU渲染原理的流派——IMR、TBR及TBDR
  19. 实验---采用SOM网络进行聚类
  20. Mathematica中将多个动态图合并在一起(包括自动与手动)

热门文章

  1. 工控机在全自动洗车系统中的应用
  2. OpenCV学习笔记(5)_ ellipse绘制函数浅析
  3. 文旅夜游为城市高质量发展提供新动力
  4. 亚像元定位 硬分类 软分类
  5. 远程命令执行漏洞与远程代码执行漏洞33333
  6. 3D人脸重建:从基础知识到识别/重建方法!
  7. 阿里云国际站有什么优势吗?
  8. 2030年销售额突破200亿美元!瑞萨电子揭秘智能汽车版图
  9. C# 编写Windows Service(windows服务程序)(第二种)
  10. HiMobileCam SDK安装使用说明(Hi3559V200)(海思)