Python面向对象oop编程(二)

文章目录

Hello,大家好,我是你们的老朋友景天,上一章我们聊到了python的面相对象编程的语法,以及一些面相对象的基本操作,今天我们继续深入探讨下面向对象的其他一些常用方法和规范

1.如何在类外访问私有成员

class Plane():
    # 公有成员
    captian = "赵沈阳"

# 私有成员
__air_sister = “3名空姐”

# 公有绑定方法
def fly(self):
print(“飞机要非要平流层,才能减少震动”,self.__air_sister)

# 私有绑定方法
def __age(self):
print(“空姐年龄保密”)

# 公有无参方法
def fly2():
print(“航天飞机飞到天空层,翱翔太空”)

# 私有无参方法
def __earn():
print(“机长的收入保密”)

def pub_get1(self):
print(self.__air_sister)
self.__age()

def pub_get2():
print(Plane.__air_sister)
Plane.__earn()

#实例化对象
obj = Plane()

运行
运行

方法一.访问私有成员 (不推荐) 使用改名方法,_类名+私有属性名

#python私有化,其实是: 采取了改名策略 =>  _类名 + __air_sister
#print(obj.__air_sister)
print(obj._Plane__air_sister)
print(Plane.__dict__)

{ module: main, ‘captian’: ‘赵沈阳’,
‘_Plane__air_sister’: ‘3名空姐’,
‘fly’: <function Plane.fly at 0x7f2774616158>, ‘_Plane__age’: <function Plane.__age at 0x7f27746161e0>, ‘fly2’: <function Plane.fly2 at 0x7f2774616268>, ‘_Plane__earn’: <function Plane.__earn at 0x7f27746162f0>, dict: <attribute dict of ‘Plane’ objects>, weakref: <attribute weakref of ‘Plane’ objects>, doc: None}

在这里插入图片描述

方法二.访问私有成员 (使用类中的公有方法,间接访问私有成员,包括调用私有属性和私有方法) (推荐)

obj = Plane()
obj.pub_get1()
Plane.pub_get2()

 
 

在这里插入图片描述
在这里插入图片描述

2.使用类对象删除相应的成员

1.对象可以访问类中的公有成员,但是无权修改或者删除该类中的成员
2.对象在访问成员时,优先访问该对象自己的成员,如果没有在访问类的,类如果也没有直接报错;

使用对象删除类的属性,方法,报错
在这里插入图片描述
在这里插入图片描述

#删除对象成员属性,但可以删除对象自己添加,修改的属性,方法

obj.captian = "赵世超"
del obj.captian
print(obj.captian)

 
 

在这里插入图片描述

#删除对象成员方法

obj.basketball = lambda : print("我的私人飞机可以在天上打篮球")
print(obj.__dict__)
obj.basketball()
del obj.basketball
print(obj.__dict__)
#obj.basketball() error

 
 

在这里插入图片描述

#删除类中成员属性 要通过类来删除

del Plane.captian
print(Plane.__dict__)
#Plane.captian
#print(obj.captian) error

 
 

在这里插入图片描述

#删除类中成员方法,删除类成员方法 不能加括号

del Plane.fly2
#Plane.fly2() error

 
 

#注意: 对象无法调无参方法!! 返回来,类可以调用对象的绑定方法么? 可以!!

Plane.fly(obj)

 
 

#类调用有参方法,要把类对象传进去
在这里插入图片描述

要删除私有的属性,方法。要在类内里面删除

3.构造方法

(1)init 构造方法 也就是初始化方法

所有编程语言都有构造方法

触发时机:实例化对象,初始化的时候触发
功能:为对象添加成员
参数:参数不固定,至少一个self参数
返回值:无

 
 

一般添加成员方法都是在类外,构造方法可以在创建对象的同时给对象创建成员

(2) 基本语法,至少加一个参数,本对象

class MyClass():
    def __init__(self):
        print("构造方法被触发 ... ")
        self.color = "屎黄色"

#实例化对象
obj = MyClass()
print(obj.dict)
print(obj.color)

运行
运行

如果定义了构造方法,则实例化对象的时候,该方法就会被调用。执行该方法的代码,可以为对象添加成员属性。只是给对象添加成员,并没有给类添加成员
只要创建对象,构造方法就被自动调用。 不是手动调用的

可以看到test对象被自动添加了color成员,并且__init__方法里面的代码也被自动执行
在这里插入图片描述
在这里插入图片描述

现在构造函数是把所有创建的对象都添加了color:蓝色 这个属性,并不是我们想要的结果。
此时就需要让构造函数带多个参数。创建对象时,可以带上参数,这样每个对象 都可以按传参不同而成员不同

(3) 带有多个参数的构造方法

class MyClass():
    def __init__(self,color):
        self.color = color

