Metaclass
1. How to create a class
class Myobject(object):
pass
2. Dynamically create classes
def Choose_Class(name):
if name== ' fish ' :
class Fish(object):
pass
return Fish #returns a class, not an instance of a class
else:
class Crab(object):
pass
return Crab
Myclass =Choose_Class( " fish " )
print (Myclass) #The function returns a class, not an instance of a class
print (Myclass())
Results of the:
But that's not dynamic enough, because you still need to code the entire class yourself. Since classes are also objects , they must be generated by something. When you use the class keyword,
The python interpreter creates this object automatically, but like most things in paython, python still gives you the means to do it manually
Remember the built-in function type, this old but powerful function that lets us know what the type of an object is, like this:
Hey, why is the type of the Myobject class type? Let's look down
3. Use type to create a class
Type has a completely different function, dynamically creating a class.
type ( class name , tuple of parent class names (can be empty for inheritance), dictionary containing attributes (name and value) )
For example the following code:
@staticmethod def TestStaticMethod(): print("static method……") @classmethod def TestClassmethod(cls): print("class method……") def echo_bar(self): print(self.bar) Animal=type('Animal',(),{'bar':True}) Fish=type('Fish',(Animal,),{"echo_bar":echo_bar,'TestStaticMethod':TestStaticMethod,"TestClassmethod":TestClassmethod}) fish=Fish()
As you can see, in Python , classes are also objects, and you can create classes dynamically. This is what Python does behind the scenes when we use the keyword class , and this is achieved through metaclasses.
4. What exactly is a metaclass (finally to the topic)
Metaclasses are the " things " used to create classes . You create classes to create instance objects of the class, don't you?
But we have already learned that classes in Python are also objects. The metaclass is used to create these classes (objects), and the metaclass is the class of the class, you can understand it like this :
MyClass = MetaClass() #Use metaclass to create an object called "class" MyObject = MyClass() #Use "class" to create instance object
We've already seen that type lets you do something like this:
MyClass = type('MyClass', (), {})
This is because the function type is actually a metaclass. type is the metaclass that Python uses behind the scenes to create all the things in Python
, note that I mean everything - all objects. This includes integers, strings, functions, and classes. They are all objects, and they are all created from a class, and that class is type .
type is the class that creates the class object. We can see by checking the __class__ attribute, and then we can see what the .__class__ attribute of any .__class__ can get
So a metaclass is something that can create a class object, and a type is a metaclass built into python.
__metaclass__ attribute
You can add the __metaclass__ attribute when defining a class.
class Fish(object): __meta__=something
If you do this, python will use the original to create Fish, but there are some steps here, first write class Fish(object), but Fish has not been created in memory, python will look for it in the class definition __metaclass__ attribute,
If it is found, python will use it to create the class Fish, if not, it will use the built-in type to create this class
When we write the following code:
class Fish(animal): __meta__=something
python does the following:
1. If there is __metaclass__ in Fish, then python will create a class named Fish through __metaclass__
2. If __metaclass__ is not found in python, it will continue to look for this attribute in the parent class animal and try the same operation as before
3. If __metaclass__ is not found in the parent class, it will look for __metaclass__ in the module hierarchy and try to do the same as before
Now the question is: what code can we put in __metaclass__
Answer: To create a class thing, then what can be used to create a class type or subclass type stuff?
Use functions as metaclasses:
def UpAttr(future_class_name,future_class_parents,future_class_attr): result={} for name,value in future_class_attr.items(): if not name.startswith("__"): result[name.upper()]=value return type(future_class_name,future_class_parents,result) # python3 writing class Fish(object, metaclass= UpAttr): bar = ' hhhh ' # python2 writing class Fish(object): __metaclass__ = UpAttr bar = ' hhhh ' print(hasattr(Fish,'bar')) print(hasattr(Fish,'BAR'))
Use class as metaclass:
class UpperAttrMetaClass(type): def __new__(cls,future_class_name,future_class_parents,future_class_attr): result={} for name,value in future_class_attr.items(): if not name.startswith("__"): result[name.upper()]=value return type(future_class_name,future_class_parents,result) # python3 writing class Fish(object, metaclass= UpperAttrMetaClass): bar = ' hhhh ' print(hasattr(Fish,'bar')) print(hasattr(Fish,'BAR'))