提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
面向对象基础
概述
1.面向过程:根据业务逻辑从上到下写垒代码
2.函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可
3.面向对象:对函数进行分类和封装,让开发“更快更好更强...”
面向过程编程(Object Oriented Programming,OOP,面向对象程序设计) 最易被初学者接受,
其往往用一长段代码来实现指定功能,开发过程中最常见的操作就是粘贴复制,即:将之前实现的代码块复制到现需功能处。
创建对象和类
面向对象编程是一种编程方式,此编程方式的落地需要使用 “类” 和 “对象” 来实现,所以,面向对象编程其实就是对 “类” 和 “对象” 的使用。
类就是一个模板,模板里可以包含多个函数,函数里实现一些功能
对象则是根据模板创建的实例,通过实例对象可以执行类中的函数
# 创建类
class Foo:
def Bar(self):
print 'Bar'
def Hello(self, name):
print 'i am %s' %name
# 根据类Foo创建对象obj
obj = Foo() # 实例化一个对象
obj.Bar() # 执行Bar方法
obj.Hello('wupeiqi') # 执行Hello方法
类的三种定义方式
class MyClass:
pass
class MyClass(): #(推荐)
pass
class MyClass(object): # object类是所有类的父类
pass
类的实例化
class MyCar():
color = "黄色的"
# 实例化对象 (类的实例化)
obj = MyCar()
类的基本结构
类的基本结构包括成员属性和成员方法
"""
1.成员属性
2.成员方法
"""
class MyCar():
# 成员属性
color = "天蓝色的"
# 成员方法
def didi():
print("小车会滴滴叫")
注意:在类中不能写逻辑语句或循环语句
这种写法可以直接在python当中执行,但是严禁使用.
如果想要表达逻辑或者循环,
需要写在成员方法当中,不能直接裸露的写在类当中,会破坏类中结构.
class MyCar():
if 5 == 5:
print("打印成功123456")
面向对象之封装
概念
封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问。
要访问该类的代码和数据,必须通过严格的接口控制。
封装最主要的功能在于我们能修改自己的实现代码,而不用修改那些调用我们代码的程序片段。
适当的封装可以让程式码更容易理解与维护,也加强了代码数据的安全性。
封装等级:
(1) 私有 : 在类的内部可以访问,在类外不可以访问
(2) 公有 : 在类的内部可以访问,在类外也可以访问
封装成员:
(1) 成员属性
(2) 成员方法
调用成员:
(1) 对象.成员属性
(2) 对象.成员方法
绑定方法:
(1) 绑定到对象 : 对象调用方法时,系统自己默认传递该对象,作为一个参数传递到当前方法中
(2) 绑定到类 : 对象或者类调用方法时,系统自己默认传递该类,作为一个参数传递到当前方法中
封装之对象的相关操作
定义一个MyCar类,并定义公有/私有成员属性和公有/私有成员方法
class MyCar():
# 公有成员属性
color = "屎黄色"
logo = "中国吉利汽车"
# 私有成员属性
__price = "2000万"
# 公有成员方法
def run(self):
print("小车会跑,百公里0.01秒,颜色{}".format(self.color)) # self <=> obj
# 私有成员方法
def __info(self):
print("车主信息是保密的,传说是京城有名的富二代")
# 实例化对象(类的实例化)
obj = MyCar()
实例化的对象访问公有成员属性和方法
# 访问属性
print(obj.color)
# obj.__price error # 私有成员属性不能够在类外调用
# 访问方法
obj.run()
# obj.__info() error # 私有成员方法不能够在类外调用
实例化的对象动态添加公有成员属性和方法
1.在类外动态添加成员属性–>通过obj对象
# 可以在类外通过对象.属性为对象添加属性
obj.logo = "五菱宏光"
print(obj.logo)
如果想确认obj对象中是否有你新添加的logo属性,可以使用对象.__dict__获取类对象中的成员
2.在类外动态添加成员方法–>通过obj对象
在类外动态添加成员方法,可分为无参方法和有参方法
# 1.无参方法
def dahuangfeng():
print("变形! 我是大黄蜂~")
obj.dahuangfeng = dahuangfeng
obj.dahuangfeng()
# 2.有参方法
# 2.1 基础版
def qingtianzhu(name):
print("请我叫我一柱擎天,简称{}".format(name))
obj.qingtianzhu = qingtianzhu
obj.qingtianzhu("擎天柱")
# 2.2 升级版
def qingtianzhu(obj,name):
print("请我叫我一柱擎天,简称{},颜色是{}".format(name,obj.color))
obj.qingtianzhu = qingtianzhu
obj.qingtianzhu(obj,"擎天柱")
# 2.3 究极版 (即使调用类外动态创建的方法,也让系统自己传递obj对象本身)
'''在类外调用自定义方法时,系统不会自动传递obj对象参数'''
import types
def qingtianzhu(obj,name):
print("请我叫我一柱擎天,简称{},颜色是{}".format(name,obj.color))
# MethodType(方法,对象) 把哪个方法和哪个对象绑定到一起,形成绑定方法
obj.qingtianzhu = types.MethodType(qingtianzhu,obj)
obj.qingtianzhu("擎天柱")
也可以使用lambda表达式实现在类外添加方法
obj.weizhentian = lambda : print("我是威震天~ ")
obj.weizhentian()
封装之类的相关操作
类调用的方式也是两种:类.成员属性和类.成员方法
但是需要注意的是:类中的无参方法只能由类来调用!!
定义一个MyCar类,并定义其公私有属性和方法
class MyCar():
# 公有属性
oil = "2.0T"
# 私有属性
__price = "5000千万"
# 公有方法
def oil_info():
print("百公里油耗是500升",MyCar.color)
# 私有方法
def __price_info():
print("我的油耗信息是保密的")
# 对象不能调用类中无参的方法
obj = MyCar()
# obj.oil_info() # 请注意!!!对象不能调用类中无参的方法 会报错
MyCar.color = '布加迪威龙'
MyCar.oil_info() # 无参方法只能由类来调用
'''
注意:对象不能调用类中无参的方法!!
原因:对象在调用方法时,会默认将obj对象作为参数传到类中的无参的方法,进而导致参数数量不一致
'''
定义的类访问公有成员和属性
# 访问公有成员属性
print(MyCar.oil)
# MyCar.__price error # 无法在类外访问私有成员属性
# 访问公有成员方法
MyCar.oil_info()
# MyCar.__price_info() error # 无法在类外访问私有成员方法
定义的类动态添加公有成员和属性
1.添加成员属性
MyCar.color = "红色"
print(MyCar.color)
# 查看类对象内部成员使用__dict__,返回的是字典
print(MyCar.__dict__)
2.添加成员方法
# 1.无参方法
def fangxiangpan():
print("改造方向盘的方法")
MyCar.fangxiangpan = fangxiangpan
MyCar.fangxiangpan()
print(MyCar.__dict__)
# 2.有参方法
def fadongji(engin):
print("动力引擎改成{}".format(engin))
MyCar.fadongji = fadongji
MyCar.fadongji("三缸发动机")
# 3.lambda 表达式
MyCar.luntai = lambda name : print("使用{}的轮胎".format(name))
MyCar.luntai("米其林")
print(MyCar.__dict__)
类和对象之间的差别
1.对象可以调用类中的成员属性和方法,返过来,类不能调用对象中的成员方法.
2.类中的成员属性和方法归属于类本身,对象可以使用,但是没有修改和删除的权利.
3.对象在调用相应成员时,先看看自己有没有
如果有,调用自己的
如果没有,调用类中的成员
如果类中成员也没有,直接报错
如何访问类中的私有成员
定义Plane类,并创建如下属性和方法
class Plane():
# 公有属性
captain = "Mike"
# 私有属性
__sistem = 10
# 公有绑定方法
def fly1(self):
print("我的飞机可以倒着飞1")
# 公有普通方法
def fly2():
print("我的飞机可以倒着飞2")
# 私有绑定方法
def __fly_info1(self):
print("我的飞机,百公里油耗是5万升1")
# 私有普通方法
def __fly_info2():
print("我的飞机,百公里油耗是5万升2")
# 公有绑定方法->间接调用私有成员
def pub_info1(self):
print(self.__sistem)
self.__fly_info1()
# 公有普通方法->间接调用私有成员
def pub_info2():
print(Plane.__sistem)
Plane.__fly_info2()
关于实现python私有化,有两种方法:
方法一:
'''
关于python私有化的实现方法: 改名策略
_类名 + 私有成员 => 改名策略
'''
# 方法一.调用私有成员 (不推荐使用改名策略找到私有成员,破坏封装性)
# 对象调用类中的私有成员
obj = Plane()
print(obj._Plane__sistem)
obj._Plane__fly_info1()
# 类调用类中的私有成员
print(Plane._Plane__sistem)
Plane._Plane__fly_info2()
print(Plane.__dict__)
方法二:
# 方法二.类或对象利用公有方法,间接找到私有成员(推荐)
# 公有绑定方法->间接调用私有成员
def pub_info1(self):
print(self.__sistem)
self.__fly_info1()
# 公有普通方法->间接调用私有成员
def pub_info2():
print(Plane.__sistem)
Plane.__fly_info2()
obj.pub_info1()
Plane.pub_info2()
"""
针对于这个方法,我们可以在类中定义公有绑定方法和公有普通方法间接调用私有成员
"""
实例化的对象/定义的类删除公有成员属性和公有成员方法
# 1.公有成员属性
# 对当前对象添加成员属性交captain
obj.captain = "王浩"
# 删除当前对象中的成员属性captain
del obj.captain
# 删除类当中的成员属性captain
del Plane.captain
print(obj.captain) # error 无论是类还是对象都没有改属性,所以报错;
# 2.公有成员方法
Plane.add_sistem = lambda self: print("因为业务需要,需要增加乘务员")
Plane.add_sistem(1)
obj.add_sistem()
# 删除类中的成员方法
del Plane.add_sistem
obj.add_sistem() # error 发现被删找不到了
obj.chaixie = lambda : print("我的飞机可以用来拆卸")
obj.chaixie()
# 删除对象中的成员方法
del obj.chaixie
obj.chaixie() # error
面向对象之继承
概念
1.什么是子类?什么是父类?如果一个类继承另外一个类,该类叫做子类(衍生类),被继承的类叫做父类(基类,超类)
2.继承的种类:1.单继承 2.多继承
3.object类:在python中,所有的类都默认继承父类object
单继承
定义一个Human类,并定义一些属性和方法:
class Human(object):
hair = "黑色"
sex = "男"
def cry(self):
print("人类会哭")
def eat(self):
print("人类会吃东西")
def __makebaby(self):
print("人类会繁衍生息")
# 1.子父继承之后,子类可以调用父类的公有成员
class Man(Human): # 定义Man类,继承Human类
pass
obj = Man()
print(obj.hair) # 子类Man直接调用父类的hair属性
obj.cry() # 子类Man直接调用父类的cry方法
# 2.子父继承之后,子类不能调用父类的私有成员
class Woman(Human):
def pub_func(self):
self.__makebaby()
obj = Woman()
obj.__makebaby() # error 子类无法直接调用父类的私有成员
obj.pub_func() # error 即使在子类定义pub_func用来存放私有成员,那也是父类的私有成员,而非子类的
子父继承之后,子类可以改写父类中的方法
1.如果子类里面有该成员属性或者方法,优先调用自己的
2.如果子类没有该成员,则调用父类中的成员
3.如果子类父类都没有该成员,则直接报错
class Children():
sex = "女"
def cry(self):
print("小孩会哇哇哇哭")
obj = Children()
obj.cry() # 子类有cry方法,优先使用子类的
多继承
多继承的基本语法
# 1.基本语法
class Father():
property = "爸爸英姿飒爽"
def f_hobby(self):
print("爸爸喜欢抽烟")
class Mother():
property = "妈妈倾国倾城"
def m_hobby(self):
print("妈妈喜欢打麻将")
class Daughter(Father,Mother): # Daughter类继承Father类和Mother类
pass
# 实例化对象
obj = Daughter()
print(obj.property) # 优先会继承Father类的property
obj.m_hobby() # 妈妈喜欢打麻将
super用法
class Father():
property = "爸爸靓仔"
def f_hobby():
print("爸爸喜欢美女")
class Mother():
property = "妈妈靓女"
def m_hobby(self):
print(self.property)
print("妈妈喜欢帅哥")
"""
(1)super本身是一个类 super()是一个对象 用于调用父类的绑定方法
(2)super() 只应用在绑定方法中,默认自动传递self对象 (前提:super所在作用域存在self)
(3)super用途: 解决复杂的多继承调用顺序
"""
class Son(Father,Mother):
property = "儿子喜欢钱"
def m_hobby(self):
print("son中m_hobby方法")
# 用类调用成员
def skill1(self):
Father.f_hobby()
print(Mother.property)
# 用对象调用成员
"""self按照顺序找: 对象本身 => 类 => 父类 对应的成员 """
def skill2(self):
print(self.property)
self.m_hobby()
# 用super调用成员
"""super()只调用父类的相关成员,顺带传递对象参数"""
def skill3(self):
print(super())
print(super().property)
super().m_hobby()
obj2 = Son()
# obj2.skill1()
obj2.property = "儿子喜欢玩小鸟"
# obj2.skill2()
obj2.skill3()
self和super的区别
self在调用成员时,先看看自己的类对象是否存在该成员
1.如果有调用自己的.
2.如果子类自己没有,调用父类的
3.如果子类和父类都没有,则直接报错
super()在调用成员时,只调用父类的相关成员(属性,绑定方法)
永远不会调用自己的,如果父类没有,直接报错
菱形继承(钻石继承)
class OldWoman():
pass
class Human():
pty = 1
def feelT(self):
print("古代人类,天热了,跳水1")
print(self.pty)
print("古代人类,天冷了,钻木取火2")
class Man(Human):
# pty = 2
def feelT(self):
print("男人,天热了,光膀子3")
print(super(),"<==2==>")
super().feelT()
print("男人,天冷了,冻死4")
class Woman(Human):
# pty = 3
def feelT(self):
print("女人,天热了,脱皮5")
print(super(),"<==3==>")
super().feelT()
print("女人,天冷了,增脂肪6")
class Children(Man,Woman):
# pty = 4
def feelT(self):
print("小孩,天热了,光腚7")
print(super(),"<==1==>")
super().feelT()
print("小孩,天冷了,多喝热水8")
# ### super的深层理解
obj = Children()
obj.feelT()
# 执行顺序73512648
代码解析
执行顺序是73512648,super()只调用父类,继承顺序Children->Father->Mother->Human
执行完毕之后还需要将每个类中的feelT方法中剩余的代码执行完
整个代码的执行顺序像递归中"一来一回"的过程
mro列表:返回调用顺序列表
mro列表:super用途的一个体现,解决复杂的多继承调用顺序关系
类.mro() 返回的是方法调用顺序列表,针对于多继承下的同名方法,按照顺序依次的进行调用
lst = Children.mro()
print(lst)
"""
[
<class '__main__.Children'>,
<class '__main__.Man'>,
<class '__main__.Woman'>,
<class '__main__.Human'>,
<class 'object'>
]
"""
issubclass 判断子父关系 (应用在类当中,判断子父关系)
# issubclass 判断子父关系 (应用在类当中,判断子父关系)
"""只要在一条继承链上即可(有血缘关系)"""
res = issubclass(Children,Man)
print(res)
res = issubclass(Children,Woman)
print(res)
res = issubclass(Children,Human)
print(res)
res = issubclass(Children,(Human,Woman,Man,OldWoman))
print(res)
res = issubclass(Children,OldWoman)
print(res)
isinstance (应用在对象和类之间,判断类型)
# isinstance(应用在对象和类之间,判断类型)
"""只要在一条继承链上即可(有血缘关系)"""
res = isinstance(obj,Children) # True
res = isinstance(obj,Human) # True
res = isinstance(obj,(Human,Children,Woman)) # True
res = isinstance(obj,OldWoman) # False
面向对象之多态
概念
什么是多态?
不同的子类对象,调用相同的父类方法,产生不同的执行结果
多态的关键字:继承和改写
多态例子
# 定义Soldier类,让空军陆军海军继承这个类
class Soldier():
def attack(self):
pass
def back(self):
pass
# 陆军
class Army(Soldier):
def attack(self):
print("[陆军]搏击,ufc,无限制格斗,太极,八卦,占星,制作八卦符")
def back(self):
print("[陆军]白天晨跑10公里,也行800百公里")
# 海军
class Navy(Soldier):
def attack(self):
print("[海军]潜泳水下30个小时,手捧鱼雷,亲自送到敌人的老挝,炸掉敌人的碉堡")
def back(self):
print("[海军]每小时在海底夜行800公里,游的比鲨鱼还快")
# 空军
class AirForce(Soldier):
def attack(self):
print("[空军]空中夺导弹,手撕飞机,在空中打飞机,精准弹幕")
def back(self):
print("[空军]高中跳伞,落地成盒")
# 实例化陆军对象
army_obj = Army()
# 实例化海军对象
navy_obj = Navy()
# 实例化空军对象
af_obj = AirForce()
lst = [army_obj,navy_obj,af_obj] # 对象列表
strvar = """
1.所有兵种开始攻击训练
2.所有兵种开始撤退训练
3.空军练习攻击,其他兵种练习撤退
"""
print(strvar)
num = input("将军请下令,选择训练的种类")
for i in lst:
if num == "1":
i.attack()
elif num == "2":
i.back()
elif num == "3":
if isinstance(i,AirForce):
i.attack()
else:
i.back()
else:
print("将军~ 风太大 我听不见~")
break