lchengshao

封装 继承 多态

1. 封装
1. 封装的理论:
"""
封装
    封装指的就是把数据与功能都整合到一起,听起来是不是很熟悉,没错,我们之前所说的”整合“二字其实就是封装的通俗说法。
    
什么是封装 在程序设计中,封装(Encapsulation)是对具体对象的一种抽象,即将某些部分隐藏起来,在程序外部看不到,其含义是其他程序无法调用。 要了解封装,离不开“私有化”,就是将类或者是函数中的某些属性限制在某个区域之内,外部无法调用。 为什么要封装 封装数据的主要原因是:保护隐私(把不想别人知道的东西封装起来)
""" class Student(): __school = 'SH' # _Student__school def __init__(self, name, age, gender): self.__name = name self.age = age self.gender = gender def __func(self): print('from func') def get_name(self): return self.__name def set_name(self,v): if type(v) is str: Student._Student__name = v return else: print('必须是字符串') def del_name(self): del self.__name print('属性已删除') """ 第一种方法: 必须一一对应 第一个是 get set del 顺序不能乱 执行相关操作的时候 装饰器会判断执行对应的函数功能 """ name = property(get_name,set_name,del_name,) stu = Student('huang',18,'male') # print(stu.name) del stu.name # 删除 stu.name = 'lu' # 修改 print(stu.name) # 查看 # print(stu.__dict__)

2. 继承

"""
1. 什么是继承?
    继承就是一种新建类的方式,新建出来的类我们称之为 '子类或者叫派生类',被继承的类我们叫做 基类
    当然 出来的类的子类都是可以遗传父类的所有属性

2. 为什么要用继承?
    类解决了什么问题:对象之间的代码冗余问题
    继承解决了什么问题:类与类之间的代码冗余问题

3. 怎么使用继承?
    经典类:没有继承object的类或子子类都是称之为经典类 python2.x本版才有经典类 3.x版本只有新式类了

    新式类:继承了object的累的子子类都是新式类
再有在Python2中才区分经典类和新式类,如果是Python3的版本,所有的类都是新式类,也就是说在Python3中默认的类都是继承了object类,在Python3中没有了经典类和新式类的说法了.
    
"""
继承代码显示如下:

class Foo:
    pass


class Bar:
    pass

class Order(Foo):
    pass
# Order 类继承了 Foo类,Order就称之为子类 Foo类就是叫做父类 或者是基类
# 单继承:一次只继承一个父类 若是继承多个 就叫多继承

class Stu(Foo,Bar):
    pass
# 多继承的类 Stu 就是子类 Foo 和 Order 就是父类

print(Stu.__bases__) # (<class '__main__.Foo'>, <class '__main__.Bar'>)
# 内置函数 查看子类继承了多少个父类

""" 继承的实际案例""" 两种方法

第一种:不依赖于继承来实现
class Teachar_Stu():
    scholl = 'SH'

    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender

    def func(self):
        print('from func')


class Stu(Teachar_Stu):
    def __init__(self, uid, class_name, name, age, gender):
        self.uid = uid
        self.class_name = class_name
        Teachar_Stu.__init__(self, name, age, gender)  # 这种类来调用方法 不依赖与继承 子类里面一定再次调用父类的方法 指名道姓的调用

    def index(self):
        print('%s 同学喜欢打篮球' % self.name)


class Tar(Teachar_Stu):
    def __init__(self, evol, salary, name, age, gender):
        self.evol = evol
        self.salary = salary
        Teachar_Stu.__init__(self, name, age, gender)  # 这种类来调用方法 不依赖与继承

    def scoring(self, student, fraction):
        print('%s 老师给 %s 同学打了 %s 分' % (self.name, student, fraction))


sti1 = Stu('D15', '12班', 'huang', 18, 'male')
sti1.index()

tar1 = Tar('10级', 35000, 'hai', 28, 'female')
tar1.scoring(tar1.name, 90)



第二种
class Teachar_Stu():
    scholl = 'SH'

    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender

    def func(self):
        print('from func')


class Stu(Teachar_Stu):
    def __init__(self, uid, class_name, name, age, gender):
        self.uid = uid
        self.class_name = class_name
        super(Stu, self).__init__( name, age, gender) # 这种写法是 python2.x版本的
     super().__init__(name,age,gender)             # 这种是python3.x版本的写法
    def index(self):
        print('%s 同学喜欢打篮球' % self.name)


class Tar(Teachar_Stu):
    def __init__(self, evol, salary, name, age, gender):
        self.evol = evol
        self.salary = salary
        super(Tar, self).__init__( name, age, gender)
     
super().__init__(name,age,gender) # 这种是python3.x版本的写法
def scoring(self, student, fraction): print('%s 老师给 %s 同学打了 %s 分' % (self.name, student, fraction)) sti1 = Stu('D15', '12班', 'huang', 18, 'male') sti1.index() tar1 = Tar('10级', 35000, 'hai', 28, 'female') tar1.scoring(tar1.name, 90)

3. 单继承下的查找

单继承
class A():
    def f2(self):
        pass

