元类-成都快上网建站

元类

1.首先介绍exec

exec:三个参数
参数一:字符串形式的命令
参数二:全局作用域(字典形式),如果不指定,默认为globals()
参数三:局部作用域(字典形式),如果不指定,默认为locals()

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author: vita
g={
'x':1,
'y':2
}
l={}

exec('''
global x,z
x=100
z=200

m=300
''',g,l)

print(g) #{'x': 100, 'y': 2,'z':200,......}
print(l) #{'m': 300}

E:\PythonProject\python-test\venvP3\Scripts\python.exe E:/PythonProject/python-test/BasicGrammer/test.py
{'x': 100, 'y': 2, '__builtins__': {'__name__': 'builtins', '__doc__': "Built-in functions, exceptions, and other objects.\n\nNoteworthy: None is the `nil' object; Ellipsis represents `...' in slices.", '__package__': '', '__loader__': , '__spec__': ModuleSpec(name='builtins', loader=), '__build_class__': , '__import__': , 'abs': , 'all': , 'any': , 'ascii': , 'bin': , 'callable': , 'chr': , 'compile': , 'delattr': , 'dir': , 'divmod': , 'eval': , 'exec': , 'format': , 'getattr': , 'globals': , 'hasattr': , 'hash': , 'hex': , 'id': , 'input': , 'isinstance': , 'issubclass': , 'iter': , 'len': , 'locals': , 'max': , 'min': , 'next': , 'oct': , 'ord': , 'pow': , 'print': , 'repr': , 'round': , 'setattr': , 'sorted': , 'sum': , 'vars': , 'None': None, 'Ellipsis': Ellipsis, 'NotImplemented': NotImplemented, 'False': False, 'True': True, 'bool': , 'memoryview': , 'bytearray': , 'bytes': , 'classmethod': , 'complex': , 'dict': , 'enumerate': , 'filter': , 'float': , 'frozenset': , 'property': , 'int': , 'list': , 'map': , 'object': , 'range': , 'reversed': , 'set': , 'slice': , 'staticmethod': , 'str': , 'super': , 'tuple': , 'type': , 'zip': , '__debug__': True, 'BaseException': , 'Exception': , 'TypeError': , 'StopAsyncIteration': , 'StopIteration': , 'GeneratorExit': , 'SystemExit': , 'KeyboardInterrupt': , 'ImportError': , 'ModuleNotFoundError': , 'OSError': , 'EnvironmentError': , 'IOError': , 'WindowsError': , 'EOFError': , 'RuntimeError': , 'RecursionError': , 'NotImplementedError': , 'NameError': , 'UnboundLocalError': , 'AttributeError': , 'SyntaxError': , 'IndentationError': , 'TabError': , 'LookupError': , 'IndexError': , 'KeyError': , 'ValueError': , 'UnicodeError': , 'UnicodeEncodeError': , 'UnicodeDecodeError': , 'UnicodeTranslateError': , 'AssertionError': , 'ArithmeticError': , 'FloatingPointError': , 'OverflowError': , 'ZeroDivisionError': , 'SystemError': , 'ReferenceError': , 'BufferError': , 'MemoryError': , 'Warning': , 'UserWarning': , 'DeprecationWarning': , 'PendingDeprecationWarning': , 'SyntaxWarning': , 'RuntimeWarning': , 'FutureWarning': , 'ImportWarning': , 'UnicodeWarning': , 'BytesWarning': , 'ResourceWarning': , 'ConnectionError': , 'BlockingIOError': , 'BrokenPipeError': , 'ChildProcessError': , 'ConnectionAbortedError': , 'ConnectionRefusedError': , 'ConnectionResetError': , 'FileExistsError': , 'FileNotFoundError': , 'IsADirectoryError': , 'NotADirectoryError': , 'InterruptedError': , 'PermissionError': , 'ProcessLookupError': , 'TimeoutError': , 'open': , 'quit': Use quit() or Ctrl-Z plus Return to exit, 'exit': Use exit() or Ctrl-Z plus Return to exit, 'copyright': Copyright (c) 2001-2017 Python Software Foundation.
All Rights Reserved.

Copyright (c) 2000 BeOpen.com.
All Rights Reserved.

Copyright (c) 1995-2001 Corporation for National Research Initiatives.
All Rights Reserved.

Copyright (c) 1991-1995 Stichting Mathematisch Centrum, Amsterdam.
All Rights Reserved., 'credits':     Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands
    for supporting Python development.  See www.python.org for more information., 'license': Type license() to see the full license text, 'help': Type help() for interactive help, or help(object) for help about object.}, 'z': 200}
{'m': 300}

