Python基础学习(十一)--封装(私有化),继承,覆写,super(),多继承、钻石继承,多态,实例/类/静态方法

一、封装特性

(一)什么是封装

封装是将类中的某些部分隐藏起来,对象不能直接使用隐藏起来的属性或者方法,具有保护功能。

(二)私有属性

形如:__变量名,在类的外部不能使用(对象也不行)

class Girl():
    def __init__(self,name,age):
        self.name=name
        self.__age=age
    def show(self):
        print(self.name,self.__age)
zs=Girl('张三',18)
zs.show()
print(zs.name)
print(zs.__age)    #  报错 'Girl' object has no attribute '__age'

(三)私有化封装后的限制

实例:使用getXX()和setXX()方法来判断age属性的值是否为负数

class Girl():
    def __init__(self):
        pass
    def setAge(self,age):
        if age<0 or age>95:
            print('错误')
            self.age=0
        else:
            self.age=age
    def getAge(self):
        return self.age
zs=Girl()
zs.setAge(20)
print(zs.getAge())    # 20

zs.age=-9
print(zs.getAge())    # -9

zs.setAge(200)
print(zs.getAge())    # 0

这时就可以发现,可以通过对象在类外对之前的值进行覆盖,这就导致失去了setXX()中判断负数的意义。

这时候,就可以用私有属性来解决这个问题,代码如下:

class Girl():
    def __init__(self,name,age):
        self.name=name
        self.__age=age
    def setAge(self,age):
        if age<0 or age>95:
            print('错误')
            self.__age=0
        else:
            self.__age=age
    def getAge(self):
        return self.__age
zs=Girl('张三',18)
zs.setAge(21)
print(zs.getAge())    # 21
print(zs.__dict__)    # {'name': '张三', '_Girl__age': 21}

# 之前的值没有被覆盖
zs.__age=99
print(zs.getAge())    # 21
print(zs.__dict__)    # {'name': '张三', '_Girl__age': 21, '__age': 99}

代码中,类外部的zs.__age=99中,__age不是类中的那个私有变量__age,而是另一个新的变量。

print(zs.__dict__)中,'_Girl__age:21'才是类中那个私有变量。

若想在类外对私有变量进行操作,可以使用_类名__变量名。知道有这种操作就可以,不支持这样使用:

class A():
    def __init__(self,age):
        self.__age=age
    def setAge(self,age):
        self.__age=age
    def __str__(self):
        return str(self.__age)
a=A(1)
a.__age=100
print(a.__dict__)
print(a._A__age)
a._A__age=99
print(a.__dict__)

结果:
{'_A__age': 1, '__age': 100}
1
{'_A__age': 99, '__age': 100}

(四)私有方法

形如:__方法名,在类外部不能使用

作用:在开发的过程中保护核心代码

class Phone():
    def test(self):
        print('test1')
    def __test1(self):
        print('test1')
x=Phone()
x.test()

# 私有方法,无法调用
x.__test1()    # 报错

私有方法在类中使用:

class Phone():
    def __phone(self):
        print('正在拨打电话')
    def phone(self,m):
        if m >=30:
            self.__phone()
        else:
            print('请先交费30元,再打电话')
x=Phone()
x.phone(36)    # 正在拨打电话

二、继承特性

(一)什么是继承

继承就是让类和类之间产生父子关系,子类可以拥有父类的静态属性和方法。

一个类可以继承一个或多个类,父类又可称为基类或超类,新建的类称为派生类或子类。

python中的继承分为:单继承和多继承

(二)继承的作用

提高代码的重用率

class Animal():
    def __init__(self,name,age,sex):
        self.name=name
        self.age=age
        self.sex=sex
    def jiao(self):
        print(self.name+'叫')
    def eat(self):
        print(self.name+'吃')

class Cat(Animal):
    def climb(self):
        print(self.name+'爬树')

class Dog(Animal):
    def swimming(self):
        print(self.name+'游泳')

d=Dog('藏獒',7,'公')
d.eat()
d.jiao()
d.swimming()
c=Cat('波斯猫',4,'母')
c.eat()
c.jiao()
c.climb()

(三)查看继承的父类

print(Cat.__bases__)    # (<class '__main__.Animal'>,)
print(Animal.__bases__)    # (<class 'object'>,)

(四)方法的覆写

子类中定义了和父类中相同的方法,我们叫做方法的复写(派生方法)。


class A():
    def hehe(self):
        print('A:呵呵')
