Python’s new class model

  • All classes in Python3. x are automatically converted to a “new class”, whether or not they inherit from Object objects

  • Python2.x must explicitly specify that the class inherits the object parent to denote a “new class”

New class versus classic class templates
# py2.xclass Dtrees: """ Dtrees default to new classes """ pass# py2.xclass Dtrees(object) """ Py2. x must explicitly inherit Object as its parent in order to be said to be new class """ passClass Dtrees: """ Dtrees default to classic class """ passCopy the code
Characteristics of new classes

Define classic and new classes

# newstyle.py,python environment for 2.xclass Classic: Python2.x defaults to a classical class. Since __getatt__ has the same effect as __getattribute__, only __getattr__ is used to demonstrate """ def __getattr__(self, method_name): print("call Classic __getattr__,it would call built-in[%s] method " % method_name) return getattr(self.__name,method_name)class NewStyleClass(object): def __init__(self): Self.__name = "newstyle name" """ python2.x needs to be specified as a new class, python3.x defaults to a new class "" def __getattr__(self, item): print("call NewStyle __getattr__,it would call built-in[%s] method " %item) return getattr(self.__name,item)def test_dir(): C = Classic() N = NewStyleClass() print(dir(C) # Print (dir(N newstyle.pyCopy the code

The built-in attribute methods in the new class will be retrieved from the class as the starting point of the search, skipping the class instance search

  • In the new class, routes to __getattr__ and __getAttribute__’s built-in function (__X__) are skipped and no longer intercepted

# newstyle.pydef test_classis(): C = Classic() print("python2.x classic instance built-in attributes:") print(str(C)) # Calling STR () executes the built-in __str__ function, but is intercepted by the __getattr__ method and then called __str__ print(c. __str__()) # to execute the same output as above: def test_new(): N = NewStyleClass() print("python3.x classic instance built-in Attributes :") print(STR (N)) # Print (type(N).__str__(N)) # must call >>> Python newstyle.py in a class manner without being intercepted by the __getattr__ methodCopy the code

  • Classic class instances add built-in operations that work fine, new class instances don’t

# newstyle.pydef test_builtin(): C = Classic() c. __add__ = lambda x:x+2 print(C+2) N = NewStyleClass() n. __add__ = lambda x: X + 2 print(N + 2) # unsupported operand type(s) for +: 'NewStyleClass' and 'int', __add__>>> Python newstyle.pyCopy the code

Changes to the class model

  • Classes are types, classes are instances of type

# newstyle.pydef test_model_change():
    C = Classic()
    print(type(C))
    print(C.__class__)

    N = NewStyleClass()
    print(type(N))
    print(N.__class__)>>> python newstyle.pyCopy the code

  • Types are classes, type are all instances of classes

# newstyle.py ... class D:passclass NClass(object):passdef test_model_change2(): C1 = Classic() C2 = D() print(type(C1) == type(C2)) Print (type(N1) == type(N2)) print(type(N1) == type(N2)Copy the code

All classes inherit object, which is the top-level base class

  • The type of an instance object is class, the type of class is type, and the type of type is type

# newstyle.py def test_class():
    print(type("str class"))
    print(type(str))
    print(type(type))>>> python newstyle.pyCopy the code

  • All new classes have attributes from the base class Object

# newstyle.py def test_inherit():
    print(Classic.__bases__)
    print(dir(Classic))
    print(NewStyleClass.__bases__)
    print(dir(object))
    print(dir(NewStyleClass))>>> python newstyle.pyCopy the code

Inheritance tree searches are traversed in breadth-first fashion on the basis of the same base class

  • Have the same top-level class

# newstyle.py class A1(object):attr = 1class B(A1):passclass C(A1):attr = 4class D2(B,C):passdef test_search(): D = D2() print(d.atr) # print(d.atr) Print (d2.__mro__) # print(d2.__mro__) # print(d2.__mro__) # print(d2.__mro__) # if __name__ == '__main__': Test_search ()>>> python newstyle.py #Copy the code

