Python in Meta class

Source: Internet
Author: User
Tags class definition instance method

Meta-Class 1. Class is also an object

In most programming languages, a class is a set of code snippets that describe how to generate an object. This is still true in Python:

>>> class ObjectCreator(object):… pass…>>> my_object = ObjectCreator()>>> print my_object<__main__.ObjectCreator object at 0x8974f2c>

However, the classes in Python are far more than that. class is also an object. Yes, yes, that's the object. As long as you use the keyword Class,python The interpreter will create an object when it executes.

The following code snippet:

>>> class ObjectCreator(object):… pass…

An object is created in memory and the name is Objectcreator. This object (class object Objectcreator) has the ability to create objects (instance objects). However, its nature is still an object, so you can do the following with it:

    1. You can assign it to a variable
    2. You can copy it.
    3. You can add properties to it
    4. You can pass it as a function parameter

Here's an example:

>>> print ObjectCreator     # 你可以打印一个类,因为它其实也是一个对象<class ‘__main__.ObjectCreator‘>>>> def echo(o):…       print o…>>> echo(ObjectCreator)                 # 你可以将类做为参数传给函数<class ‘__main__.ObjectCreator‘>>>> print hasattr(ObjectCreator, ‘new_attribute‘)Fasle>>> ObjectCreator.new_attribute = ‘foo‘ #  你可以为类增加属性>>> print hasattr(ObjectCreator, ‘new_attribute‘)True>>> print ObjectCreator.new_attributefoo>>> ObjectCreatorMirror = ObjectCreator # 你可以将类赋值给一个变量>>> print ObjectCreatorMirror()<__main__.ObjectCreator object at 0x8997b4c>
2. Dynamically Creating classes

Because classes are also objects, you can create them dynamically at run time, just like any other object. First, you can create a class in a function, using the class keyword.

>>> def choose_class(name):…       if name == ‘foo‘:…           class Foo(object):…               pass…           return Foo     # 返回的是类,不是类的实例…       else:…           class Bar(object):…               pass…           return Bar…>>> MyClass = choose_class(‘foo‘)>>> print MyClass              # 函数返回的是类,不是类的实例<class ‘__main__‘.Foo>>>> print MyClass()            # 你可以通过这个类创建类实例,也就是对象<__main__.Foo object at 0x89c6d4c>

But this is not dynamic enough, because you still need to write your own code for the entire class. Because classes are also objects, they must be generated by something. When you use the class keyword, the Python interpreter automatically creates the object. But like most things in Python, Python still provides you with a way to handle it manually.

Do you remember the built-in function type? This ancient but powerful function lets you know what the type of an object is, just like this:

>>> print type(1) #数值的类型<type ‘int‘>>>> print type("1") #字符串的类型<type ‘str‘>>>> print type(ObjectCreator()) #实例对象的类型<class ‘__main__.ObjectCreator‘>>>> print type(ObjectCreator) #类的类型<type ‘type‘>

Looking closely at the results of the above operation, it is not surprising to find that the type of the Objectcreator view is, the answer is type. Look underneath.

3. Creating a class with type

Type also has a completely different function for dynamically creating classes.