# 实例化对象
obj1 = MyClass(“狗屎绿”)
print(obj1.color)
obj2 = MyClass(“粉嫩红”)
print(obj2.color)

运行
运行

设置成员属性时,self.设置的成员属性名 = 传参传进来的值
这样就给对象添加了成员
在这里插入图片描述
在这里插入图片描述

这样,针对不同对象,就可以通过传参赋予不同的属性值

(3)类可以是一个,对象可以是多个,创造的对象彼此是独立的,可以给构造函数带多个参数,分别赋予不同的值;

class Children():
    def __init__(self,name,skin):
        self.name = name
        self.skin = skin

def cry(self):
print(“小孩一下生久哇哇哇的哭”)

def la(self):
print(“小孩一下生久拉粑粑”)

def __eat(self):
print(“小孩一下生就要吃奶奶…”)

#这种成员方法,通过self.参数名 调用对象属性,创建对象的时候可通过类传参,对象调用的时候,通过对象传参,不用手动传参
def info(self):
print(“小孩的名字:{},小孩的肤色{}”.format(self.name,self.skin))

#这种成员方法,直接调用参数名 对象调用该成员方法的时候,需要手动传参 。可以覆盖构造函数在创建对象时的值
def info2(self,name,skin):
print(“小孩的名字:{},小孩的肤色{}”.format(name,skin))

运行
运行

#实例化对象

afanda = Children("阿凡达","深蓝色")
afanda.cry()
afanda.info()

haoke = Children(“绿巨人”,“绿色的”)
haoke.la()
haoke.info()

wangbaoqiang = Children(“王宝强”,“亮绿色”)
wangbaoqiang.info()
# wangbaoqiang.__eat() error
wangbaoqiang.info2(“张保张”,“黄色”)

构造函数除了self外有几个参数,创建对象的时候,就必须带几个参数,不能少也不能多。否则创建对象失败
在这里插入图片描述

不能少参数
在这里插入图片描述
在这里插入图片描述

也不能多
在这里插入图片描述

在这里插入图片描述

成员方法带参数时,调用成员方法应该带参数
当成员方法里面是通过self.属性名 时,是通过对象来传参,调用函数时,传的参不会传进去
成员方法
在这里插入图片描述

调用:
在这里插入图片描述

当成员方法直接通过变量名来调用,调用时传参,会把创建对象时的参数覆盖
在这里插入图片描述

在这里插入图片描述

#这种成员方法,通过变量名调用参数。此时的参数是成员方法的形参,不是类或对象的成员属性
对象调用的时候,需要手动传参,会把创建对象时的参数覆盖。 但是这样调用比较麻烦,应该让对象来操作一切
在这里插入图片描述

4.继承

一个类除了自身所拥有的属性方法之外,还获取了另外一个类的成员属性和方法 是一种继承关系
被继承的类叫做父类(基类,超类),继承的类叫做子类(衍生类)
在python中所有类都继承object这个父类
继承: (1) 单继承 (2) 多继承
子类继承父类所有的属性和方法
节省了代码量

不由任意内置类型派生的类,称之为经典类
class 类名:
代码

新式类:

class 类名(object):
代码

Python面向对象的继承指的是多个类之间的从属关系,即子类默认继承父类所有的属性和方法
如果一个类不去写继承哪个类,默认继承的是object, object类是顶级类或基类。其他子类叫派生类

1.单继承

(1) 子父继承之后,子类可以调用父类的公有成员
class Human(object):
    eye = "黑色的"

def jump(self):
print(“古代人类都能上树”)

def beat_animal(self):
print(“古代人类都会打猎”)

def __makefire(self):
print(“古代人类会生火”)

class Man(Human):
pass

obj = Man()
obj.jump()

运行
运行

在这里插入图片描述

(2) 子父继承之后,子类不能调用父类的私有成员
class Woman(Human):
    def pub_func(self):
        self.__makefire()

obj2 = Woman()
# obj2.__makefire() 不行
# obj2.pub_func() 不行

在这里插入图片描述
在这里插入图片描述

(3) 子父继承之后,子类可以重写父类的同名公有方法和属性
class Children(Human):
    def beat_animal(self):
        print("小孩天生只会打豆豆,不会打猎")

obj3 = Children()
obj3.beat_animal()

在这里插入图片描述

2.多继承

多继承就是一个类同时继承了多个父类
当一个类继承多个父类的时候,默认使用第一个父类的同名属性和方法

(1) 基本语法
class Father():
    property = "风流倜傥,才华横溢,玉树临风,才高八斗,学富五车,英姿洒窗"
    def f_hobby(self):
        print("吃喝嫖赌抽,坑蒙拐骗偷,抽烟喝酒烫头")