Process finished with exit code 0

2.元类

2.1元类是什么

元类是用于创建类的类,是类的模板
元类是用来控制如何创建类的,正如类是创建对象的模板一样,而元类是为了控制类的创建行为
元类的实例化结果为我们用class定义的类,正如类的实例化是对象(f1对象是Foo类的一个实例,Foo类是type类的一个实例)
type是python的一个内建元类,用来直接控制生成类,Python中任何class定义的类其实都是type类实例化的对象。

成都创新互联公司服务项目包括梨树网站建设、梨树网站制作、梨树网页制作以及梨树网络营销策划等。多年来,我们专注于互联网行业,利用自身积累的技术优势、行业经验、深度合作伙伴关系等,向广大中小型企业、政府机构等提供互联网行业的解决方案,梨树网站推广取得了明显的社会效益与经济效益。目前,我们服务的客户以成都为中心已经辐射到梨树省份的部分城市,未来相信会继续扩大服务区域并继续获得客户的支持与信任!

2.2type创建类的方式

"方式一:使用class关键字创建的类"
class Chinese(object):
    country='China'
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def talk(self):
        print('%s is talking' %self.name)
"方式二:使用type创建类"
#准备工作:
type(class_name,class_bases,class_dic)
#type创建类主要分为三部分
  1 类名===class_name
  2 类的父类===class_bases
  3 类体===class_dic==即类的内容,可使用exec产生

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author: vita
#类名
class_name='Chinese'
#类的父类
class_bases=(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)
"""
#步骤一(先处理类体->名称空间):类体定义的名字都会存放于类的名称空间中(一个局部的名称空间),
# 我们可以事先定义一个空字典,
# 然后用exec去执行类体的代码(exec产生名称空间的过程与真正的class过程类似,只是后者会将__开头的属性变形),
# 生成类的局部名称空间,即填充字典
class_dic={}
exec(class_body,globals(),class_dic)
print("class_dic===",class_dic)
# 步骤二:调用元类type(也可以自定义)来产生类Chinense
Foo=type(class_name,class_bases,class_dic) #实例化type得到对象Foo,即我们用class定义的类Foo

print(Foo)
print(type(Foo))
print(isinstance(Foo,type))
print(Foo.__dict__)

E:\PythonProject\python-test\venvP3\Scripts\python.exe E:/PythonProject/python-test/BasicGrammer/test.py
class_dic=== {'country': 'China', '__init__': , 'talk': }


True
{'country': 'China', '__init__': , 'talk': , '__module__': '__main__', '__dict__': , '__weakref__': , '__doc__': None}

Process finished with exit code 0

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

一个类没有声明自己的元类,默认他的元类就是type,除了使用元类type,用户也可以通过继承type来自定义元类

"定义类的时候,就会自动运行Mymeta了"
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author: vita
class Mymeta(type):
    def __init__(self,class_name,class_bases,class_dic):
        print("metadata") #验证定义类的时候就运行了该类
        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,namem,age):
        self.name=namem
        self.age=age

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

E:\PythonProject\python-test\venvP3\Scripts\python.exe E:/PythonProject/python-test/BasicGrammer/test.py
metadata

Process finished with exit code 0
"类名改为小写,运行"
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author: vita
class Mymeta(type):
    def __init__(self,class_name,class_bases,class_dic):
        print("metadata")
        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,namem,age):
        self.name=namem
        self.age=age

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

E:\PythonProject\python-test\venvP3\Scripts\python.exe E:/PythonProject/python-test/BasicGrammer/test.py
metadata
Traceback (most recent call last):
  File "E:/PythonProject/python-test/BasicGrammer/test.py", line 15, in 
    class chinese(object,metaclass=Mymeta):
  File "E:/PythonProject/python-test/BasicGrammer/test.py", line 8, in __init__
    raise TypeError('类名的首字母必须大写')
TypeError: 类名的首字母必须大写

Process finished with exit code 1
"验证没有注释时的情况"
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author: vita
class Mymeta(type):
    def __init__(self,class_name,class_bases,class_dic):
        print("metadata")
        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,namem,age):
        self.name=namem
        self.age=age

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

E:\PythonProject\python-test\venvP3\Scripts\python.exe E:/PythonProject/python-test/BasicGrammer/test.py
metadata
Traceback (most recent call last):
  File "E:/PythonProject/python-test/BasicGrammer/test.py", line 15, in 
    class Chinese(object,metaclass=Mymeta):
  File "E:/PythonProject/python-test/BasicGrammer/test.py", line 11, in __init__
    raise TypeError('必须有注释,且注释不能为空')
TypeError: 必须有注释,且注释不能为空

Process finished with exit code 1

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

"调用obj对象时,调用__call__方法"
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author: vita
#知识储备__call__方法
class Foo:
    var = "var"
    def __call__(self, *args, **kwargs):
        print(self)
        print(args)
        print(kwargs)

obj=Foo()
# print(obj.var) 这样不会调用__call__
#调用obj对象时,调用__call__方法
obj(1,2,3,a=1,b=2,c=3) #obj.__call__(obj,1,2,3,a=1,b=2,c=3)

#元类内部也应有有一个__call__方法,会在调用Foo时触发执行
#Foo(1,2,x=1)  #Foo.__call__(Foo,1,2,x=1)
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author: vita
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('egon',age=18)
        print("exec __call__")

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

class Chinese(object,metaclass=Mymeta):
    '''
    中文人的类
    '''
    country='China'

    def __init__(self,namem,age):
        self.name=namem
        self.age=age

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

obj=Chinese('egon',age=18) #Chinese.__call__(Chinese,'egon',18)

print(obj.__dict__)

E:\PythonProject\python-test\venvP3\Scripts\python.exe E:/PythonProject/python-test/BasicGrammer/test.py
exec __call__
{'name': 'egon', 'age': 18}

Process finished with exit code 0

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

"#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author: vita
#单例模式
#实现方式一:
class MySQL:
    __instance=None #__instance=obj1

    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

#三个对象都是一个,因为只创建了一次
obj1=MySQL.singleton()
obj2=MySQL.singleton()
obj3=MySQL.singleton()

print(obj1 is obj2 is obj3)
"

E:\PythonProject\python-test\venvP3\Scripts\python.exe E:/PythonProject/python-test/BasicGrammer/test.py
True

Process finished with exit code 0
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author: vita
#单例模式
#实现方式二:元类的方式
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): #obj=Chinese('egon',age=18)
        if not self.__instance:
            obj=object.__new__(self)
            self.__init__(obj)
            self.__instance=obj

        return self.__instance

class Mysql(object,metaclass=Mymeta):
    '''
    mysql xxx
    '''
    def __init__(self):
        self.host='127.0.0.1'
        self.port=3306

obj1=Mysql()
obj2=Mysql()
obj3=Mysql()

print(obj1 is obj2 is obj3)

E:\PythonProject\python-test\venvP3\Scripts\python.exe E:/PythonProject/python-test/BasicGrammer/test.py
True

Process finished with exit code 0

本文标题:元类
网站路径:http://kswjz.com/article/ijggji.html
扫二维码与项目经理沟通

我们在微信上24小时期待你的声音

解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流