exec() and metaclass

exec() and metaclass

1. the role of exec()

exec executes Python statements stored in strings or files. Compared with eval, exec can execute more complex Python codes.

syntax:

exec(code,global_dict,local_dict)

code: the incoming text code

global_dic: The dictionary passed in, the global namespace and the built-in namespace are received

local_dict: incoming dictionary, receiving local name space

example

code ='''
global x
x = 10
y = 20
'''
global_dict = {'x':200}

local_dict = {}

exec(code,global_dict,local_dict)

print(global_dict)
#global_dictReturns the global namespace and built-in namespace

print(local_dict)
#local_dictReturn to the local namespace

{'x': 10,'__builtins__': {'__name__':'builtins','__doc__': "Built-in functions, exceptions, and other objects.\n\nNoteworthy: None is the `nil' object; Ellipsis represents `...' in slices.",'__package__':'','__loader__': <class'_frozen_importlib.BuiltinImporter'>,'__spec__': ModuleSpec(name='builtins', loader=<class'_frozen_importlib. BuiltinImporter'>),'__build_class__': <built-in function __build_class__>,'__import__': <built-in function __import__>,'abs': <built-in function abs>,'all': <built-in function all>,'any': <built-in function any>,'ascii': <built-in function ascii>,'bin': <built-in function bin>,'callable': <built-in function callable>,'chr': <built-in function chr>,'compile': <built-in function compile>,'delattr': <built-in function delattr>,'dir ': <built-in function dir>,'divmod': <built-in function divmod>,'eval': <built-in function eval>,'exec': <built-in function exec>,'format': <built-in function format>,'getattr': <built-in function getattr>,'globals': <built-in function globals>,'hasattr': <built-in function hasattr>,'hash': <built -in function hash>,'hex': <built-in function hex>,'id': <built-in function id>,'input': <built-in function input>,'isinstance': <built-in function isinstance>,'issubclass': <built-in function issubclass>,'iter': <built-in function iter>,'len': <built-in function len>,'locals': <built- in function locals>,'max': <built-in function max>,'min': <built-in function min>,'next': <built-in function next>,'oct': <built-in function oct>,'ord': <built-in function ord>,'pow': <built-in function pow>,'print': <built-in function print>,'repr': <built-in function repr> ,'round': <built-in function round>,'setattr': <built-in function setattr>,'sorted': <built-in function sorted>,'sum': <built-in function sum>, ' vars': <built-in function vars>,'None': None,'Ellipsis': Ellipsis,'NotImplemented': NotImplemented,'False': False,'True': True,'bool': <class'bool'>,'memoryview ': <class'memoryview'>,'bytearray': <class'bytearray'>,'bytes': <class'bytes'>,'classmethod': <class'classmethod'>,'complex': <class'complex '>,'dict': <class'dict'>,'enumerate': <class'enumerate'>,'filter': <class'filter'>,'float': <class'float'>,'frozenset' : <class'frozenset'>,'property': <class'property'>,'int': <class'int'>,'list':<class'list'>,'map': <class'map'>,'object': <class'object'>,'range': <class'range'>,'reversed': <class'reversed'> ,'set': <class'set'>,'slice': <class'slice'>,'staticmethod': <class'staticmethod'>,'str': <class'str'>,'super': < class'super'>,'tuple': <class'tuple'>,'type': <class'type'>,'zip': <class'zip'>,'__debug__': True,'BaseException': < class'BaseException'>,'Exception': <class'Exception'>,'TypeError': <class'TypeError'>,'StopAsyncIteration': <class'StopAsyncIteration'>,'StopIteration': <class'StopIteration'>,'GeneratorExit': <class'GeneratorExit'>,'SystemExit': <class'SystemExit'>,'KeyboardInterrupt': <class'KeyboardInterrupt'>,'ImportError ': <class'ImportError'>,'ModuleNotFoundError': <class'ModuleNotFoundError'>,'OSError': <class'OSError'>,'EnvironmentError': <class'OSError'>,'IOError': <class'OSError '>,'WindowsError': <class'OSError'>,'EOFError': <class'EOFError'>,'RuntimeError': <class'RuntimeError'>,'RecursionError': <class'RecursionError'>,'NotImplementedError' :<class'NotImplementedError'>,'NameError': <class'NameError'>,'UnboundLocalError': <class'UnboundLocalError'>,'AttributeError': <class'AttributeError'>,'SyntaxError': <class'SyntaxError'> ,'IndentationError': <class'IndentationError'>,'TabError': <class'TabError'>,'LookupError': <class'LookupError'>,'IndexError': <class'IndexError'>,'KeyError': < class'KeyError'>,'ValueError': <class'ValueError'>,'UnicodeError': <class'UnicodeError'>,'UnicodeEncodeError': <class'UnicodeEncodeError'>,'UnicodeDecodeError': <class'UnicodeDecodeError'>,'UnicodeTranslateError': <class'UnicodeTranslateError'>,'AssertionError': <class'AssertionError'>,'ArithmeticError': <class'ArithmeticError'>,'FloatingPointError': <class'FloatingPointError'>,'OverflowError': <class'OverflowError'>,'ZeroDivisionError': <class'ZeroDivisionError'>,'SystemError': <class'SystemError'>,'ReferenceError': <class'ReferenceError'>,'BufferError': <class'BufferError'> ,'MemoryError': <class'MemoryError'>,'Warning': <class'Warning'>,'UserWarning': <class'UserWarning'>,'DeprecationWarning': <class'DeprecationWarning'>,'PendingDeprecationWarning': <class'PendingDeprecationWarning'>,'SyntaxWarning': <class'SyntaxWarning'>,'RuntimeWarning': <class'RuntimeWarning'>,'FutureWarning': <class'FutureWarning'>,'ImportWarning': < class'ImportWarning'>,'UnicodeWarning': <class'UnicodeWarning'>,'BytesWarning': <class'BytesWarning'>,'ResourceWarning': <class'ResourceWarning'>,'ConnectionError': <class'ConnectionError'>, 'BlockingIOError': <class'BlockingIOError'>,'BrokenPipeError': <class'BrokenPipeError'>,'ChildProcessError': <class'ChildProcessError'>,'ConnectionAbortedError': <class'ConnectionAbortedError'>,'ConnectionRefusedError': <class'ConnectionRefusedError'>,'ConnectionResetError': <class'ConnectionResetError'>,'FileExistsError': <class'FileExistsError'>,'FileNotFoundError': <class'FileNotFoundError'>, 'IsADirectoryError': <class'IsADirectoryError'>,'NotADirectoryError': <class'NotADirectoryError'>,'InterruptedError': <class'InterruptedError'>,'PermissionError': <class'PermissionError'>,'ProcessLookupError': <class 'ProcessLookupError'>,'TimeoutError': <class'TimeoutError'>,'open': <built-in function 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.}}
{'y': 20}

