zoukankan      html  css  js  c++  java
  • 初识面向对象(钻石继承,super,多态,封装,method,property,classmethod,staticmethod)



    组合 什么有什么的关系

    一个类的对象作为另一个类的对象
    继承
    子类可以使用父类中的名字(静态属性 方法)
    抽象类和接口类
    只能不继承,不能被实例化
        子类必须实现父类中的同名方法———规范代码
        metaclass=ABCMeta @abstractmethod
        python 支持多继承,对于python 来说,抽象类和接口类没有区别
        接口类是python 特有的,因为Pythonz直接用类就可以实现接口的效果
        python没有'接口'这种数据类型,java中有
    继承
    多态
    封装
    property
    classmethod
    staticmethod

    钻石继承
    class A:
        def func(self):print('in A')
    class B(A):
        def func(self):print('in B')
    class C(A):
        def func(self):print('in C')
    class D(B,C):
        def func(self): print('in D')
    d=D()
    d.func()#in D
    
    class A:
        def func(self):print('in A')
    class B(A):pass
        # def func(self):print('in B')
    class C(A):pass
        # def func(self):print('in C')
    class D(B,C):pass
        # def func(self): print('in D')
    d=D()
    d.func()#in A
    钻石继承--4个类图形
    D->B->C->A
    class E:
        def func(self):print('in E')
    class D:
        def func(self):print('in D')
    class C(E):
        def func(self):print('in C')
    class B(D):pass
        # def func(self):print('in B')
    class A(B,C):pass
        # def func(self):print('in A ')
    d=D()
    d.func()#in D 走最合理的路
    
    class F:
        def func(self):print('in F')
    class E(F):
        def func(self):print('in E')
    class D(F):
        def func(self):print('in F')
    class C(E):
        def func(self):print('in C')
    class B(D):
        def func(self):print('in B')
    class A(B,C):
        def func(self):print('in A')#遵循广度优先的原则
    print(A.mro())#打印的是A 的找值顺序[<class '__main__.A'>, <class '__main__.B'>, ...]A,B,D,C,E,F
    super
    class List(list):
        def append(self, obj):
            if type(obj) is str:
                super().append(obj)#调用父类的方法,list.append(obj)
            else:
                # print(f'{obj}不是字符串类型')
                print('%s不是字符串类型' % obj)
    
        def show_middle(self):
            return self[int(len(self) / 2)]#返回以长度的一半为索引的self的值
    
    
    li = List('hello word22222')#['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'd', '2', '2', '2', '2', '2', '18', 'abc']
    li.append('18')
    li.append('abc')
    print(li)
    print(li.show_middle())#r
    
    
    class A:
        def func(self):
            print('A')
    class B(A):
        def func(self):
            print('B')
            super().func()
    class C(A):
        def func(self):
            print('C')
            super().func()
    class D(B,C):
        def func(self):
            print('D')
            super().func()
    D().func()#D,B,C,A
    print(D.mro())#打印的是A 的找值顺序D->B->C->A
    B().func()#B,A
    print(B.mro())#打印的是A 的找值顺序B->A
    super并不是单纯的找父类,和mro的顺序是玩完全对应的

    新式类:python 3里全部是新式类
    新式类默认继承object
    py2里面
    新式类 主动继承object
    经典类 不主动继承object--遵循深度优先算法,没有mro 方法,没有super

    python  动态强类型语言
    弱类型 1+'2' 参数的数据类型也不需要指定
    强类型 同类型之
    间可以做运算 参数的数据类型也需要指定
    在python的经典类中,方法解析顺序是深度优先算法
    事实上,对于你定义的每一个类,Python 会计算出一个方法解析顺序(Method Resolution Order, MRO)列表它代表了类继承的顺序
    在Python的新式类中,方法解析顺序并非是广度优先的算法,而是采用C3算法,只是在某些情况下,C3算法的结果恰巧符合广度优先算法的结果。

    C3算法的本质就是Merge,不断地把mro()函数返回的序列进行Merge,规则如下:

    1. 如果第一个序列的第一个元素,是后续序列的第一个元素,或者不再后续序列中再次出现,则将这个元素合并到最终的方法解析顺序序列中,并从当前操作的全部序列中删除。

    2. 如果不符合,则跳过此元素,查找下一个列表的第一个元素,重复1的判断规则

    举例:

    # 归并算法 C3算法
    class A:pass
    class B(A):pass
    class C(A):pass
    class D(B):pass
    class E(C):pass
    class F(D,E):pass
    
    # 第一步 先找出F类的父类的MRO
    D [D,B,A,O]
    E [E,C,A,O]
    # 变形为:merge([D,B,A,O], [E,C,A,O], [D,E])
    # 第一个表的表头  后面所有的表去掉表头部分不能含有这个D
    FD merge([B,A,O], [E,C,A,O], [E]) # 先将D取出来
    FDB merge([A,O], [E,C,A,O], [E])  # 再将B取出来
    # 不满足条件时 取二个
    FDBE merge([A,O], [C,A,O]) # 将第二个列表E取出来
    FDBEC merge([A,O], [A,O])  # 将第二个列表里的C取出来,此时取值完成
    FDBECAO  # F的继承顺序为FDBECAO
    # 注意:这是模仿内部的查找机制做的示例,并非真实原理
    多态
    python天生自带多态
    什么是多态
    java多态
    class Foo:pass
    class list(Foo):pass
    class dict(Foo):pass
    class str(Foo):pass
    def len(a):
        print(a)
    len(1)

    封装

    封装成一个函数
    封装成一个类

    封装 面向对象的特性
    class A:
        __静态属性='aaa' #私有的静态属性
        print(__静态属性)#aaa __静态属性,在内部的储存方式为_类名__名字,例如_A__静态属性
    在一个变量前加上两个下划线是有特殊意义的,将变量变成私有的
    
    print(A.__静态属性)#报错,私有的名字不能在类的外部使用
    print(A.__dict__)#将类的内容打印出来
    print(A._A__静态属性)#从语法的角度上不允许直接调用  aaa
    A.__wahahaha='hahaha'#在一个类的外部是不可能定义一个私有名字的 ,此处的hahaha是普通变量
    print(A.__dict__)
    私有的对象属性
    class Room:
        def __init__(self,owner,id,length,width,height):
            self.owner=owner
            self.id=id
            self.__length=length
            self.__width=width
            self.__height=height
        def area(self):
            return self.__length*self.__width  #这里 self.__length在内存里是self._Room__length
    r=Room('小灰灰',301,1,1,0.5)
    print(r.area())#1
    私有的方法
    不希望从外部去调用这个方法,不独立完成一个功能,而是类整体完成某个功能的一部分
    class Student:#理解
        def __init__(self,name,pwd):
            self.name=name
            self.__pwd=pwd
        def __getpwd(self):
            return self.__pwd[::-1]
        def login(self):
            return self.__getpwd()
    s=Student('xiaohua','abc')
    print(s.login())#cba
    
    
    class A:
        def __init__(self):
            self.func()
        def func(self):
            print('A')
    
    class B(A):
        def func(self):
            print('B')
    
    B()#B  用的是父类class A 的__init__方法,调用的是自己的func函数
    
    class A:
        def __init__(self):
            self.__func()   #_A__func
        def __func(self):
            print('A')
    class B:
        def __func(self):
            print('B')
        def __init__(self):
            self.__func()   #_B__func
    B()#B
    
    class A:
        def __init__(self):
            self.__func()   #_A__func
        def __func(self):
            print('A')
    class B:
        def __init__(self):
            self.__func()   #_B__func
    B()#报错,找不到_B__func的对象

    名字
    共有的 在类的外部用 内部用 子类用
    私有的 在类的内部用

    私有的概念和面试题 ***
    私有的属性和静态属性***
    私有方法**

    几个装饰器函数
    property
    classmothod
    staticmethod
    装饰器
    圆形
    半径r
    面积area
    周长 perimeter

    from math import pi
    class Circle:
        def __init__(self,r):
            self.r=r
        @property#将一个方法伪装成一个属性
        def area(self):
            return pi*self.r**2
        @property
        def perimeter(self):
            return 2*pi*self.r
    r1=Circle(3)
    print(r1.area)#相当于不加装饰前的r1.area()
    print(r1.perimeter)#相当于不加装饰前的r1.perimeter()

     

    class Person:
        def __init__(self,name):
            self.__name=name
        @property#将一个方法伪装成一个属性
        def name(self):
            return self.__name
        @name.setter#将这个属性进行修改
        def name(self,new):
            if type(new) is str:
                self.__name=new
    a=Person('egon')
    print(a.name)#egon
    a.name='alex'#不能直接改
    print(a.name)#alex
    
    
    class Demo:
        def __init__(self,wahaha):
            self.__wahaha=wahaha
        @property#将一个方法伪装成属性
        def wahaha(self):
            print('in wahaha')
            return  self.__wahaha
        @wahaha.setter
        def wahaha(self,new):
            self.__wahaha=new
    d=Demo('abc')
    print(d.wahaha)#123 可以被查看
    d.wahaha=123#可以被修改
    print(d.wahaha)#123
    
    
    class Goods:
        def __init__(self,discount,origin_price):
            self.__discount=discount
            self.__price=origin_price
        @property
        def price(self):
            return round(self.__discount*self.__price,2)#保留两位小数
        @price.setter
        def price(self,new):
            self.__price=new
    d=Goods(0.8,10)
    print(d.price)#8.0
    d.price=12
    print(d.price)#9.6

    一个属性
    可以被查看
    可以被修改
    可以被删除

    class A:pass
    a=A()
    a.name='egon'
    print(a.__dict__)#{'name': 'egon'}
    del a.name
    print(a.__dict__)#{}
    
    
    class A:
        def __init__(self, path):
            self.__f = open(path, 'w')  # 创建属性的方式可以改变
        @property
        def f(self):
            return self.__f
        @f.deleter
        def f(self):
            self.close()#所有的借用操作系统的资源,在删除一个变量之前必须先归还资源
            del self.__f
        def write(self,content):
            self.__f.write(content)
        def close(self):
            self.__f.close()#上面的self.close()=self.__f.close()
    obj=A('heheda')
    obj.write('窗前明月光,地上鞋两双')
    obj.close()#所有的借用操作系统的资源,在删除一个变量之前必须先归还资源
    
    del obj.f#f 文件删除,文件没有关
    print(obj.f)
    property***
    setter**
    deleter*
    class Goods:
        __discount=0.8
        def __init__(self,origin_price):
            self.__price=origin_price
        @property
        def price(self):
            return round(self.__price*Goods.__discount,2)#Goods.__discount.调用静态变量
        @price.setter
        def price(self,new_price):
            self.__price=new_price
        @classmethod
        def change_discount(cls,new_discount):
            print(cls,Goods)#此时的cls和Goods是一样的
            Goods.__discount=new_discount
            # cls.__discount=new_discount
    banana=Goods(10)
    print(banana.price)#8
    banana.change_discount(1)#10 恢复原价
    print(banana.price)
    
    
    class Student:
        def __init__(self,name,sex):
            self.name=name
            self.sex=sex
        @staticmethod #相当于函数
        def login():
            name=input('>>')
            if name=='alex':
                print('登录成功')
    # 学生的登录行为
    Student.login()

     

    method            方法--函数                          由实例化对象去调用
    property 伪装成属性的一种方法 --特性 由实例化对象去调用
    classmethod 类方法 由类调用,只用用类中的静态变量
    staticmethod 静态方法 由类调用,一个方法既不会用到对象的属性,也不会用到类的属性


  • 相关阅读:
    Windows 7目录
    用wubi安装的Ubuntu在重装Windows 7系统后,如何恢复(转)
    用java查询HBase中某表的一批数据
    hbase数据模型以及编码压缩(转)
    应用Flume+HBase采集和存储日志数据
    HBase性能调优(转)
    【剑指Offer学习】【面试题50:树中两个结点的最低公共祖先】
    [Phonegap+Sencha Touch] 移动开发24 打包wp8.1的App,执行时输入框聚焦弹出软键盘之后,界面上移而不恢复原位的解决的方法
    写在课程设计之后
    String内存溢出异常(错误)可能的原因及解决方式
  • 原文地址:https://www.cnblogs.com/daofaziran/p/9102513.html
Copyright © 2011-2022 走看看