Refer to the property inheritance search mentioned earlier in Python object-oriented programming (1)

  • The top-level base class is not the same

# newstyle.pyclass A1(object):attr = 1class A2(object):attr = 2class B(A1):passclass C(A2):attr = 4class T(A2):passclass D2(B,T,C):passdef test_search(): d = D2() print(d.atr) print(d2.__mro__) >>> Python newstyle.py #Copy the code

New class extensions

Use the __slots__ slot to store the attribute names of instance objects

  • 1. Definition: Assigning a sequence of string attribute names, store string attribute names with a sequence

  • 2. How it works:

    • 1) Avoid adding random instance attributes of the class. Only the attributes specified by the slot can be set and accessed

    • 2) It can optimize memory usage and speed up program execution

  • 3. The statement:

    • 1) Defined by the built-in attribute __slots__ variable

    • 2) Must be defined in the statement at the top of the class

  • 4. Attention points:

    • You must assign a value to the attribute name defined by the slot, and accessing it without assigning it will result in an AttributeError

  • 5. Code testing

# newstyle_extend.pyclass MyObject(object): __slots__ = ['age','name','job']def test_slots(): Obj = MyObject() # print(obj.age) # print(obj.age) # print(obj.age) # obj.hobby = u newstyle_extend.pyCopy the code

  • 6. Slot and namespace dictionaries

    • __slots__ excludes instance dictionary attributes unless dictionary attributes are explicitly defined in slots

    • Whenever we need to define attributes outside the slot to be stored in the namespace dictionary, we need to add an attribute to the slot, __dict__

# newstyle_extend.pyclass MyObject(object): __slots__ = ['age','name','job','__dict__']def test_slots(): Obj = MyObject() # Obj. hobby = u" The hobby property in slots that do not exist will be stored in the namespace dictionary "print(obj.__dict__)>>> python newstyle_extend.pyCopy the code

  • 7. When using slots in the inheritance tree, the subclass inherits the slot attributes of the parent class

# newstyle_extend.pyclass D(object): __slots__ = ['a','b']class E(object): __slots__ = ['c', 'd']class M(E): __slots__ = ['xx','a'] # multiple bases have instance lay-out conflictdef test_inherhit_class(): m = M() print(dir(m))>>> python newstyle_extend.pyCopy the code

Attribute accessor

  • The property function is used to get properties in the format property(GET,set,del,doc), which contains operations to get,set, delete, and document properties

# property.pyclass PropertyObject(object): def get_name(self): print("call get_name method..." ) return "keithl" def set_name(self, value): print("call set_name method for value[%s]..." % value) self.__name = value name = property(fget = get_name,fset = set_name)def test_property(): po = PropertyObject() print(po.name) po.name = "xiaokun"if __name__ == '__main__': test_property()>>> python property.pyCopy the code

  • Use a decorator instead of the above property Settings

# property.pyclass PropertyObject(object): @property def name(self): print("call get_name method..." ) return "keithl" @name.setter def name(self,value): print("call set_name method value[%s]..." % value) self.__name = value ... The test code is omitted >>> Python property.pyCopy the code

Attribute tools: __getAttribute__ and descriptors

The relationship between attribute retrieval and overloaded operators has been explained in detail. If you are not familiar with this, you can refer to Python object-oriented Programming (5).

  • The __getAttribute__ method in the new class intercepts all attribute-fetching operations, including those defined by the above attributes

  • Use the class descriptor __get__& __set__

# property.pyclass NameDescriptor(object):
    def __get__(self, instance, owner):return "get_keithl"
    def __set__(self, instance, value):instance._name="set_"+valueclass descriptors(object):
    name = NameDescriptor()def test_name_desc():
    nd = descriptors()
    print(nd.name)
    nd.name = "keithl"
    print(nd.name)
    print(nd._name)>>> python property.pyCopy the code

If there is harvest, welcome to forward ~