The type can accept a description of a class as a parameter and then return a class. (You know, it's silly to have two different uses of the same function, depending on the parameters passed in, but this is in Python for backwards compatibility)

Type can work like this:

Type (class name, a tuple of the parent class name, which can be empty for inheritance), contains the dictionary (name and value) of the property

For example, the following code:

In [2]: class Test: #定义了一个Test类 ...: pass ...:In [3]: Test() #创建了一个Test类的实例对象Out[3]: <__main__.Test at 0x10d3f8438>

You can create it manually like this:

Test2 = type("Test2",(),{}) #定了一个Test2类In [5]: Test2() #创建了一个Test2类的实例对象Out[5]: <__main__.Test2 at 0x10d406b38>

We use "Test2" as the class name, and we can also treat it as a variable as a reference to the class. Classes and variables are different, and there's no reason to complicate things. That is, the 1th argument in the type function, which can also be called the other name, which indicates the name of the class.

In [23]: MyDogClass = type(‘MyDog‘, (), {})In [24]: print MyDogClass<class ‘__main__.MyDog‘>

Use Help to test these 2 classes

In [10]: help(Test) #用help查看Test类Help on class Test in module __main__:class Test(builtins.object) |  Data descriptors defined here: | |  __dict__ |      dictionary for instance variables (if defined) | |  __weakref__ |      list of weak references to the object (if defined)
In [8]: help(Test2) #用help查看Test2类Help on class Test2 in module __main__:class Test2(builtins.object) |  Data descriptors defined here: | |  __dict__ |      dictionary for instance variables (if defined) | |  __weakref__ |      list of weak references to the object (if defined)
4. Create a class with attributes using Type

The type accepts a dictionary to define properties for the class, so

>>> Foo = type(‘Foo‘, (), {‘bar‘:True})

Can be translated as:

>>> class Foo(object):… bar = True

And you can use Foo as a normal class:

>>> print Foo<class ‘__main__.Foo‘>>>> print Foo.barTrue>>> f = Foo()>>> print f<__main__.Foo object at 0x8a9b84c>>>> print f.barTrue

Of course, you can inherit from this class, so the following code:

>>> class FooChild(Foo):… pass

Can be written as:

>>> FooChild = type(‘FooChild‘, (Foo,),{})>>> print FooChild<class ‘__main__.FooChild‘>>>> print FooChild.bar   # bar属性是由Foo继承而来True
Attention:
    • The 2nd argument of type, the name of the parent class in the tuple, not the string
    • The added property is a class property, not an instance property
5. Create a class with a method using type

Eventually you will want to add a method to your class. You just need to define a function with the proper signature and assign it as a property.

Adding an instance method
in [46]:DefEcho_bar(self): #定义了一个普通的函数 ...: print (Self.bar) ...: in [47]: Foochild = Type ( Span class= "hljs-string" > ' Foochild ', (Foo,), { ' Echo_bar ': Echo_bar})  #让FooChild类中的echo_bar属性, pointing to the function defined above in [48]: hasattr (Foo,  ' Echo_bar ')  #判断Foo类中, is there echo_bar this attribute Out[48]: Span class= "Hljs-keyword" >falsein [49]:in [49]: hasattr ( Foochild,  ' Echo_bar ')  #判断FooChild类中, is there echo_bar this attribute out[< Span class= "Hljs-number" >49]: truein [50]: My_foo = FooChild () In [51]: My_foo.echo_bar () true     
Adding a static method
In [36]: @staticmethod    ...: def testStatic(): ...: print("static method ....") ...:In [37]: Foochild = type(‘Foochild‘, (Foo,), {"echo_bar":echo_bar, "testStatic": ...: testStatic})In [38]: fooclid = Foochild()In [39]: fooclid.testStaticOut[39]: <function __main__.testStatic>In [40]: fooclid.testStatic()static method ....In [41]: fooclid.echo_bar()True
To add a class method
In [42]: @classmethod    ...: def testClass(cls): ...: print(cls.bar) ...:In [43]:In [43]: Foochild = type(‘Foochild‘, (Foo,), {"echo_bar":echo_bar, "testStatic": ...: testStatic, "testClass":testClass})In [44]:In [44]: fooclid = Foochild()In [45]: fooclid.testClass()True

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 you use the keyword class, and this is done through the Meta class.

6. What is a meta-class (finally to the topic)

A meta-class is a "thing" used to create a class. You create a class just to create an instance object of the class, don't you? But we've learned that the classes in Python are also objects.

The meta-class is used to create these classes (objects), the meta-class is the class class, you can understand that:

#使用元类创建出一个对象,这个对象称为“类”MyObject = MyClass() #使用“类”来创建出实例对象

You've seen the type that allows you to do something like this:

MyClass = type(‘MyClass‘, (), {})

This is because the function type is actually a meta class. The type is the meta-class that Python uses to create all the classes behind. Now you want to know why is the type all in lowercase instead of type? Well, I guess that's for consistency with STR, STR is the class used to create the string object, and int is the class used to create the integer object. Type is the class that creates the class object. You can see this by checking the __class__ property. all the things in Python, note that I mean all things--are objects. This includes integers, strings, functions, and classes. They are all objects, and they are all created from a class, which is the type.

>>> age = 35>>> age.__class__<type ‘int‘>>>> name = ‘bob‘>>> name.__class__<type ‘str‘>>>> def foo(): pass>>>foo.__class__<type ‘function‘>>>> class Bar(object): pass>>> b = Bar()>>> b.__class__<class ‘__main__.Bar‘>

Now, what is the __class__ attribute for any one __class__?

>>> a.__class__.__class__<type ‘type‘>>>> age.__class__.__class__<type ‘type‘>>>> foo.__class__.__class__<type ‘type‘>>>> b.__class__.__class__<type ‘type‘>

Therefore, a meta-class is something that creates objects of this class. Type is the inner Jianyuan class of Python, and of course, you can also create your own meta-class.

7. __metaclass__ Properties

You can add a __metaclass__ property to a class when you define it.

class Foo(object):    __metaclass__ = something…    ...省略...

If you do this, Python will use the Meta class to create the class Foo. Be careful, there's some tricks in there. You first write class Foo (object), but the class Foo is not yet created in memory. Python will look for the __metaclass__ attribute in the class definition, and if found, Python will use it to create the class Foo, and if not found, it will use the built-in type to create the class. Read this passage a few times. When you write the following code:

class Foo(Bar):    pass

Python does the following:

    1. Is there a __metaclass__ attribute in Foo? If so, Python creates a class (object) with the name Foo through __metaclass__
    2. If Python does not find __metaclass__, it will continue to look for the __metaclass__ attribute in bar (parent class) and try to do the same thing as before.
    3. If Python cannot find __metaclass__ in any parent class, it will look for __metaclass__ in the module hierarchy and try to do the same.
    4. If you still can't find __metaclass__,python, you'll use the built-in type to create this class object.

Now the question is, what code can you put in the __metaclass__? The answer is: You can create something of a class. So what can be used to create a class? Type, or anything that uses the type or subclass type.

8. Custom meta-classes

The primary purpose of the meta-class is to automatically change the class when the class is created. Typically, you do something like this for the API, and you want to create a class that matches the current context.

Imagine a silly example where you decide that the properties of all classes in your module should be in uppercase form. There are several ways to do this, but one is by setting __metaclass__ at the module level. In this way, all classes in this module are created by this meta-class, and we just need to tell the Meta class to change all the attributes to uppercase.

Fortunately, __metaclass__ can actually be called arbitrarily, and it doesn't need to be a formal class. So, let's start with a simple function as an example.

In Python2
#-*-Coding:utf-8-*-DefUpper_attr #遍历属性字典 to capitalize the attribute name not beginning with __ newattr = {} for name,value in future_class_attr.items (): if not Name.startswith ( "__"): Newattr[name.upper ()] = value # Call type to create a class return type (Future_class_name, future_class_parents, newattr) class foo (object): __ metaclass__ = upper_attr  #设置Foo类的元类为upper_attr bar =  ' Bip ' Print (Hasattr (foo,  bar)) print (Hasattr (foo,  ' bar ')) F = Foo () print ( F.bar)                
In Python3
#-*-Coding:utf-8-*-Defupper_attr (Future_class_name, future_class_parents, future_ CLASS_ATTR):  #遍历属性字典 to capitalize the attribute name that is not the beginning of __ newattr = {} for name, Value in future_class_attr.items (): if not name.startswith ( "__"): Newattr[name.upper ()] = value  #调用type来创建一个类 return type (Future_class_name, future_class_parents , newattr) class Foo ' Bip ' Print (hasattr (Foo, ") print (Hasattr (Foo,  ' bar ')) F = Foo () print (F.bar)   

Now let's do it again, this time using a real class as a meta class.

#coding =utf-8ClassUpperattrmetaclass(type):# __new__ is a special method called before __init__# __new__ is the method used to create an object and return it# and __init__ is just used to initialize the passed parameters to the object# You seldom use __new__ unless you want to be able to control the creation of objects# here, the object created is the class, we want to be able to customize it, so here we rewrite __new__# If you want, you can do something in the __init__.# There are some advanced uses that involve rewriting __call__ special methods, but we don't have toDef__new__(CLS, Future_class_name, Future_class_parents, future_class_attr):#遍历属性字典, change the property name to uppercase Newattr = {} that is not the beginning of __For Name,valueIn Future_class_attr.items ():IfNot Name.startswith ("__"): Newattr[name.upper ()] = value# method 1: Create a Class object with ' type '# return type (Future_class_name, future_class_parents, newattr)# Method 2: Multiplexing the Type.__new__ method# This is basic OOP programming, no magic.# return type.__new__ (CLS, Future_class_name, Future_class_parents, newattr)# Method 3: Use the Super method to return super (Upperattrmetaclass, CLS). __new__ (CLS, Future_class_name, Future_class_parents, newattr)#python2的用法class Foo(object): __metaclass__ = Upperattrmetaclass bar = ' Bip '# Python3 Usage # class Foo (object, Metaclass = Upperattrmetaclass):# bar = ' Bip ' Print (hasattr (Foo, ' Bar ')) # Output: Falseprint (hasattr (Foo, ' BAR '))# output: Truef = Foo () print (f.bar)# output: ' Bip '   

That's it, besides, there's really nothing else to say about the meta-class. But in terms of the meta-class itself, they are really simple:

    1. Block creation of classes
    2. Modifying a class
    3. Returns the class after the modification
Why should we use meta-classes?

Now back to our big theme, why are you going to use such an error-prone and obscure feature? Well, generally speaking, you don't use it at all:

"Meta-class is the magic of depth,99% of users should not worry about it at all." If you want to figure out whether you need to use a meta-class, then you don't need it. Those who actually use the meta-class know very well what they need to do and do not need to explain why they use the meta-class at all. "The leader of the--python world Tim Peters

Python in Meta class

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.