>>> class ObjectCreator(object): ... pass ... >>> my_object = ObjectCreator() >>> print my_object <__main__.ObjectCreator object at 0x8974f2c> class keyword is used, Python executes the command and creates an object . Instruction >>> class ObjectCreator(object): ... pass ... ObjectCreator .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> class keyword is used, Python creates this object automatically. But like most things in Python, there is a way to do it manually.type function? Good old function that allows you to determine the type of object: >>> print type(1) <type 'int'> >>> print type("1") <type 'str'> >>> print type(ObjectCreator) <type 'type'> >>> print type(ObjectCreator()) <class '__main__.ObjectCreator'> type function has a completely different use: it can also create classes on the fly. type takes a class description as input and convokes the class.type works as follows: type(< >, < >, # , <, >) >>> class MyShinyClass(object): ... pass >>> MyShinyClass = type('MyShinyClass', (), {}) # - >>> print MyShinyClass <class '__main__.MyShinyClass'> >>> print MyShinyClass() # <__main__.MyShinyClass object at 0x8997cec> type accepts a dictionary that defines class attributes: >>> class Foo(object): ... bar = True >>> Foo = type('Foo', (), {'bar':True}) >>> print Foo <class '__main__.Foo'> >>> print Foo.bar True >>> f = Foo() >>> print f <__main__.Foo object at 0x8a9b84c> >>> print f.bar True >>> class FooChild(Foo): ... pass >>> FooChild = type('FooChild', (Foo,), {}) >>> print FooChild <class '__main__.FooChild'> >>> print FooChild.bar # bar is inherited from Foo True >>> def echo_bar(self): ... print self.bar ... >>> FooChild = type('FooChild', (Foo,), {'echo_bar': echo_bar}) >>> hasattr(Foo, 'echo_bar') >>> hasattr(FooChild, 'echo_bar') True >>> my_foo = FooChild() >>> my_foo.echo_bar() True class keyword is used, and it does this using metaclasses. MyClass = MetaClass() MyObject = MyClass() type allows you to do something like this: MyClass = type('MyClass', (), {}) type function is actually a metaclass. type is a metaclass that Python internally uses to create all classes.Type ?str , the class for creating string objects, and int , the class for creating integer objects. type is just a class for creating class objects.__class__ attribute: >>> 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'> __class__ for each __class__ ? >>> a.__class__.__class__ <type 'type'> >>> age.__class__.__class__ <type 'type'> >>> foo.__class__.__class__ <type 'type'> >>> b.__class__.__class__ <type 'type'> type is a built-in metaclass that Python uses, but of course you can create your own.__metaclass__ attribute__metaclass__ : class Foo(object): __metaclass__ = something... [...] Foo class.class Foo(object) , an object class is not yet created in memory.__metaclass__ in the class definition. If he finds it, he uses it to create the class Foo . If not, it will use type . class Foo(Bar): pass Foo class have the attribute __metaclass__ ?Foo , using what is specified in __metaclass__ .__metaclass__ , he searches for __metaclass__ in the parent class Bar and tries to do the same.__metaclass__ is not in any of the parents, Python will search for __metaclass__ at the module level.__metaclass__ at all, he uses type to create a class object.__metaclass__ ?type or any of its subclasses, as well as anything that uses them.__metaclass__ at the module level.__metaclass__ can be any callable object, not necessarily a formal class (I know that something with the word “class” in the name does not have to be a class, what nonsense? However, this is useful). # , # `type` def upper_attr(future_class_name, future_class_parents, future_class_attr): """ -, """ # , '__' attrs = ((name, value) for name, value in future_class_attr.items() if not name.startswith('__')) # uppercase_attr = dict((name.upper(), value) for name, value in attrs) # `type` return type(future_class_name, future_class_parents, uppercase_attr) __metaclass__ = upper_attr # class Foo(object): # __metaclass__ , bar = 'bip' print hasattr(Foo, 'bar') # Out: False print hasattr(Foo, 'BAR') # Out: True f = Foo() print f.BAR # Out: 'bip' # , `type` , `str` `int`, # class UpperAttrMetaclass(type): # __new__ __init__ # , # __init__ , . # __new__, , # # , , # __new__. # - __init__, . # __call__, # . def __new__(upperattr_metaclass, future_class_name, future_class_parents, future_class_attr): attrs = ((name, value) for name, value in future_class_attr.items() if not name.startswith('__')) uppercase_attr = dict((name.upper(), value) for name, value in attrs) return type(future_class_name, future_class_parents, uppercase_attr) type and do not overload the call to the __new__ parent. Let's do that: class UpperAttrMetaclass(type): def __new__(upperattr_metaclass, future_class_name, future_class_parents, future_class_attr): attrs = ((name, value) for name, value in future_class_attr.items() if not name.startswith('__')) uppercase_attr = dict((name.upper(), value) for name, value in attrs) # type.__new__ # , return type.__new__(upperattr_metaclass, future_class_name, future_class_parents, uppercase_attr) upperattr_metaclass . There is nothing special about it: the method always receives the current instance as the first argument. In the same way as you use self in normal methods.self , there is an agreement on the naming of all these arguments. So the real metaclass looks something like this: class UpperAttrMetaclass(type): def __new__(cls, name, bases, dct): attrs = ((name, value) for name, value in dct.items() if not name.startswith('__')) uppercase_attr = dict((name.upper(), value) for name, value in attrs) return type.__new__(cls, name, bases, uppercase_attr) super , which will cause inheritance (since, of course, you can create a metaclass inherited from a metaclass inherited from type ): class UpperAttrMetaclass(type): def __new__(cls, name, bases, dct): attrs = ((name, value) for name, value in dct.items() if not name.startswith('__')) uppercase_attr = dict((name.upper(), value) for name, value in attrs) return super(UpperAttrMetaclass, cls).__new__(cls, name, bases, uppercase_attr) __dict__ and the like.__metaclass__ accepts any callable object, why would you suddenly use a class if it’s obviously more difficult?UpperAttrMetaclass(type) , you immediately know what will happen next.__new__ , __init__ and __call__ . Of course, you can usually do everything in __new__ , but some are more comfortable using __init__Metaclasses are deep magic, about which 99% of users do not even need to think. If you think whether you need to use them - you do not need (people who really need them, know exactly why they need them, and do not need an explanation of why).
~ Guru Python Tim Peters
class Person(models.Model): name = models.CharField(max_length=30) age = models.IntegerField() guy = Person(name='bob', age='35') print guy.age IntegerField , but int , and the value can be obtained directly from the database.models.Model defines __metaclass__ , which __metaclass__ some magic and turns the Person class that we just defined with a simple expression into a complex database binding. >>> class Foo(object): pass >>> id(Foo) 142630324 type .type is its own metaclass. It cannot be reproduced on pure Python and is done with a small cheat at the implementation level.Source: https://habr.com/ru/post/145835/
All Articles