2. metaclass

2.1 What is a metaclass, and what is the role of a metaclass?

In Python, everything is an object. The class we define with the class keyword is also an object. The class responsible for generating the object is called a metaclass, and a metaclass can be referred to as a class for short. The main purpose of metaclasses is to control the creation behavior of classes.

Type is a built-in metaclass of Python, which is used to directly control the generated class. In Python, any class defined by a class is actually the result of instantiation of the type class.

Only by inheriting the type class can it be called a metaclass. Otherwise, it is an ordinary custom class. The custom metaclass can control the generation process of the class. The generation process of the class is actually the calling process of the metaclass.

2.2 Custom create metaclass

  1. Customize a class, inherit the type class, and derive your own properties and methods
  2. Classes that need to use metaclasses specify a custom metaclass through metaclass.
  3. Inherit the three parameters stipulated by the type class: a. what: class name --> the name of the type object b. bases: --> base class/parent class c. dict: --> class name space

example

Definition of control class

class MyMeta(type):
#Control class definition
    def __init__(self,class_name,class_base,class_dict):

        print(class_name)

        if not class_name.istitle():
            raise TypeError('The first letter of the class must be capitalized')

        if not class_dict.get('__doc__'):
            raise TypeError('A comment must be written inside the class')

        print(class_base)
        print(class_dict)

        super().__init__(class_name,class_base,class_dict)
        #Inheritance of the three parameters that need to be passed in the type class

class Bar():
    pass

class Foo(Bar,metaclass=MyMeta):# MyMeta(Foo, Foo_name, (Bar, ), foo_dict)
    'metaclass=MyMeta will pass all the parameters needed by the metaclass to the metaclass'
    x = 10
    def __init__(self,y,z):
        self.y = y
        self.z = z

    def f1(self):
        print('from Foo.f1')

foo = Foo(20,30)

(<class'__main__.Bar'>,)
{'__module__':'__main__','__qualname__':'Foo','__doc__':'metaclass=MyMeta will pass all the parameters required by the metaclass to the metaclass','x': 10,'__init__': < function Foo.__init__ at 0x000001D8048F0F28>,'f1': <function Foo.f1 at 0x000001D804902048>}

How to call the control class

When the class is called, it will first trigger the __call__ inside the class or the class inherited by the class, and then call __new__ through __call__

To instantiate an empty object, to control the calling method of the class, you only need to use these two methods directly inside the class.

 # Simulate what is done inside the type metaclass
    # The __call__ triggered by the metaclass can control the call of the class. Calling __call__ will trigger the following two points
    def __call__(self, *args, **kwargs):
        # 1. __new__() will be called to instantiate an empty obj
        obj = object.__new__(self)
        # 2. Will execute __init__(obj, *args, **kwargs),
        obj.__init__(*args, **kwargs)
        return obj

    # The creation of objects can be controlled by __new__ inside the metaclass
    def __new__(cls, *args, **kwargs):
        pass
Reference: https://cloud.tencent.com/developer/article/1554231 exec() and metaclasses-Cloud + Community-Tencent Cloud