zoukankan      html  css  js  c++  java
  • 第五章-面向对象-1.元类介绍/2.自定义元类控制类的行为/3.控制类的实例化行为/4.控制类的实例化行为的应用

    1.元类介绍

    1.储备知识exec()
    参数1;字符串形式得命令
    参数2.全局作用域(字典形式),如果不指定默认就使用globals()
    参数3.局部作用域(字典形式),如果不指定默认就使用locals()

    2.python 一切皆对象 ,对象可以怎么用?
    2.1. 都可以被引用 x=obj
    2.2. 都可以当作函数得参数传入
    2.3. 都可以当作函数得返回值
    2.4. 都可以当作容器类得元素 li=[func,time]

    # 类也是对象,Foo=type() 类是属于type() 类

    3.什么叫元类
    类得类就叫元类 type type(Foo) == <class 'type'>
    产生类得类称之为元类,默认所有用class定义得类,他们得元类是type
    元类(type) --> 实例化 --> 类(class)--> 实例化 --> 对象

    4.定义类得两种方式:
    4.1 class 关键字得方式 class Chinese:
    4.2 type 元类 定义类得三要素:类名,类的基类们,类得名称空间
    Chinese1=type(class_name,class_bases,class_dic)
     1 # print(globals())
     2 # g = {
     3 #     'x':1,
     4 #     'y':2
     5 # }
     6 #
     7 # l = {}
     8 
     9 # exec当做一个函数
    10 # exec("""
    11 # global x,m
    12 # x = 10
    13 # m = 100
    14 #
    15 # z = 3
    16 # """,g,l)
    17 # print(g)
    18 # print(l)
    19 #-------------------------------------------------------------
    20 # 类也是对象,Foo = type(...)
    21 # class Foo:
    22 #     pass
    23 #
    24 # obj = Foo()
    25 # print(type(obj),type(Foo))
    26 # # <class '__main__.Foo'> <class 'type'>
    27 
    28 
    29 # 产生类的类称之为元类,默认所有用class定义的类,他们的元类是type
    30 
    31 #--------------------------------------------------------------
    32 # 定义类的两种方式:
    33 # 方式一:class
    34 
    35 class Chinese: # Chinese = type(...) # Chinese类就是调用了一个type类实例化得到的
    36     country = 'China'
    37 
    38     def __init__(self,name,age):
    39         self.name = name
    40         self.age = age
    41 
    42     def talk(self):
    43         print('%s is talking ' % self.name)
    44 
    45 # print(Chinese)
    46 obj = Chinese('egon',18)
    47 print(obj,obj.name,obj.age)
    48 
    49 # 方式二:type
    50 # 类定义三要素:
    51 # 1.类名:
    52 class_name = 'Chinese'
    53 
    54 # 2.继承,类的基类们:
    55 class_bases = (object,)
    56 
    57 # 3.名称空间:
    58 class_body = """
    59 country = 'China'
    60 
    61 def __init__(self,name,age):
    62     self.name = name
    63     self.age = age
    64 
    65 def talk(self):
    66     print('%s is talking ' % self.name)
    67 """
    68 class_dic = {}
    69 exec(class_body,globals(),class_dic)
    70 # print(class_dic)
    71 
    72 # 实例化元类得到一个元类的对象也就是用class 声名的一个类
    73 Chinese1 = type(class_name,class_bases,class_dic)
    74 # print(Chinese1)
    75 obj1 = Chinese1('egon',18)
    76 print(obj1,obj1.name,obj1.age)
    2.自定义元类控制类的行为
    自定义元类 来控制 类的行为 控制类的创建行为
     1 class Mymeta(type):
     2     def __init__(self,class_name,class_bases,class_dic):
     3         # print(class_name)
     4         # print(class_bases)
     5         # print(class_dic)
     6         if not class_name.istitle():
     7             raise TypeError('类名的首字母必须为大写')
     8 
     9         if '__doc__' not in class_dic or not class_dic['__doc__'].strip():
    10             raise TypeError('必须有注释,且注释不能为空')
    11         super(Mymeta,self).__init__(class_name,class_bases,class_dic)
    12 
    13 class Chinese(object,metaclass=Mymeta):
    14     '''1'''
    15     country = 'China'
    16 
    17     def __init__(self,name,age):
    18         self.name = name
    19         self.age = age
    20 
    21     def talk(self):
    22         print('%s is talking ' % self.name)
    23 
    24 # Chinese = Mymeta(class_name,class_bases,class_dic)
    25 
    26 
    27 # raise TypeError('类型错误!')
    28 
    29 # class Foo:
    30 #     pass
    31 # print(Foo.__dict__)

    3.控制类的实例化行为
    知识储备 __call__方法
    obj(1,2,3,a=1,b=2,c=3) # 对象在调用时 会触发 __call__
    ------------------------------------
    #生成对象步骤 --》 #1.先造空对象 2.初始化 3.返回值
    def __call__(self, *args, **kwargs): 在元类的__call__()方法中实现
    # 1.先造一个空对象
    obj=object.__new__(self)
    # 2.初始化obj
    self.__init__(obj,*args,**kwargs)
    # 3.返回obj
    return obj

    总结:元类
    __init__ 控制类的创建
    __call__ 控制类的实例化
     1 # 如果希望对象可调用,可以在对象的类中写一个__call__方法,调用的时候触发该方法
     2 # class Foo:
     3 #     def __call__(self, *args, **kwargs):
     4 #         print(self)
     5 #         print(args)
     6 #         print(kwargs)
     7 #
     8 # obj = Foo()
     9 # obj(1,2,3,a=1,b=2,c=3) # obj.__call__(obj,1,2,3,a=1,b=2,c=3)
    10 #
    11 # # 元类内部也应该有一个__call__方法,会在调用Foo时触发执行
    12 # # Foo(1,2,x=1) # Foo.__call__(Foo,1,2,x=1)
    13 
    14 
    15 class Mymeta(type):
    16     def __init__(self,class_name,class_bases,class_dic):
    17         if not class_name.istitle():
    18             raise TypeError('类名的首字母必须为大写')
    19 
    20         if '__doc__' not in class_dic or not class_dic['__doc__'].strip():
    21             raise TypeError('必须有注释,且注释不能为空')
    22         super(Mymeta,self).__init__(class_name,class_bases,class_dic)
    23 
    24     def __call__(self, *args, **kwargs): # obj = Chinese('egon',18)
    25         # print('=====>')
    26         # print(self) # self = Chinese
    27         # print(args) # args = ('egon', 18)
    28         # print(kwargs) # kwargs = {}
    29         # 第一件事:先造一个空对象obj
    30         obj = object.__new__(self)
    31         # 第二件事:初始化obj
    32         self.__init__(obj,*args,**kwargs)
    33         # 第三件事:返回obj
    34         return obj
    35 class Chinese(object,metaclass=Mymeta):
    36     '''1'''
    37     country = 'China'
    38 
    39     def __init__(self,name,age):
    40         self.name = name
    41         self.age = age
    42 
    43     def talk(self):
    44         print('%s is talking ' % self.name)
    45 
    46 obj = Chinese('egon',18)  # Chinese.__call__(Chinese,'egon',18)
    47 print(obj.__dict__)
    4.自定义元类控制类的实例化行为的应用
    单例模式: 对象的参数都一样 实质就是一个对象  不要在申请新的内容空间 直接使用一个 就是单例模式
    eg: 单例模式对id的应用 obj1 和 obj2 公用一块内存 “优化策略”
    >>> obj1=int(1)
    >>> obj2=int(1)
    >>> obj1 is obj2
    True
    >>> id(obj1)
    1897295328
    >>> id(obj2)
    1897295328
    --------------------------------
    自己定义的类 对象内部的特征如果是一样的就公用一块内存 用单例模式呢:
    实现单例模式 是一种 优化策略 多个对象公用一块内存
    __instance=None #__instance=obj1
    def singleton(cls):
    print(obj1 is obj2)
    -------------------------------
    单例模式的实现方式:1.@classmethod def singleton(cls):
    2.利用元类实现
     1 # 单例模式:
     2 # 实现方式一:
     3 # class MySQL:
     4 #     __instance = None # __instance = obj1
     5 #
     6 #     def __init__(self):
     7 #         self.host = '127.0.0.1'
     8 #         self.port = 3306
     9 #
    10 #     @classmethod
    11 #     def singleton(cls):
    12 #         if not cls.__instance:
    13 #             obj = cls()
    14 #             cls.__instance = obj
    15 #         return cls.__instance
    16 #
    17 #     def conn(self):
    18 #         pass
    19 #
    20 #     def execute(self):
    21 #         pass
    22 #
    23 # # obj1 = MySQL()
    24 # # obj2 = MySQL()
    25 # # obj3 = MySQL()
    26 #
    27 # # print(obj1)
    28 # # print(obj2)
    29 # # print(obj3)
    30 # # <__main__.MySQL object at 0x002CF6F0>
    31 # # <__main__.MySQL object at 0x002CF6D0>
    32 # # <__main__.MySQL object at 0x002CFF30>
    33 #
    34 # obj1 = MySQL.singleton()
    35 # obj2 = MySQL.singleton()
    36 # obj3 = MySQL.singleton()
    37 #
    38 # print(obj1)
    39 # print(obj2)
    40 # print(obj3)
    41 # # <__main__.MySQL object at 0x01EAFF70>
    42 # # <__main__.MySQL object at 0x01EAFF70>
    43 # # <__main__.MySQL object at 0x01EAFF70>
    44 
    45 # 实现方式二:元类的方式
    46 
    47 class Mymeta(type):
    48     def __init__(self,class_name,class_bases,class_dic):
    49         if not class_name.istitle():
    50             raise TypeError('类名的首字母必须为大写')
    51 
    52         if '__doc__' not in class_dic or not class_dic['__doc__'].strip():
    53             raise TypeError('必须有注释,且注释不能为空')
    54         super(Mymeta,self).__init__(class_name,class_bases,class_dic)
    55         self.__instance = None
    56 
    57 
    58     def __call__(self, *args, **kwargs): # obj = Chinese('egon',18)
    59         if not self.__instance:
    60             obj = object.__new__(self)
    61             self.__init__(obj,*args,**kwargs)
    62             self.__instance = obj
    63         return self.__instance
    64 
    65 class Mysql(object,metaclass=Mymeta):
    66     '''1'''
    67     def __init__(self):
    68         self.host = '127.0.0.1'
    69         self.port = 3306
    70 
    71     def conn(self):
    72         pass
    73 
    74     def execute(self):
    75         pass
    76 
    77 obj1 = Mysql()
    78 obj2 = Mysql()
    79 obj3 = Mysql()
    80 print(obj1)
    81 print(obj2)
    82 print(obj3)
    83 # <__main__.Mysql object at 0x0034C090>
    84 # <__main__.Mysql object at 0x0034C090>
    85 # <__main__.Mysql object at 0x0034C090>
     
     
  • 相关阅读:
    数据结构2
    EF Fluent API
    VS2017+mysql5.7 连接数据库生成实体
    JavaScript中的枚举
    EasyUI datagird 排序 按数字类型的问题
    php 将秒数转换为时间(年、天、小时、分、秒)
    mySQL把秒转换成日期
    Android 界面间传参数
    android 登陆界面
    Android 在已有的项目上创建新的项目
  • 原文地址:https://www.cnblogs.com/mumupa0824/p/8964980.html
Copyright © 2011-2022 走看看