class B(A):
    def hehe(self):
        print('B:呵呵')
a=A()
b=B()
a.hehe()    # A:呵呵
b.hehe()    # B:呵呵

(五)super()

子类和父类中有相同的方法,如果子类想调用父类的相同方法,可以使用super()方法。

class Animal():
    def __init__(self,name,age):
        self.name=name
        self.age=age
class Cat(Animal):
    def __init__(self,name,age,velocity):
        self.v=velocity
        super().__init__(name,age)
    def jiao(self):
        print('喵喵喵,速度{}'.format(self.v))
class Dog(Animal):
    def jiao(self):
        print('汪汪汪')
c=Cat('波斯',3,200)
d=Dog('京巴',4)
c.jiao()
d.jiao()

super()还可以从外部使用,需要传递类名(本类)和对象名

class A():
    num=3
    __num1=2
    def __init__(self,x,y):
        self.x=x
        self.y=y
class B(A):
    num=10
    def __init__(self,x,y,z):
        self.z=z
        super().__init__(x,y)
b=B(1,2,3)
print(b.x)
print(B.num)
# print(B.__num1)    # 报错
print(A.num)

print(super(B,b).num)

三、多继承

(一)多继承注意事项

如果子类与父类又相同的方法,就会调用子类中的方法

class A():
    def t(self):
        print('A:t1')
class B():
    def t(self):
        print('B:t2')
class C(A,B):
    def t(self):
        print('C:t3')
c=C()
c.t()

如果不同的父类存在同样的方法名称,根据MRO方法解析顺序列表进行查找。

class A():
    def tx(self):
        print('A:t1')
class B():
    def tx(self):
        print('B:t2')
class C(B,A):    # A在前,先A;B在前,先B
    def t(self):
        print('C:t3')
c=C()
c.tx()

(二)继承原理(钻石继承)

1.子类会先于父类被检查

2.多个父类会根据它们在列表中的顺序被检查

3.如果对下一个类存在两个合法的选择,选择第一个父类

(三)多继承中super的本质--表示mro表的下一个

class A():
    def func(self):
        print('A开始')
        print('A结束')
class B(A):
    def func(self):
        print('B开始')
        super().func()
        print('B结束')
class C(A):
    def func(self):
        print('C开始')
        super().func()
        print('C结束')
class D(B,C):
    def func(self):
        print('D开始')
        super().func()
        print('D结束')
print(D.mro())
d=D()
d.func()
class A():
    def __init__(self):
        print('A开始')
        print('A结束')
class B(A):
    def __init__(self):
        print('B开始')
        super().__init__()
        print('B结束')
class C(A):
    def __init__(self):
        print('C开始')
        super().__init__()
        print('C结束')
class D(B,C):
    def __init__(self):
        print('D开始')
        super().__init__()
        print('D结束')
print(D.mro())
d=D()
class A():
    def __init__(self):
        print('A')
        super().__init__()
class B():
    def __init__(self):
        print('B')
        super().__init__()
class C(A,B):
    def __init__(self):
        print('C')
        super().__init__()
c=C()
print(C.mro())

四、多态

class Dog():
    def jiao(self):
        print('汪汪')
class Cat():
    def jiao(self):
        print('喵喵')
class Pig():
    def jiao(self):
        print('哼哼')
def hehe(a):
    a.jiao()
d=Dog()
c=Cat()
p=Pig()
# 若不知道d,c,p对象是什么类型的对象,就不知道会执行哪个
# 这就是多态
hehe(d)
hehe(c)
hehe(p)
class Ali():
    def pay(self,money):
        print('阿里支付:',money)
class WChat():
    def pay(self,money):
        print('微信支付:',money)
class Person():
    def comsume(self,x,money):
        x.pay(money)
a=Ali()
w=WChat()
zs=Person()
zs.comsume(a,100)
zs.comsume(w,200)

五、实例方法、类方法和静态方法

class A():
    num=10
    def hehe(self):
        print('我是实例方法,也叫对象方法')
    @classmethod
    def haha(cls):
        print('我是类方法,我的第一个参数代表的是类,A')
        print(cls.num)
    @staticmethod
    def heihei():
        print('我是静态方法,跟这个类没有太多血缘关系')
a=A()
a.hehe()
A.hehe(a)    # 用类名访问对象方法,第一个参数如果传过来的是对象,就可以,了解即可,不建议使用
A.haha()
a.haha()    # 传进去的参数,虽然是对象,但知道它属于哪个类
A.heihei()
a.heihei()

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值