class Mother():
property = “倾国倾城,貌美如花,沉鱼落雁,闭月羞花,婀娜多姿,前凸后翘”
def m_hobby(self):
print(“蹦野迪,社会摇,打麻将,网红勾引小鲜肉”)

class Daughter(Father,Mother):
pass

obj = Daughter()
print(obj.property)
obj.m_hobby()

运行
运行

#当一个类继承多个父类的时候,默认使用第一个父类的同名属性和方法。按继承括号里面的先后顺序,谁在前先调用谁的
在这里插入图片描述

(2) 多继承的成员调用
class Father():
    property = "风流倜傥,才华横溢,玉树临风,才高八斗,学富五车,英姿洒窗"
    def f_hobby():
        print("吃喝嫖赌抽,坑蒙拐骗偷,抽烟喝酒烫头")

class Mother():
property = “倾国倾城,貌美如花,沉鱼落雁,闭月羞花,婀娜多姿,前凸后翘”
def m_hobby(self):
print(self.property)
print(“蹦野迪,社会摇,打麻将,网红勾引小鲜肉”)

super()调用父类方法:

语法一:super(当前类名, self).函数()

语法二:super().函数()

(1)super本身是一个类 super()是一个对象 传子类对象 用于调用父类的绑定方法
(2)super() 只应用在绑定方法中,默认自动传递self对象 (前提:super所在作用域存在self)
(3)super用途: 解决复杂的多继承调用顺序
使用super()可以自动查找父类。调用的顺序遵循类.mro()方法返回的的列表顺序。比较适合单继承

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 = "喜欢看lol,dnf,wow,跑跑卡丁车,ddo,霸王大陆,澄海3c"
# obj2.skill2()

obj2.skill3()

即便在子类中存在同名方法或属性,也不调用。只调用父类方法和属性
在这里插入图片描述

在这里插入图片描述

super() 只应用在绑定方法中,默认自动传递self对象 (前提:super所在作用域存在self)
如果调用非绑定方法,会报错

f_hobby()方法非绑定方法
在这里插入图片描述

通过super()调用报错
在这里插入图片描述

通过super调用父类方法,是把子类对象传过去,执行,如果方法中调用对象成员属性,则调用的是子类成员属性

在这里插入图片描述
在这里插入图片描述

(3).菱形继承 (钻石继承) super深度理解

“”"
Human
Man Woman
Children
“”"
在这里插入图片描述

四个类中都有同名方法,该怎么调

class MyClass():
    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

运行
运行

super调用顺序

#mro: 方法解析顺序 (c3算法计算的)
#语法: 类.mro() => 列表
m :method
r :resolution
o :order
super 会自动根据mro列表返回出来的顺序关系,依次调用
super作用:专门用于解决复杂的多继承调用顺序关系;依照mro返回的列表顺序,依次调用;
super调用的顺序:会按照c3算法的广度优先原则进行调用
super传参:会默认在调用方法时,传递该对象参数;
在这里插入图片描述

lst = Children.mro()
print(lst)

[
<class main.Children’>,
<class main.Man’>,
<class main.Woman’>,
<class main.Human’>,
<class ‘object’>
]

根据 类.mro方法返回的列表顺序,来调用。遇到super().feelT()暂停,查找下一个调用
在这里插入图片描述

当不确定调用顺序时,可以打印下这个列表,来确认

# ### issubclass与isinstance
# issubclass 判断类的子父关系(应用在类与类之间) 第一个参数是子,第二个参数是父  是父子关系返回True,非父子关系返回False
"""只要在一条继承链上满足关系即可"""
res = issubclass(Children,Man)
res = issubclass(Children,Human)
res = issubclass(Children,MyClass)
# 如果元组当中有一个父类满足,即返回真
res = issubclass(Children,  (Man,Human,MyClass)  )
print(res)

 
 

在这里插入图片描述

# isinstance 判断对象的类型  (应用在类与对象之间)  第一个参数是对象,第二个参数是类
"""只要在一条继承链上满足关系即可"""
res = isinstance(obj,Children)
res = isinstance(obj,Human)
res = isinstance(obj,MyClass)
# 如果元组当中有一个类满足,即返回真
res = isinstance(obj,  (Man,Human,MyClass)  )
print(res)

 
 

#该对象只要是该类,或者该类的子类创建的,返回的都是True
在这里插入图片描述

(4).多继的承弊端

多继承的弊端会造成菱形继承这种情况,找不清调用顺序
super对象按照mro列表的顺序依次调用,解决菱形继承存在的问题

经典类:深度优先 (python2.x)
新式类:广度优先 (python3.x)

写多继承时,尽量避免造成不同类相同方法名的情况,提高代码质量 高内聚,低耦合
高内聚:一个模块只完成一个任务,专一性高
低耦合:模块与模块之间可以彼此独立不冲突,方便移植复用.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值