Top

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

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

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

    # #####示例一:验证 类 或 对象 是否能做字典的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__方法中返回的对象内存地址一样,但一个无数据,一个有数据

 

posted @ 2018-08-29 15:06  勇敢的巨蟹座  阅读(213)  评论(0编辑  收藏  举报