zoukankan      html  css  js  c++  java
  • 面向对象一

    一.面向对象初始

    函数式编程相较于面向过程编程的优点

    1.减少代码的重用性。
    2.增强代码的可读性。
    

    面向对象编程相较于函数编程的优点

    1.是一类相似功能函数的集合,使代码更清晰化,更合理化。
    

    概念

    类的实例化:类名+()的过程称为类的实例化,产生一个对象(实例).
    实例化做三件事:
        1.执行object的__new__()方法,产生并返回一个空对象(在内存中开辟了一个对象空间)
        2.自动触发类的内部__init__函数的执行,将空对象作为参数传给__init__函数
        3.在__init__方法中通过self给对象空间添加属性
    查看对象的名称空间(只存对象独有的):
        print(obj.__dict__)
    对象属性的查找顺序(对象的命名空间->类的命名空间):
        1.类的数据属性(给对象用,不同对象对应的地址相同)
        2.类的函数属性(给对象用,不同对象)
        #1.对象名.__dict__
        #2.类名.__dict__
    

    类的结构

    类的结构从大方向来说就分为两部分:

    1.静态变量 2.动态方法

    class Human:
        '''静态变量'''
        mind = "有思想"
        feeling = "有感情"
        
        '''动态方法'''
        def work(self):
            print("会工作")
    

    二.从类名的角度研究类

    img

    类名操作静态属性

    1.查看类中所有内容,__dic__方式

    class Human:
        mind = "有思想"
        feeling = "有感情"
        
        def work(self):
            print("会工作")
            
    print(Human.__dic__)
    Human.__dic__['mind'] = "没有思想"  # 错误,通过__dic__只能查询,不能修改
    

    2.万能的.

    class Human:
        mind = "有思想"
        feeling = "有感情"
        
        def work(self):
            print("会工作")
    # 查 print(Human.mind)
    # 改 Human.mind = "五思想"
    # 增 Human.hobby = "玩"
    # 删 del Human.hobby 
    

    类名操作动态方法

    除了两个特殊方法(静态方法,类方法),一般不会通过类名操作类中方法

    class Human:
        mind = "有思想"
        feeling = "有感情"
        
        def work(self):
            print("会工作")
    Human.work(1)  # 需要传参
    

    三.从对象角度研究类

    img

    对象操作对象空间属性

    1.对象查询对象中的所有属性

    class Human:
        mind = "有思想"
        feeling = "有感情"
        
        def __init__(self,name,age):
            self.name = name
            self.age = age
            
        def work(self):
            print("会工作")
    obj = Human("张三",18)
    print(obj.__dict__) # {"name":"张三","age":18}
    

    2.对象操作对象中的单个属性,万能的.

    class Human:
        mind = "有思想"
        feeling = "有感情"
        
        def __init__(self,name,age):
            self.name = name
            self.age = age
            
        def work(self):
            print("会工作")
    obj = Human("张三",18)
    # 增 obj.sex = "男"   此举是将sex属性添加到__init__()方法中
    # 删 del obj.sex 
    # 改 obj.name = "小明"
    # 查 print(obj.__dict__)
    

    对象查看类中的属性

    class Human:
        mind = "有思想"
        feeling = "有感情"
        
        def __init__(self,name,age):
            self.name = name
            self.age = age
            
        def work(self):
            print("会工作")
            
    obj = Human("张三",19)
    print(obj.mind)  # 先从对象空间找,找不到去类中找
    

    对象操作类中的方法

    class Human:
        mind = "有思想"
        feeling = "有感情"
        
        def __init__(self,name,age):
            self.name = name
            self.age = age
            
        def work(self):
            print("会工作")
            
    obj = Human("张三",20)
    obj.work()
    

    类中的方法一般都是通过对象执行(除去类方法、静态方法是类本身调用的)的。

    四.类与类之间的联系

    1.依赖关系

    将一个类的类名或者对象传入另一个类的方法

    class Elephant:
        def __init__(self,name):
            self.name = name
        def open(self,obj):
            print(f'{self.name}默念三生')
            obj.be_open()
    
    class Refrigerator:
        def __init__(self,name):
            self.name = name
        def be_open(self):
            print(f'{self.name}冰箱被打开了')
            
    qiqi = Elephant("琪琪")
    haier = Refrigerator("海尔")
    qiqi.open(haier)
    

    2.组合关系

    给一个类的对象封装一个属性,此属性为另一个类的对象

    class Boy:
        def __init__(self,name,girlfriend=None):
            self.name = name
            self.girlfriend = girlfriend
            
        def have_a_dinner(self):
            print(f'{self.name}请他的{self.girlfriend.age}岁的女朋友{self.girlfriend.name}吃饭!')
    
    class GirlFriend:
        def __init__(self,name,age):
            self.name = name
            self.age = age
            
    boy = Boy("小明")
    girl = GirlFriend("如花",30)
    boy.girlfriend = girl
    boy.have_a_dinner()
    

    五.单继承

    继承是一种新建类的方式,新建的类称为子类派生类,父类也称为基类超类

    1.继承的优点

    1.增加了类的耦合性
    2.减少了重复代码
    3.使代码更加规范化,合理化
    

    2.类名+方法调用父类中方法

    严格来说,此方法与继承无关

    class Father:
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
    class Son(Father):
        def __init__(self,name,age):
            Father.__init__(self,name,age)
    
    son = Son("小明",20)
    print(son.__dict__)
    

    3.super()方法

    super()的返回值是一个特殊的对象,专门用来调用父类中的属性

    class Animal:
        def __init__(self,name,age,sex):
            self.name = name
            self.age = age
            self.sex = sex
    
        def eat(self):
            print("动物可以吃饭!")
            print(f"{self.name},{self.age},{self.sex}")
    
    class Person(Animal):
        def __init__(self,name,age,sex):
            # super().__init__(name,age,sex)
            super(Person,self).__init__(name,age,sex)
    
        def eat(self):
            print("人可以吃饭!")
            super().eat()
    
    person = Person("小明",19,"男")
    person.eat()
    

    六.多继承

    1.继承的分类

    只有在python2中才区分新式类和经典类。python3中,所有类都是新式类。

    新式类

    继承object的类,以及该类的子类,都是新式类

    在python3中,如果一个类没有指定继承的父类,默认就继承object

    经典类

    没有继承object的类,以及该类的子类,都是经典类

    2.查找顺序

    2.1经典类的深度优先

    2.2新式类的mro(c3)算法(参考文献:https://www.cnblogs.com/jin-xin/articles/10274734.html)

    七.封装

    1.什么是封装

    封装就是将属性私有化,提供共有的方法访问私有属性

    2.为什么要用封装?

    通过封装,可以实现对属性数据的访问限制,同时增加了程序的可维护性

    3.图解

    将"小明"和18封装给foo对象
    img

    八.多态

    1.多态定义

    同一个对象,多种形态。python默认支持多态。

    在python中,定义变量a,a=10,a="hello",a=[1,2,3],就是默认支持多态的体现。在一个类中,实例化出来多个对象,每个对象都有独一的形态,这也是多态的体现。

    2.鸭子类型

    两个完全没有耦合性的类中有相同功能的方法,我们为这两个方法设定相同的名字,那么这两个方法就互成为鸭子类型。

    class A:
        def f1(self):
            print("in A f1")
        def f2(self):
            print("in A f2")
    class B:
        def f1(self):
            print("in B f1")
        def f2(self):
            print("in B f2")
    
    # 如上:A和B类中的f1、f2方法互为鸭子类型
    # 这样的例子很多:str、tuple、list都有index方法,就是互为鸭子类型
    

    九.类的强制约束

    1.提取父类

    python语言惯用的一种约束方式,在父类中主动抛出错误

    class Payment:
        def pay(self,money):
            raise Exception("你没有实现pay方法")   #尽量抛出的是NotImplementError
    
    class QQpay(Payment):
        def pay(self,money):
            print(f"使用QQ支付了{money}")
    
    class Alipay(Payment):
        def pay(self,money):
            print(f"使用Ali支付了{money}")
    
    class Wechat(Payment):
        def fuqian(self,money):
            print(f"使用Wechat支付了{money}")
    
    def pays(obj,money):   # 新建的统一支付接口
        obj.pay(money)
    
    qqpay = QQpay()
    alipay = Alipay()
    wechat = Wechat()
    pays(qqpay,100)
    pays(alipay,200)
    pays(wechat,300)    # 子类中没有此方法,会执行父类的,父类抛出错误
    

    2.使用抽象类

    借鉴于java语言,定义抽象类的概念,做到真正的强制约束。

    '''
    抽象类和接口类做的事情 :建立规范
    制定一个类的metaclass是ABCMeta,
    那么这个类就变成了一个抽象类(接口类)
    这个类的主要功能就是建立一个规范
    
    '''
    
    from abc import ABCMeta,abstractmethod
    class Payment(metaclass=ABCMeta):
        @abstractmethod
        def pay(self,money):
            pass
    
    class QQpay(Payment):
        def pay(self,money):
            print(f"使用QQ支付了{money}")
    
    class Alipay(Payment):
        def pay(self,money):
            print(f"使用Ali支付了{money}")
    
    class Wechat(Payment):
        def fuqian(self,money):
            print(f"使用Wechat支付了{money}")
    
    def pays(obj,money):   # 新建的统一支付接口
        obj.pay(money)
    
    qqpay = QQpay()
    alipay = Alipay()
    wechat = Wechat()
    pays(qqpay,100)       
    pays(alipay,200)
    pays(wechat,300)        #初始化对象就会报错
    

    十.super()深入了解

    https://www.cnblogs.com/jin-xin/articles/10279154.html
    按照self对象从属于类的mro的顺序,执行Foo类的下一个类

    class F:
        def f1(self):
            pass
    class Foo(F):
        def f1(self):
            super(Foo,self).f1()
    foo = Foo()
    foo.f1()
    
    
    
    #############
    class A:
    
       def __init__(self):
           self.__func()                        # self._A__func()
    
        def __func(self):                     # _A__func()
            print('in A __func')
    
    class B(A):
       def __func(self):                     # _B__func()
           print('in B __func')
    
    
    obj = B()         #执行结果:in A_func
    

    十一.类的组成成员

    类大致分为两块区域
    img

    细分

    class A:
        name = 'alex'                  #静态字段
        __iphone = '1259874159'        #私有静态字段
        
        def __init__(self,name,age):   #特殊方法
            self.name = name           #对象普通属性
            self.__age = age           #对象私有属性
        def func1(self):               #普通方法
            pass
        def __func(self):              #私有方法
            pass
        
        @classmethod                   #类方法
        def class_func(cls):
            pass
        
        @staticmethod                  #静态方法
        def static_func():
            pass
        @property                      #属性
        def prop(self):               
            pass
    

    十二.类的私有成员

    无论是类的私有属性还是私有方法,都只能在本类内部调用,注意是本类内部。外部和此类的子类都不能调用。如果要想一个变量或方法变成私有的,在前面加上__即可,这样打印a.dict,我们可以得到对象a的空间的属性,私有属性默认为设为_A__name,可通过此字段访问私有属性,但建议不要这样做。

    1.私有静态字段

    # 类内部可访问
    class A:
        name = "公有静态字段"
        __name = "私有静态字段"
        
        def func(self):
            print(self.name)
            print(self.__name)
            
    a = A()
    a.func()  #打印结果:共有静态字段 私有静态字段
    
    
    # 外部不可访问
    class A:
        __name = "私有静态字段"
    
    a = A()
    print(a.__name)  # 报错,提示对象a没有此__name属性
    
    
    # 类的子类不能访问
    class A:
        __name = "私有静态字段"
    class B:
        def func(self):
            print(self.__name)
    
    b = B()
    b.func()   # 报错,提示对象b没有__name属性
    

    2.私有方法

    # 类内部可访问
    class A:
        def __func(self):
            print("类的私有方法")
        def func(self):
            self.__func()
    a = A()
    a.func() # 打印结果: 类的私有方法
    
    
    # 外部不可访问
    class A:
        def __func(self):
            print("类的私有方法")
    a = A()
    a.__func()  # 报错,提示对象a没有__func属性
    
    
    # 类的子类不能访问
    class A:
        def __func(self):
            print("类的私有方法")
    class B(A):
        def func(self):
            self.__func()
    b = B()
    b.func()    # 报错,提示b对象没有__func属性
    

    3.私有对象属性

    class A:
        def __init__(self,name,sex):
            self.name = name 
            self.__sex = sex
    a = A("小明","男")
    print(a.__sex)    # 报错,提示对象a没有__sex属性
    print(a.__dict__) # {'name': '小明', '_A__sex': '男'}
    

    十三.类的其他成员

    类的其他成员中包括实例方法、类方法、静态方法、双下方法。

    1.类方法

    一般通过类名调用的方法,并且自动将类名地址传给参数cls。通过实例化对象调用也可以,还是将对象所属类名地址也传给cls。

    类方法作用:1.得到类名可以实例化对象。2.可以操作类的属性

    # 得到实例化对象的个数
    class Student:
        count = 0 
        def __init__(self,name,id):
            self.name = name
            self.id = id
            
        @classmethod
        def addnum(cls):
            cls.count = cls.count + 1
        
        @classmethod
        def getnum(cls):
            return cls.count
    
    obj1 = Student('liye', 12343243243)
    obj1 = Student('liye', 12343243243)
    print(Student.getnum()) # 2
    

    2.静态方法

    使用装饰器@staticmethod

    静态方法主要用来存放逻辑性的代码,逻辑上属于类,但是和类本身没有关系。

    静态方法作用:1.代码更加规范、合理。2.它仅仅托管于某个类的名称空间中,便于使用和维护。

    import time
    
    class TimeTest(object):
    
        area = '中国'
        def __init__(self, hour, minute, second):
            self.hour = hour
            self.minute = minute
            self.second = second
    
        def change_time(self):
            print(f'你想调整的时间: {self.hour}时{self.minute}分{self.second}秒')
    
        @staticmethod
        def showTime():
            return time.strftime("%H:%M:%S", time.localtime())
    
    
    def showTime():
        return time.strftime("%H:%M:%S", time.localtime())
    
    def time1():
        pass
    
    def time2():
        pass
    # t = TimeTest(2, 10, 10)
    # # t.change_time()
    # print(TimeTest.showTime())
    

    十四.特性property

    应用场景:遇到类似于属性的方法名,可以让其伪装成属性

    以下两个方法都是将动态方法伪装成一个属性

    1.利用装饰器设置属性

    class Foo:
        @property
        def bmi(self):
            print("get的时候运行")
        
        @bmi.setter
        def bmi(self,value):
            print("set的时候运行")
        
        @bmi.deleter
        def bmi(self):
            print("delete的时候运行")
            
    foo = Foo()
    foo.bmi           # 执行@property装饰的方法
    foo.bmi = 666     # 不是改变bmi的值,而是执行setter装饰的方法
    del foo.bmi       # 执行deleter装饰的方法
    

    2.利用实例化对象的方式设置属性

    class Foo:
        def get_A(self):
            print("get的时候运行")
        def set_A(self):
            print("set的时候运行")
        def delete_A(self):
            print("delete的时候运行")
        A = property(get_A,set_A,delete_A)   # 内置property三个参数与get,set,delete
    
    f1 = Foo()
    f1.A              # 执行get_A()函数
    f1.A = 'aaa'      # 执行set_A()函数
    del f1.A          # 执行delete_A()函数
    

    十五.isinstance,issubclass

    1.isinstance(对象与类的关系)

    判断对象是否是某类某类派生类的实例化对象

    class A:
        pass
    class B(A):
        pass
    
    obj = B()
    print(isinstance(obj,B))  # True
    print(isinstance(obj,A))  # True
    

    2.issubclass(类与类的关系)

    判断是否是某类某类派生类派生类

    class A:
        pass
    class B(A):
        pass
    class C(B):
        pass
    
    issubclass(B,A)    # True
    issubclass(C,A)    # True
    
  • 相关阅读:
    背水一战 Windows 10 (61)
    背水一战 Windows 10 (60)
    背水一战 Windows 10 (59)
    背水一战 Windows 10 (58)
    背水一战 Windows 10 (57)
    背水一战 Windows 10 (56)
    背水一战 Windows 10 (55)
    背水一战 Windows 10 (54)
    背水一战 Windows 10 (53)
    背水一战 Windows 10 (52)
  • 原文地址:https://www.cnblogs.com/luckinlee/p/11620350.html
Copyright © 2011-2022 走看看