• 面对对象进阶


    面对对象进阶

    1.多继承中的self 

    class A:
        def bar(self):
            print('BAR')
            self.f1()
    '''
    self本身代表的D类的对象d1
    d1如果要在他的父类中去寻找f1
    首先应该去C类
    '''
    
    class B(A):
        def f1(self):
            print('B')
    
    
    class C:
        def f1(self):
            print('C')
    
    
    class D(C, B):
            pass
    
    
    d1 = D()
    d1.bar()
    
      流程分析:
    1. d1 = D(),最终找到了object里面的__init__方法创建了对象d1
    2. d1.bar(),执行bar方法,先去C里找,再去B里面找,最后在A中找到了
    3. 执行A中的bar方法,遇到self.f1(),此时self依然表示对象d1
    4. 依然先去C里面找方法f1,最终在C中找到了

    2.构造方法

      2.1 普通构造方法
    class Animal:
        def __init__(self):
            print('A构造方法')
            self.ty = '动物'
    
    
    class Cat(Animal):
        def __init__(self):
            print('B构造方法')
            self.n = '猫'
    
    
    a = Animal()
    c = Cat()
    print(a.__dict__)
    print(c.__dict__)
    '''
    A构造方法
    B构造方法
    {'ty': '动物'}
    {'n': '猫'}
    '''
    
      2.2 如果我们想将父类的字段ty封装子类Cat创建的对象中去呢?
    class Animal:
        def __init__(self):
            print('A构造方法')
            self.ty = '动物'
    
    
    class Cat(Animal):
        def __init__(self):
            print('B构造方法')
            self.n = '猫'
            self.ty = '动物'
            # 执行父类的构造方法
    
    
    a = Animal()
    c = Cat()
    print(a.__dict__)
    print(c.__dict__)
    '''
    A构造方法
    B构造方法
    {'ty': '动物'}
    {'n': '猫', 'ty': '动物'}
    '''
      2.3 如果父类的字段较多,创建子类的时候想继承这些字段,需要重复的代码量很大

       我们可以执行父类的构造方法super

    class Animal:
        def __init__(self):
            print('A构造方法')
            self.ty = '动物'
            self.chi = '吃'
            self.he = '喝'
            self.la = '拉'
    
    # 方法1
    class Cat(Animal):
        def __init__(self):
            print('B构造方法')
            self.n = '猫'
            super(Cat, self).__init__()  # 找到Cat的父类,执行其父类的构造方法
    
    '''
    方法2
    class Cat(Animal):
        def __init__(self):
            print('B构造方法')
            self.n = '猫'
            Animal.__init__(self)
    '''
    
    a = Animal()
    c = Cat()
    print(a.__dict__)
    print(c.__dict__)
    '''
    A构造方法
    B构造方法
    A构造方法
    {'ty': '动物', 'chi': '吃', 'he': '喝', 'la': '拉'}
    {'n': '猫', 'ty': '动物', 'chi': '吃', 'he': '喝', 'la': '拉'}
    '''

    3.面对对象中的反射

      3.1基本用法
    class Foo:
        def __init__(self, name):
            # 类的字段
            self.name = name
    
        def show(self):
            print('show')
    
    
    obj = Foo('alex')
    
    # 通过类,找到类的方法
    r1 = hasattr(Foo, 'show')
    print(r1)
    '''
    True
    '''
    
    # 通过对象,既可以找到对象的成员,也可以找到类里的成员
    r2 = hasattr(obj, 'name')  # 找到对象的成员
    r3 = hasattr(obj, 'show')  # 通过类对象指针,可以找到类的方法
    print(r2, r3)
    '''
    True True
    '''
      3.2 通过字符导入模块,用反射操作类的成员
    class Foo:
        def __init__(self, name):
            # 类的字段
            self.name = name
    
        def show(self):
            print('show')
    testmoudle.py
    # 通过字符串导入模块
    c = __import__('testmoudle', fromlist=True)  # 模块名有嵌套的话
    # 通过反射获取模块中的类
    class_name = getattr(c, 'Foo')
    # 根据类创建一个对象
    obj = class_name('alex')
    # 通过反射获取name对应的值
    val = getattr(obj, 'name')
    print(val)
    '''
    alex
    '''
    

      

    4.类的成员

      成员

        字段:普通字段(每个对象都不同的数据),静态字段(每个对象都有一份

        方法:普通方法(使用对象封装的数据),静态方法(无需使用对象封装的内容),类方法(自动将类名传入

        特性:将方法以字段的形式调用 

      快速判断是由类执行还是对象执行

        有self,对象调用

        无self,类调用

    class Province:
        # 静态字段
        country = 'China'
    
        def __init__(self, name):
            # 普通字段
            self.name = name
            # self.country = 'china'
    
        # 普通方法
        def show(self):
            print('show')
    
        # 类方法
        @classmethod
        def xxoo(cls):  # cls == class
            print('xxoo')
    
        # 静态方法
        @staticmethod
        def xo(arg1, arg2):
            print('xo')
    
        def start(self):
            temp = '%s sb' % self.name
            return temp
    
        # 特性,将方法伪造成字段,用于获取
        @property
        def end(self):
            temp = '%s sb' % self.name
            return temp
    
        @end.setter
        def end(self, value):
            print(value)
    
    
    hebei = Province('河北')
    
    Province.xo(1, 2)
    
    # 方法本需要加括号访问
    # @property后 可以以访问字段的方式去访问
    obj = Province('alex')
    ret1 = obj.start()
    ret2 = obj.end
    print(ret1, ret2)
    
    # 获取字段
    # print(obj.name)
    # 设置字段
    # obj.name = '123'
    # print(obj.name)
    
    print(obj.end)  # 获取
    obj.end = 123  # 设置
    
    '''
    ************ 规范 **************
    1.通过类访问的有: 静态字段,静态方法,类方法(静态方法的特殊形式)
        Province.country
        Province.xo(1, 2)
    2.通过对象访问的有:普通字段,类的方法
        hebei.name
        hebei.show()
    ************ 规范 **************
    
    3.静态字段存在的意义
        将每个对象都存在的东西只在类里保存一份就行
      
    
    4.静态方法存在的意义
        普通方法执行前需要先创建对象
        静态方法不需要先创建对象,类
        似于将一个普通的函数放在类中,
            在c#和java中非常有用因为他们只能
            面向对象,必须要创建类
        
    5.类方法和静态方法一样,只能通过类访问
        区别在于
            静态方法,参数任意
            类方法会自动获取当前类的类名,作为参数传入
        
    '''
    

      

    5.成员修饰符

      对于私有的,只有自己可以访问,其他(包括子类)都不能访问

      5.1 对于字段
    class Foo:
        A = 'aa'
        __A = 'aa'
    
        def __init__(self):
            self.name = 'alex'
            self.__name = 'wuwen'
    
        def aaa(self):
            print(Foo.__A)
            print(self.__name)
    
        def bbb(self):
            pass
    
    class Bar(Foo):
    
        def fetch(self):
            print(self.__name)
    
    # 静态字段
    print(Foo.A)   # 共有在类外类里均可访问
    #print(Foo.__A)
    obj = Foo()    # 私有只能在类里访问
    obj.aaa()
    
    # 普通字段
    print(obj.__name)  # 不能在外部访问
    obj.aaa()  #  可在外部访问
    
    obj1 = Bar()  #  执行父类的构造方法
    print(obj.__name)  # 继承的子类在外部不能访问
    
    obj1.fetch()  # 不能访问
    obj1.aaa()    # 不能访问
    
      5.2 对于方法
    class Foo:
    
        def __init__(self):
            pass
    
        def __aaa(self):
            print('aaa')
    
        def bbb(self):
            self.__aaa()
    
        @staticmethod
        def __eee():
            print('ddd')
    
        @staticmethod
        def fff():
            Foo.__eee()
    
    
    # 普通方法
    obj = Foo()
    #obj.__aaa()  # 不能直接访问
    obj.bbb()     # 间接访问
    
    # 静态方法
    # Foo.__eee() # 静态方法在外部通过类无法访问
    Foo.fff()     # 间接访问私有的静态方法
    
    # 类方法与特性均是一样的道理
    
      5.3 python与其他语言的区别之处,强行访问私有成员

        对象._类+私有成员

    class Foo:
    
    
        def __init__(self):
            self.name = 'alex'
            self.__name = 'wuwen'
    
        def aaa(self):
            print(self.__name)
    
        def bbb(self):
            pass
    
    obj = Foo()
    # obj.__name  不能直接访问
    print(obj._Foo__name)  # 强行访问
    '''
    wuwen
    '''
    

      

    6.类的特殊成员

      __init__

      __del__

      __call__

      __getitem__

      __setitem__

      __delitem__

      __new__

      __metaclass__

      6.1 对于字典的一些操作,由dict创建的对象为什么可以使用[ ]del等快捷键操作该对象

        __init__

        __getitem__

        __setitem__

        __delitem__

    # dic = dict(k1=123, k2=456)  因为dic类中有__init__方法
    # print(dic['k1'])  为什么对象可以加[]呢  因为dic类中有__getitem__方法
    # dic['k1'] = 456   因为dic类中有__setitem__方法
    # del dic['k2']     因为dic类中有__delitem__方法
    
    class Foo:
        def __init__(self):
            print('init')
    
        def __call__(self, *args, **kwargs):
            print('call')
    
        def __getitem__(self, item):
            print(item)
    
        def __setitem__(self, key, value):
            print(key, value)
    
        def __delitem__(self, key):
            print('模拟删除成功!!')
    
    
    obj = Foo()
    obj()  # 对象后面加()执行__call__
    obj['66']  # 对象后加[]执行__getitem__
    obj['77'] = 77
    del obj['77']
    '''
    init
    call
    66
    77 77
    '''
    
      6.2 对于列表,他的切片操作又是如何在类中实现的呢?

        __getitem__

    r = list([11, 22, 33, 44, 55, 66, 77])
    ret = r[1:6:2]  # 切片
    print(ret)
    
    
    class Foo:
        def __getitem__(self, item):
            print(item, type(item))
    
    
    obj = Foo()
    obj()
    obj[1:3]  # 切片的时候,将1:3传入一个slice类得到一个对象再传入getitem
    '''
    slice(1, 3, None) <class 'slice'>
    '''
    
      6.3  __dict__
    class Foo:
        '''
        我是类的注释
        '''
    
        def __init__(self):
            self.name = 'alex'
            self.gender = 'female'
    
        def __call__(self, *args, **kwargs):
            print('call')
    
        def __getitem__(self, item):
            print(item, type(item))
    
        def __setitem__(self, key, value):
            print(key, value)
    
        def __delitem__(self, key):
            print('模拟删除成功!!')
    
    
    obj = Foo()
    print(obj.__dict__)  # 查看对象封装的字段
    '''
    {'name': 'alex', 'gender': 'female'}
    '''
    print(Foo.__dict__)  # 查看类的成员
    '''
    {'__module__': '__main__', '__doc__': '
        我是类的注释
        ', '__init__': <function Foo.__init__ at 0x000000000220BA60>, 
    '__call__': <function Foo.__call__ at 0x000000000220BAE8>, '__getitem__': <function Foo.__getitem__ at 0x000000000220BB70>, 
    '__setitem__': <function Foo.__setitem__ at 0x000000000220BBF8>, '__delitem__': <function Foo.__delitem__ at 0x000000000220BC80>, 
    '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>}
    '''
    
      6.4  类似于字符串,列表,为什么我们可以用for循环这个对象呢?

        事实上:如果for循环对象的时候,默认执行类中的__iter__方法,是一个生成器

        所以一个对象可以被for循环的话,说明这个对象的类中有__iter__ 方法

    li = [1, 2, 3]  #  等价于 li = list([])
    for i in li:
        print(i)
    '''
    1
    2
    3
    '''
    
    # 实现一个简单版本的list类
    class Foo:
    
        def __iter__(self):
            yield 1
            yield 2
            yield 3
    
    
    li = Foo()
    for i in li:
        print(i)
    '''
    1
    2
    3
    '''
    
      6.5 __new__和__metaclass__

            

  • 相关阅读:
    distributed caching for .net applications
    Linux_18/ mysql
    找到一本不错的Linux电子书,附《Linux就该这么学》章节目录。
    LinuxProbe/ 疑问ABC
    Linux_15/ autofs, DNS
    Linux_14/ SAMBA, NFS
    Linux_13/ 虚拟网站主机功能,Vsftpd
    Linux_12/ Apache, SELinux
    Linux_11/ firewalld-config, SSH, bounding
    Linux_10/ iptables & firewalld
  • 原文地址:https://www.cnblogs.com/wuwen19940508/p/7048284.html
Copyright © 2020-2023  润新知