9.3 Moto类

9.3 Moto类

First, the definition metaclass

Everything in python object class is an object, then, is what the class is created it?

class Person:
    pass
p=Person()

Person class is an object, then it must also be made a class is instantiated get, then this class is called meta-class .

type is built metaclass, all classes are instantiated by the type obtained.

Summary: metaclass is to generate class class!

Two, class analysis of the underlying principles

class class name: class keyword class constructor will come out.

In fact, the interior is generated by the metaclass of this class (type) of the example.

How to produce it, it is to pass a bunch of parameters type (), to achieve.

grammar

type()
type(object_or_name, bases, dict)
    object_or_name:类的名字,是个字符串
    bases:是它的所有父类,基类
    dict:名称空间,是一个字典

() To create a class by type, NA class keyword.

l={}
exec('''
school='oldboy'
def __init__(self,name):
    self.name=name
def score(self):
    print('分数是100')
''',{},l)
People = type('People',(object,),l)

p=Person('nick')
print(p.name)        # nick
print(p.__dict__)    # {'name': 'nick'}

exec()

exec execute Python statements which are stored in a string or file, as compared to the eval, exec can perform more complex Python code.

exec(object[, globals[, locals]])
  • object: Required parameter indicates Python code needs to be specified. It must be a string or code objects. If the object is a string that will first be resolved to a set of Python statement, and then execute (unless a syntax error occurs). If the object is a code object, it is just a simple execution.
  • globals: optional parameter represents the global name space (to store global variables), if provided, must be a dictionary object.
  • locals: an optional parameter that indicates the current local namespace (store local variables), if provided, may be any map object. If this parameter is ignored, then it will take the globals the same value.

Return value: exec return value is always None.

Controlled by generating class metaclass

Custom metaclass to control the production of class, you can control the name of the class, the class hierarchy and class name space!

type: custom metadata class must inherit type, inherited type of class called metaclass.

class Mymeta(type):
    def __init__(self,name,bases,dic):
        # 此时的self为Person这个类(Person类也是对象)
        print(name)
        print(bases)
        print(dic)
        
# metaclass=Mymeta  指定这个类生成的时候,用自己写的Mymeta这个元类
class Person(object,metaclass = Mymeta):
    school='oldboy'
    def __init__(self,name):
        self.name=name
    def score(self):
        print('分数是100')
p = Person('nick')
'''
Person
(<class 'object'>,)
{'__module__': '__main__', '__qualname__': 'Person', '__doc__': '\n    注释\n    ', 'school': 'oldboy', '__init__': <function Person.__init__ at 0x03C0B4B0>, 'score': <function Person.score at 0x03C0B4F8>}
'''

Exercise: control class name must be all uppercase, control class must add a comment!

class Mymeta(type):
    def __init__(self,name,bases,dic):
        # 此时的self为Person这个类(Person类也是对象)
        if not name.isupper():
            raise Exception('类名必须全大写 。')
        doc = self.__dict__['__doc__']
        if not doc:
            raise Exception('你的类没有加注释')
        
# metaclass=Mymeta  指定这个类生成的时候,用自己写的Mymeta这个元类
class Person(object,metaclass = Mymeta):
    school='oldboy'
    def __init__(self,name):
        self.name=name
    def score(self):
        print('分数是100')
p = Person('nick')

Process Control Yuan class by calling the class

Call process control class is actually generated in the control object.

class Mymeta(type):
    # Person('nick') 自动触发init,先触发元类的__call__
    def __call__(self, *args, **kwargs):
        return self.__dict__  # 返回的是People类的对象p,无法点出属性/方法。

class Person(object,metaclass=Mymeta):
    school='oldboy'
    def __init__(self,name):
        self.name=name
    def score(self):
        print('分数是100')

p=Person('nick')
print(p)

Exercise: all the attributes object is set to private

class Mymeta(type):
    def __call__(self, *args, **kwargs):
        # 实例化产生一个Person类的对象,借助__new__来产生,需要把类传过去,才能产生对象
        obj=object.__new__(self)  # obj 是Person类的对象,只不过是空的
        # 对象调用__init__方法完成初始化
        obj.__init__(*args, **kwargs)
        # 修改对象属性为私有属性(拼接_*__*)
        obj.__dict__={ '_%s__%s'%(self.__name__,k):v for k,v in                                             obj.__dict__.items()}

        return obj

class Person(object, metaclass=Mymeta):
    school = 'oldboy'
    def __init__(self, name):
        self.name = name
    def score(self):
        print('分数是100')
        
p = Person(name='nick')
print(p.__dict__)  # {'_Person__name': 'nick'}
print(p.name)      # AttributeError: 'Person' object has no attribute 'name'

After the property has metaclass search order

Class property search order: the class itself -> inheritance by mro order to find the parent -> Custom yuan class find -> type -> error

Find the order of objects: start with the object itself to find ---> class to find ---> mro inheritance to the parent class to find ---> error

Guess you like

Origin www.cnblogs.com/dadazunzhe/p/11455356.html