Deep Mining of Python and metabases II [experience] and deep mining of python
The previous article solved some of the namespace problems that may occur during the generation of instance objects by calling class objects. This time we go back to the next layer to see how class objects are generated.
We know that the type () method can view the type of an object, or determine which class the object is generated:
print(type(12)) print(type('python')) class A: pass print(type(A))
Through this code, we can see that Class Object A is generated by type (), that is, type can also be used to generate new objects and produce class objects, therefore, it is the class of all class objects:
print(type.__doc__) type(object_or_name, bases, dict) type(object) -> the object's type type(name, bases, dict) -> a new type
The class definition class syntax is actually converted to type (name, bases, dict). The name parameter is the class name, and bases is the tuples that inherit the parent class, dict is a class property and method:
Class A: pass # is actually equal to B = type ('A', (), {}) print (. _ name _ = B. _ name _) True
In theory, this is the significance of the meta-class, but from the actual point of view, it is obvious that it is more convenient and reasonable to use the class syntax, the actual significance of the meta-class is to construct a new meta-class by inheriting the type class and perform specific operations to generate class objects with specific behaviors. In this way, it seems that its nature is no different from ordinary class objects, but it inherits the type class.
When an instance is generated, it is initialized by calling the _ init _ method. In fact, before that, the _ new _ method will be called to create an instance, then through _ init _ initialization, it is like _ new _ is responsible for declaring variables, while _ init _ is responsible for initializing declared variables. Here, there is a rule that the return value of _ new _ (cls,) must be an instance of the cls parameter, otherwise _ init _ will not be triggered, for example, in enum. in the definition of Enum, the instance is not returned when _ new _ is defined because the enumeration type is Singleton mode. Therefore, Initialization is not performed:
class Enum: def __new__(cls, value): print(cls, value) return value def __init__(self): print("Will not be called!") e = Enum(1) <class '__main__.Enum'> 1
Generally, you need to call the _ new _ method of the parent class to create a cls instance, the usage of the type mentioned above is also called when the Meta class is defined (because the Meta class inherits from the type ):
Class MetaEnum (type): def _ new _ (metaclass, name, base, attrs): print ("Metaclass :{}\ nName :{}\ nParents: {} \ nAttributes :{}". format (metaclass, name, base, attrs) return super (). _ new _ (metaclass, name, base, attrs) class Enum (metaclass = MetaEnum ): # The method for defining metaclass in Python 2.7 is to use the _ metaclass _ variable # [PEP 3115] (https://www.python.org/dev/peps/pep-3115/) # change the syntax of Python 3.0 to class Cls (metaclass = Meta) test = 0 Metaclass: Name: Enum Parents: () Attributes: {'_ qualname _': 'enum', '_ module __': '_ main _', 'test': 0} Now let's take a look at the Enum class. It is no longer a type but its MetaEnum: type (Enum) _ main __. metaEnum
In addition to the _ new _ method, PEP 3115 also defines the _ prepare _ attribute, which is used to set the initialized namespace (that is, the 3rd parameters of type) or enum. for example, if you want to restrict the repeated use of attribute names in the enumeration type, you can use the behavior of the meta-class restriction class:
# Define a new dictionary class when assigning a new dict [k] = v
# Check whether k is repeated
Class _ EnumDict (dict): def _ init _ (self): super (). _ init _ () self. members = [] def _ setitem _ (self, k, v): if k in self. members: raise TypeError ("Attempted to reuse key :'{}'". format (k) else: self. members. append (k) super (). _ setitem _ (k, v) class MetaEnum (type): @ classmethod def _ prepare _ (metaclass, cls, bases): return _ EnumDict () def _ new _ (metaclass, name, base, attrs): return super (). _ new _ (Metaclass, name, base, attrs) class Enum (metaclass = MetaEnum): pass class Color (Enum): try: red = 1 red = 2 bytes t TypeError: # Why is as err not used here? Print ("TypeError catched") TypeError catched
In Python, everything is an object. All objects are instances of a certain type, or an instance of a certain mona1 class. type is its own metadata and its own instance.