元类

元类

python中一切皆对象,其类也是对象

对象的要求或者意义:

  • 可以被引用,例如:x=obj
  • 可以当作函数进行参数传入
  • 可以作为容器类的元素
  • 可以当作函数的返回值

1.元类的含义:产生类的类称之为元类,默认所有用class定义的类,他们的元类都是type

python中运用关键字class定义类的过程是:class(A)  其实就是 type实例化出来的,之后再由类实例化产生对象

2.定义类的两种形式

通过class关键字:class(Chinese) : #Chinese = type(...)

通过type: 定义出类的三要素:类的名称,类的基类,类的名称空间

3.自定义元类的应用

3.1可以控制类的具体行为

通过def __init__(self,class_name,class_bases,class_dic),获取到类的名称,类的基类,类的名称空间

之后运用class Chinese(object,metaclass=Mymeta) ,利用元类中的__init__来进行控制类名,类体的操作

def __init__(self,class_name,class_bases,class_dic):
     if not class_name.istitle():
          raise TypeError('类名的首字母必须大写')

3.2可以控制类的实例化过程

通过def __call__(self,*args,**kwargs):进而得到对象的属性,

之后在进行三步操作:

  • 创建空对象
  • 初始化对象
  • 返回对象值
    def __call__(self, *args, **kwargs): #Chinese('egon',age=18)
        # print(self) #self=Chinese
        # print(args) #args=('egon',)
        # print(kwargs) #kwargs={'age':18}

        #第一件事: 造出一个空对象obj
        obj=object.__new__(self)
        #第二件事: 初始化obj
        self.__init__(obj,*args,**kwargs)
        #第三件事: 返回obj
        return obj

4.单例模式

运用python实现单例模式有两种方法:

1.定义一个绑定类的绑定方法

class MySQL:
    __instance = None

    def __init__(self):
        self.host='127.0.0.1'
        self.port=3306

    @classmethod
    def singleton(cls):
        if not cls.__instance:
            obj = cls()
            cls.__instance=obj
        return cls.__instance

2.通过元类中的内置方法__call__来实现

class Mymeta(type):
    def __init__(self,class_name,class_bases,class_dic):


        super(Mymeta,self).__init__(class_name,class_bases,class_dic)
        self.__instance=None

    def __call__(self, *args, **kwargs): #Chinese('egon',age=18)
        if not self.__instance:
            obj=object.__new__(self)
            self.__init__(obj)
            self.__instance=obj

        return self.__instance
# class Foo:
#     pass
# f=Foo()
# print(type(f))
# print(type(Foo))

# g={'x':1,'y':2}
# l={}
# exec("""
# global x,m
# x=10
# m=100
# z=3
# """,g,l)
# print(g)
# print(l)
# -------------------------
# 产生类得第一种方式:
class Chinese:
    country='China'
    def __init__(self,name,age):
        self.name=name
        self.age=age

    def talk(self):
        print('%s is talking'%self.name)

# obj=Chinese('alice',12)
# obj.talk()
# print(obj.name,obj.age)

#产生类得第二种方式:
class_name='Chinese'
class_base=(object,)
class_body="""
country='China'
def __init__(self,name,age):
    self.name=name
    self.age=age

def talk(self):
    print('%s is talking'%self.name)
"""
# class_dic={}
# exec(class_body,globals(),class_dic)
# # print(class_dic)
# ch = type(class_name,class_base,class_dic)
# obj1=ch('alice',12)
# print(obj1.__dict__)
# print(ch.__dict__)
# print(ch)
# print(obj1,obj1.name,obj1.age)

#自定义元类 控制类的行为:
class Mymeta(type):  #元类
    # print('--1--')
    def __init__(self,class_name,class_bases,class_dic):   # 控制类的创建
        # print(class_name)
        # print(class_bases)
        # print(class_dic)
        if not class_name.istitle():
            raise TypeError('类名的首字母必须大写')
        if '__doc__' not in class_dic or not class_dic['__doc__'].strip():
            raise TypeError('必须有注释,且注释不能为空')

        super(Mymeta, self).__init__(class_name,class_bases,class_dic)

    def __call__(self, *args, **kwargs):  # 控制类的实例化
        # print(self)
        # print(args)
        # print(kwargs)
        obj=object.__new__(self)           #1.造空对象
        self.__init__(obj,*args,**kwargs)  #2.初始化obj
        return obj                        #返回obj


class Chinese(object,metaclass=Mymeta):
    '''
    中文人的类
    '''
    country='China'
    def __init__(self,name,age):
        print('--2--')
        self.name=name
        self.age=age

    def talk(self):
        print('%s is talking'%self.name)

    def __call__(self, *args, **kwargs):
        print(self)
        print(args)
        print(kwargs)


# obj=Chinese('alice',12)   # 触发它的类的 __call__() 元类
# obj(1,2,3,a=1,b=2)    # 触发它的类的 __call__()  Chinese
# print(obj.__dict__)
# print(Chinese.__dict__)
#
# print(type(Chinese))
# Chinese=Mymeta(class_name,class_bases,class_dir)
# print(obj.__dict__)

#自定义元类的应用:

# obj1=int(1)
# obj2=int(1)
# print(id(obj1))
# print(id(obj2))
# print(obj1 is obj2)  # 实现了单例模式 参数相同 多个对象 使用同一块内存 是一种优化策略

# 单例模式 实现方式一:

class Mymeta(type):
    def __init__(self,class_name,class_bases,class_dic):
        super().__init__(class_name,class_bases,class_dic)
        self.__instance=None

    def __call__(self, *args, **kwargs):
        if not self.__instance:
            obj = object.__new__(self)
            self.__init__(obj)
            self.__instance=obj
        return self.__instance



class Mysql(object,metaclass=Mymeta):
    # __instance=None
    def __init__(self):
        self.host='127.0.0.1'
        self.port=3306

    # @classmethod
    # def singleton(cls):
    #     if not cls.__instance:
    #         obj=cls()
    #         cls.__instance=obj
    #     return cls.__instance

    def conn(self):
        pass

    def execute(self):
        pass

# obj1=Mysql()
# obj2=Mysql()
# print(obj2.__dict__)
# print(id(obj1))
# print(id(obj2))

# obj1=Mysql.singleton()
# obj2=Mysql.singleton()
# # print(obj1.__dict__)
# print(id(obj1))
# print(id(obj2))

# obj1=Mysql()
# obj2=Mysql()
# print(id(obj1))
# print(id(obj2))

 

原文地址:https://www.cnblogs.com/Mryang123/p/8620740.html