zoukankan      html  css  js  c++  java
  • Python----面向对象---自定义元类控制类的实例化行为

    一、知识储备

    1、__call__方法

     1 class Foo:
     2     def __call__(self, *args, **kwargs):
     3         print(self)
     4         print(args)
     5         print(kwargs)
     6 
     7 obj = Foo()
     8 obj()
     9 
    10 结果为:
    11 
    12 <__main__.Foo object at 0x000002AFE2B4BDA0>
    13 ()
    14 {}

    实例化时传参

    1 obj(1, 2, 3, a=1, b=2, c=3)  # 相当于执行obj.__call__(obj, 1, 2, 3, a=1, b=2, c=3)
    2 
    3 结果为:
    4 
    5 <__main__.Foo object at 0x000001A1799CBDA0>
    6 (1, 2, 3)
    7 {'a': 1, 'b': 2, 'c': 3}

     元类内部也应该有一个__call__方法,会在调用Foo时触发执行

    Foo(1, 2, x=1)相当于 Foo.__call__(Foo,1,2,x=1)

     1 class Mymeta(type):
     2     def __init__(cls, class_name, class_bases, class_dic):
     3 
     4         if not class_name.istitle():
     5             raise TypeError('类名的首字母必须大写')
     6 
     7         if '__doc__' not in class_dic or not class_dic['__doc__'].strip():
     8             raise TypeError('必须有注释,且注释不能为空')
     9 
    10         super(Mymeta, cls).__init__(class_name, class_bases, class_dic)
    11 
    12     def __call__(cls, *args, **kwargs):
    13         print('=====>')
    14 
    15 
    16 class Chinese(object, metaclass=Mymeta):
    17     '''
    18     xxx
    19     '''
    20 
    21     country = 'China'
    22 
    23     def __init__(self, name, age):
    24         self.name = name
    25         self.age = age
    26 
    27     def talk(self):
    28         print('%s is talking' % self.name)
    29 
    30 
    31 obj = Chinese('egon', 18)
    32 
    33 执行结果为:
    34 
    35 =====>

    可以看出,Chinese类实例化会触发它的父类的__call__方法,

    我们先看一下__call__方法的传值

     1     def __call__(cls, *args, **kwargs):
     2         print(cls)
     3         print(args)
     4         print(kwargs)
     5 
     6 结果为:
     7 
     8 <class '__main__.Chinese'>
     9 ('egon', 18)
    10 {}
    1     def __call__(cls, *args, **kwargs):
    2         print(cls)  # cls = Chinese
    3         print(args)  # args = ('egon',)
    4         print(kwargs)  # kwargs = {'age': 18}
    5 
    6 obj = Chinese('egon', age=18)  # Chinese.__call__(chinese,'egon',age=18)

    要想控制Chinese类的实例化,就要在它的元类的__call__方法上下功夫

    __call__方法会做3件事:

    1、先造一个空对象obj

    2、初始化obj

    3、返回obj

     1     def __call__(cls, *args, **kwargs):
     2         # print(cls)  # cls = Chinese
     3         # print(args)  # args = ('egon',)
     4         # print(kwargs)  # kwargs = {'age': 18}
     5         obj = object.__new__(cls)
     6         cls.__init__(obj, *args, **kwargs)
     7         return obj
     8 
     9 obj = Chinese('egon', age=18)  # Chinese.__call__(chinese,'egon',age=18)
    10 print(obj.__dict__)
    11 
    12 结果为:
    13 
    14 
    15 {'name': 'egon', 'age': 18}

    实例化成功了,

  • 相关阅读:
    Qt类继承关系图
    回归Qt——写在Qt5.10发布之日
    Jdk1.7下的HashMap源码分析
    Jdk1.8下的HashMap源码分析
    八皇后||算法
    设计模式之一单例模式
    多线程之美8一 AbstractQueuedSynchronizer源码分析<二>
    多线程之美7一ReentrantReadWriteLock源码分析
    多线程之美6一CAS与自旋锁
    多线程之美5一 AbstractQueuedSynchronizer源码分析<一>
  • 原文地址:https://www.cnblogs.com/xudachen/p/8660844.html
Copyright © 2011-2022 走看看