class Foo(A):
    def f1(self):  # _Foo__f1
        print('from Foo.f1')

    def f2(self):
        print('from Foo.f2')
        self.f1()


class Bar(Foo):
    def f1(self): # _Bar__f1
        print('from Bar.f1') # from Bar.f1
"""单继承下的属性查找:先从对象自己名称空间中查找,然后去产生这个对象的类中查找,最后去继承的父类中查找."""
obj = Bar()
obj.f2()
"""
from Foo.f2
from Bar.f1
"""

如果有隐藏属性:
class A():
    def f2(self):
        pass

class Foo(A):
    def __f1(self):  # _Foo__f1
        print('from Foo.f1')

    def f2(self):
        print('from Foo.f2')
        self.__f1() # _Foo__f1


class Bar(Foo):
    def __f1(self): # _Bar__f1
        print('from Bar.f1') # from Bar.f1
"""单继承下的属性查找:先从对象自己名称空间中查找,然后去产生这个对象的类中查找,最后去继承的父类中查找.
如果有隐藏属性 在对象中找不到 去类中 类中找不到去父类 父类中找到了 一样是调用父类的隐藏属性
"""

obj = Bar()
obj.f2() 

4. 多继承下的属性查找

多继承下分菱形查找和非菱形查找
菱形查找分 经典类 和 新式类
经典类:按照深度优先的查找顺序
新式类:按照广度优先查找
 # 在python2中,未继承object的类及其子类,都是经典类
    def test(self):
        print('from G')


class E(G):
    def test(self):
        print('from E')


class F(G):
    def test(self):
        print('from F')


class B(E):
    def test(self):
        print('from B')


class C(F):
    def test(self):
        print('from C')


class D(G):
    def test(self):
        print('from D')


class A(B, C, D):
    # def test(self):
    #     print('from A')
    pass


obj = A()
obj.test()  # 如上图,查找顺序为:obj->A->B->E->G->C->F->D->object
# 可依次注释上述类中的方法test来进行验证,注意请在python2.x中进行测试
类及其子类,都是经典类

class G(object):
    def test(self):
        print('from G')

class E(G):
    def test(self):
        print('from E')

class F(G):
    def test(self):
        print('from F')

class B(E):
    def test(self):
        print('from B')

class C(F):
    def test(self):
        print('from C')

class D(G):
    def test(self):
        print('from D')

class A(B,C,D):
    # def test(self):
    #     print('from A')
    pass

obj = A()
obj.test() # 如上图,查找顺序为:obj->A->B->E->C->F->D->G->object
# 可依次注释上述类中的方法test来进行验证

"""python3中都是新式类,都是广度优先查询"""

5. super 和 mro的使用

class A:
    def test(self):
        super().test()

class B:
    def test(self):
        print('from B')

class C(A, B):
    pass

s = A()
s.test() # 首先要清楚当前产生对象的是那个类 super的作用基本就是调用父类的功能
"""mro列表是通过一个C3算法得出来的,我们无需明白底层原理,只需要知道每个类的mro列表到底是什么,然后按照这个列表去查找就行"""
# 在打印mro列表的时候,一定是从起始类开始

"""mro列表,每个类都有自己的mro列表,怎么查看类的mro列表"""
a = A()
# a.test()
print(A.mro()) # (<class '__main__.A'>, <class 'object'>)
print(A.__mro__)

6. 鸭子类型

什么是多态?
    同一种事物的多种形态

鸭子类型的两种方式

第一种:
import abc  # # abstract class 抽象类   具体的Specific

class Foo(metaclass=abc.ABCMeta): # 把animal类变成了抽象类
    @abc.abstractmethod  # """父类中得方法不是为了实现逻辑的,实现功能的,而是单纯的为了限制子类的行为"""
    def func(self): # 把抽象类中得方法变成抽象方法, 它不实现具体的功能,就是单纯的为了限制子类中的方法
        print('吃的功能')

class Bar(Foo):
    def func(self):
        print('qq')

class Stary(Foo):
    def func(self):
        print('ww')

stu = Stary()
stu.func()
"""抽象类和普通类有什么区别? 抽象类只能够被继承、不能够被实例化"""
"""怎么限制子类Bar类必须有func功能? 我们可以在父类中来限制子类的行为,其实就是限制子类中必须有某些方法"""

第二种 :
"""Python崇尚的是鸭子类型"""

"""鸭子类型就是更多的关注的是对象的行为,而不是对象的类型"""
并不是一定要限制子类要实现父类的功能 
而是在不继承的情况下 照样能让 其他类有这个功能 

class People():
    def speak(self):pass

    def jiao(self):
        pass

class Dog():
    def speak(self):
        pass


class Pig():
    def speak(self):
        pass

"""多态带来的特性:在不考虑对象类型的情况下,直接调用对象的方法或者属性"""
def animal(obj):
    return obj.speak()

obj = Pig()
obj1 = Dog()

animal(obj)
animal(obj1)

 

posted on 2023-10-09 19:52  Lubomierz  阅读(6)  评论(0编辑  收藏  举报

导航