元类

exec

参数1:字串形式命令
参数2:全局作用域(字典形式),如果不指定默认就使用globals()
参数3:局部作用域(字典形式),如果不指定默认就使用locals()

g = {"x":1,"y":2}
l = {}
exec('''
global x,m
x=10
m=100
z = 3''',g,l)     # 引号中产生一个变量,变量放到局部作用域中
print(g)
print(l)

  引号中产生一个变量,变量放到局部作用域中

python中一切皆对象。


对象使用:
  1、都可以被引用,x=obj
  2、都可以当做函数的参数传入
  3、都可以当做函数的返回值
  4、都可以当做容器类的元素(列表、元组、字典、集合,可以装多种值)


 

元类

产生类的类称之为元类,默认用class定义的类,他们的元类是type

定义类的两种方式:

方式一:class

class Chinese(objext,metaclass = type):   # Chinese = type(...) metaclass元类
    country = "China"
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def talk(self):
        print("%s is talking" %self.name)

方式二:type
定义类的三要素:类名、类的基类们。类的名称空间
类名(字符串):class_name = "Chinese"
继承(元组形式):class_bases = (object,)
类体(定义阶段类体代码立即执行)类的名称空间(字典形式):class_dic

# 类的名称空间的产生
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)
#实例化
Chinese = type(class_name,class_bases,class_dic) # 实例化元类,得到元类的对象(就是用class声明的类)

自定义元类,控制类的行为

class Foo:
    """注释"""
    pass
print(Foo.__dict__)

#__doc__ 存放注释信息

class Mymeta(type):
    def __init__(self,class_name,class_bases,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)


class Chinese(object,metaclass = Mymeta):
    """自定义元类"""
    country = "China"
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def talk(self):
        print("%s is talking" %self.name)

 


自定义元类,控制实例化的行为

__call__

# __call__方法 调用对象会触发__call__,将对象本身连同参数一起传入该方法中。

__call__控制类的实例化行为

__init__控制类的创建行为

class Foo:
    def __call__(self, *args, **kwargs):
        print(self)
        print(args)
        print(kwargs)
obj = Foo()
obj(1,2,3,a=1,b=2,c=3)   # obj.__call__(obj,1,2,3,a=1,b=2,c=3)

<__main__.Foo object at 0x000002C36C7F0358>
(1, 2, 3)
{'a': 1, 'b': 2, 'c': 3

元类内部也应该有一个__call__方法,会在调用Foo时触发执行
Foo(1,2,x=1) # Foo.__call__(Foo,1,2,x=1)

class Mymeta(type):
    def __init__(self,class_name,class_bases,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)     # self= Chinese
        print(args)     # args=('alex',)
        print(kwargs)   # kwargs={'age': 18}


class Chinese(object,metaclass = Mymeta):
    """自定义元类"""
    country = "China"
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def talk(self):
        print("%s is talking" %self.name)

obj = Chinese("alex",age=18)      # Chinese.__call__(Chinese,"alex",18)

<class '__main__.Chinese'>
('alex',)
{'age': 18}

控制类的实例化行为

class Mymeta(type):
    def __init__(self,class_name,class_bases,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):   #obj = Chinese("alex",age=18)
        # print(self)     # self= Chinese
        # print(args)     # args=('alex',)
        # print(kwargs)   # kwargs={'age': 18}
        # 第一步:创造一个空对象
        obj = object.__new__(self)
        # 第二部:初始化obj
        self.__init__(obj,*args, **kwargs)
        # 第三部:返回obj
        return obj


class Chinese(object,metaclass = Mymeta):
    """自定义元类"""
    country = "China"
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def talk(self):
        print("%s is talking" %self.name)

obj = Chinese("alex",age=18)      # Chinese.__call__(Chinese,"alex",18)
print(obj.__dict__)

  {'name': 'alex', 'age': 18}


自定义元类控制类的实例化行为的应用

单例模式 参数一样,不要再新生新的内存空间

实现方式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

    def conn(self):
        pass
    def execute(self):
        pass

obj1 = MySQL.singleton()
obj2 = MySQL.singleton()

print(obj1 is obj2)

True

实现方式2:通过元类实现

class Mymeta(type):
    def __init__(self,class_name,class_bases,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)
        self.__instance = None

    def __call__(self, *args, **kwargs):   #控制类的实例化行为
        # 第一步:创造一个空对象
        if not self.__instance:
            obj = object.__new__(self)
        # 第二部:初始化obj
        self.__init__(self)
        self.__instance = obj
        # 第三部:返回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.singleton()
obj2 = Mysql.singleton()

print(obj1 is obj2)

  True

 

posted @ 2018-11-05 19:53  混世妖精  阅读(142)  评论(0编辑  收藏  举报