• 面向对象进阶二(组合补充、主动调用其他类的成员、特殊成员)


    一、组合补充(重要程度*****)

      分析如下几个示例的代码和结果,并作出总结:

        # #####示例一:验证 类 或 对象 是否能做字典的key
        class Foo:
            pass
        user_info = {
            Foo : 1,  # 类 做字典的key
            Foo() : 5  # 对象 做字典的key
        }
        print(user_info)
        # {<class '__main__.Foo'>: 1, <__main__.Foo object at 0x00000000029284E0>: 5}
        # #####示例二:对象中到底有什么?
        class Foo(object):
            def __init__(self,age):
                self.age = age
            def display(self):
                print(self.age)
    
        data_list = [Foo(8),Foo(9)]
        for item in data_list:
            print(item.age,item.display())
        # 结果为:
        # 8
        # 8 None
        # 9
        # 9 None
        # #####示例三.
        class StarkConfig(object):
            def __init__(self,num):
                self.num = num
            def changelist(self,request):
                print(self.num,request)
    
        class RoleConfig(StarkConfig):
            def changelist(self,request):
                print('666')
        # 创建了一个列表,列表中有三个对象(实例)
        config_obj_list = [StarkConfig(1),StarkConfig(2),RoleConfig(3)]
        for item in config_obj_list:
            print(item.num)
        # 结果为:
        # 1
        # 2
        # 3   
        # 分析:RoleConfig类中没有__init__方法,创建对象时又传了一个参数3,
        # 所以就去父级查找有没有__init__,有则执行,在所创建的对象中封装数据3
        # #####示例四
        class StarkConfig(object):
            def __init__(self,num):
                self.num = num
            def changelist(self,request):
                print(self.num,request)
            def run(self):
                self.changelist(999)
    
        class RoleConfig(StarkConfig):
            def changelist(self,request):
                print(666,self.num)
    
        config_obj_list = [StarkConfig(1),StarkConfig(2),RoleConfig(3)]
        config_obj_list[1].run()  # 2 999
        config_obj_list[2].run()  # 666 3
        # #####示例五
        class UserInfo(object):
            pass
    
        class Department(object):
            pass
    
        class StarkConfig(object):
            def __init__(self,num):
                self.num = num
            def changelist(self,request):
                print(self.num,request)
            def run(self):
                self.changelist(999)
    
        class RoleConfig(StarkConfig):
            def changelist(self,request):
                print(666,self.num)
    
        class AdminSite(object):
            def __init__(self):
                self._registry = {}
            def register(self,k,v):
                self._registry[k] = v(k)
    
        site = AdminSite()
        site.register(UserInfo,StarkConfig)
        site.register(Department,StarkConfig)
        print(len(site._registry)) # 2
        for k,row in site._registry.items():
            row.run()
        # 结果为:
        # <class '__main__.UserInfo'> 999
        # <class '__main__.Department'> 999

      总结:

        1)对象 和 类 可以做字典的key

        2)明确对象中到底封装了什么

        3)哪个对象.方法,那么self就是这个对象,就从这个对象的类开始找

    二、主动调用其他类的成员(***)

      如何主动调用其他类的成员,如下两种方式:

        # #####方式一:Base.实例方法(自己传self)   与继承无关
        class Base(object):
            def f1(self):
                print('5个功能', self)
    
        class Foo(object):
            def f1(self):
                print('3个功能')
                Base.f1(self) # 此时,参数必须要写,python不会自动传,写什么传什么
    
        obj = Foo()
        obj.f1()
        # 结果为:
        # 3个功能
        # 5个功能 <__main__.Foo object at 0x0000000002718D68>
        # #####方式二:按照类的继承顺序,找下一个.
        class Foo(object):
            def f1(self):
                super().f1()
                print('3个功能')
    
        class Bar(object):
            def f1(self):
                print('6个功能')
    
        class Info(Foo,Bar):  # 查找顺序:Info Foo Bar
            pass
    
        obj = Info()
        obj.f1()
        # 结果为:
        # 6个功能
        # 3个功能

    三、特殊成员(目前是***,越往后期越重要,越看源码用的越多)

    1、按照某种语法会自动执行某些方法,如下示例:
      class Foo(object):
          def __init__(self, a1, a2):
              self.a1 = a1
              self.a2 = a2
    
          def __call__(self, *args, **kwargs):
              print('call', args, kwargs)
              return 123
    
          def __getitem__(self, item):
              print(item)
              return 8
    
          def __setitem__(self, key, value):
              print(key, value, 'setitem')
    
          def __delitem__(self, key):
              print(key)
    
          def __add__(self, other):
              return self.a1 + other.a2
    
          def __enter__(self):
              print('enter')
              return '执行__enter__方法'
    
          def __exit__(self, exc_type, exc_val, exc_tb):
              print('exit')
      # 1. 类名()   自动执行 __init__
      obj = Foo(1,2)
    
      # 2. 对象()   自动执行 __call__
      ret = obj(6,4,2,k1=456)  # call (6, 4, 2) {'k1': 456}
      print(ret)  # 123
    
      # 3. 对象['xx']   自动执行 __getitem__
      ret = obj['yu']
      print(ret)  # yu
    
      # 4. 对象['xx'] = 11   自动执行 __setitem__
      obj['k1'] = 123  # k1 123 setitem
    
      # 5. del 对象[xx]   自动执行 __delitem__
      del obj['delitem']  # delitem
    
      # 6. 对象+对象   自动执行 __add__
      obj1 = Foo(1,2)
      obj2 = Foo(88,99)
      ret = obj2 + obj1
      print(ret)  # 90
    
      # 7. with 对象   自动执行 __enter__ / __exit__
      obj = Foo(1,2)
      with obj as f:
          print(f)  # 执行__enter__方法
          print('内部代码')
    2、真正的构造方法
      class Foo(object):
          def __init__(self, a1, a2):     # 初始化方法
              """
              为空对象进行数据初始化
              """
              self.a1 = a1
              self.a2 = a2
    
          def __new__(cls, *args, **kwargs): # 构造方法
              """
              创建一个空对象
              若不写__new__,则会由所有类的父类object的__new__来创建
              :return:
              """
              return object.__new__(cls) # Python内部创建一个当前类的对象并返回(初创时内部是空的.)
    
      obj1 = Foo(1,2)   # 先执行 __new__() 方法,再执行 __init__() 方法
      print(obj1)       # 此对象内存地址与__new__方法中返回的对象内存地址一样,但一个无数据,一个有数据
  • 相关阅读:
    Sprng Data JPA与hibernate的关系
    Exception in thread "main" java.io.FileNotFoundException: d:xxx.txt (拒绝访问。)
    Telnet测试BIO Socket
    计算机网络篇
    Postman测试接口发现时间少8个小时?添加这两行代码就解决!
    匿名内部类
    解决线程安全的三种方法
    equals和hashcode的区别
    postman测试springsecurity 登录鉴权,获取Cookie后进行其他接口测试
    (链表)求相交链表交点
  • 原文地址:https://www.cnblogs.com/li-li/p/9554401.html
Copyright © 2020-2023  润新知