Get object Information
To get a variable, in addition to using isinstance () to determine whether it is a certain type of instance, there is no other way to obtain more information?
For example, there are already definitions:
class person (object ): def __init__ (self , Name, gender): se LF . Name = name self . Gender = gender< span class= "kw" >class Student (person): def __init__ (self , Name, gender, score): super (Student, self ). __init__ (Name, gender) self . Score = score def WhoAmI (self ): return ' I am a Student, my name is %s " % self . Name
You can first get the type of the variable with the type () function, which returns a type object:
>>>type(123)<type'int'>>>>= Student('Bob''Male'88)>>>type(s)<class'__main__.Student'>
Second, you can use the Dir () function to get all the properties of a variable:
>>> dir(123)# integers also have many properties ...[' __abs__ ',' __add__ ',' __and__ ',' __class__ ',' __cmp__ ', ...]>>> dir(s) [' __class__ ',' __delattr__ ',' __dict__ ',' __doc__ ',' __format__ ',' __getattribute__ ',' __hash__ ',' __init__ ',' __module__ ',' __new__ ',' __reduce__ ',' __reduce_ex__ ',' __repr__ ',' __setattr__ ',' __sizeof__ ',' __str__ ',' __subclasshook__ ',' __weakref__ ',' Gender ',' name ',' score ',' WhoAmI ']
For instance variables, dir () returns all instance properties, including __class__
those that have special meaning. Notice that the method whoAmI
is also a property of S.
How do you get rid __xxx__
of special attributes of this class, leaving only our own defined properties? Review the use of the filter () function.
The property returned by Dir () is a list of strings, and if a property name is known, the GetAttr () and SetAttr () functions are required to get or set the properties of the object:
>>> GetAttr(S,' name ')# Get the Name property' Bob '>>> SetAttr(S,' name ',' Adam ')# Set the new Name property>>>S.name' Adam '>>> GetAttr(S,' age ')# Gets the Age property, but the attribute does not exist, error:Traceback (most recent): File"<stdin>", line1,inch <Module>Attributeerror:' Student ' Objecthas no attribute' age '>>> GetAttr(S,' age ', -)# Gets the Age property and returns the default value if the property does not exist: -
New and Legacy classes
The new Python class is introduced in version 2.2, and we can call the previous Class A classic or old class.
Why should we introduce it in 2.2 new style class
? The official explanation is: to unify classes (class)
and types (type)
.
Before 2.2, for example, in version 2.1, classes and types are different,
If a
It is ClassA
an instance,
Then a.__class__
return class __main__.ClassA
, type (a) returns always <type ‘instance‘>
.
The introduction of a new class, such as a ClassB
new class, b
is an ClassB
instance of, b.__class__
and all are type(b)
returned ‘class ‘__main__.ClassB‘
, so it is unified.
With the introduction of new classes, there are other benefits, such as the introduction of more built-in properties, the introduction of descriptors, the ability to calculate attributes, and so on. For forward compatibility, the user-defined class is the classic class by default, and the new class needs to inherit from the base class of all classes object or a new class that inherits from Object.
? It is important to note that while using the latest Python (2.7), some features do not work in legacy classes.
? Therefore, in order to ensure that you are using a new class, there are the following methods:
? Put this assignment statement at the front of the class module code __metaclass__ = type
(mentioned earlier).
? Their classes object
inherit directly or indirectly from the built-in classes.
? If you do not need to be compatible with legacy classes, the old version of the class is maintained as a new class.
? Of course, there are Python3
no such problems, because all classes are subclasses object
of the Class (implicit).
# Encoding:utf-8# Comparison of new and old classesclassOldstyle:def __init__( Self, name, description): Self. Name=Name Self. description=Description#新类, you can add __metaclass__ = Type hereclassNewStyle (Object):#新类 can also be directly inherited to the object class def __init__( Self, name, description): Self. Name=Name Self. description=Descriptionif __name__ == ' __main__ ': Old=Oldstyle (' old ',' Old Style class ')Print(old.__class__)Print((type(old)))Print((dir(old)))Print('-------------------------------------------------------') New=NewStyle (' new ',' New style class ')Print(new.__class__)Print((type(new)))Print((dir(new)))
Operation Result:
__main__. Oldstyle<type ' instance '>[' __doc__ ',' __init__ ',' __module__ ',' description ',' name ']-------------------------------------------------------<class ' __main__. NewStyle '><class ' __main__. NewStyle '>[' __class__ ',' __delattr__ ',' __dict__ ',' __doc__ ',' __format__ ',' __getattribute__ ',' __hash__ ',' __init__ ',' __module__ ',' __new__ ',' __reduce__ ',' __reduce_ex__ ',' __repr__ ',' __setattr__ ',' __sizeof__ ',' __str__ ',' __subclasshook__ ',' __weakref__ ',' description ',' name '][finishedinch 0.1s]
Multi-inheritance Property lookup mechanism
If you treat each class as a point, and many classes form a graph, then the inheritance mechanism in Python is a search
So, is this search a depth-first search or a breadth-first search?
The above-mentioned problem is also known mro
method resolution order
as the path (from which class) that is used primarily to determine the properties of a tune at multiple inheritance.
In the old class (before the Python2.3) the multi-inheritance mechanism of the class is based on depth-first search, but in the new class (from Python2.3) The multi-inheritance mechanism of the class is based on the C3 algorithm similar to the breadth-first search.
C3 algorithm
The C3 algorithm was first proposed to be used in Lisp, and it was applied in Python to solve the problem that the original depth-first search algorithm did not satisfy the local priority and monotonicity.
- Local precedence: Refers to the order of the parent class at the time of declaration, such as C (A, A, b), and if you access the Class C object properties, you should first find class A in order of declaration, and then look for class A.
- Monotonicity: If in the parse order of C, a is in front of B, then in all subclasses of C, this order must also be fulfilled.
In a new class, it is a breadth-first search when looking for a function or property to invoke.
In the old class, it is a depth-first search. As shown in the following:
Several methods in Python that provide inheritance order:
mro
Method
__mro__
Property
inspect
Method of the module getmro
import inspectclass A: passclass B(A): passprint(B.mro())print(B.__mro__)print(inspect.getmro(B))
Operation Result:
[<class ' __main__. B '>,<class ' __main__. A '>,<class ' object '>](<class ' __main__. B '>,<class ' __main__. A '>,<class ' object '>)(<class ' __main__. B '>,<class ' __main__. A '>,<class ' object '>)
From the above results, the results of the tuple as a result __mro__
and inspect.getmro
appear to be more satisfying.
深度优先
And
广度优先
- Inheritance mechanism of deep-first search for legacy classes
# -*- coding:utf-8 -*-fromimport getmroclass D: passclass B(D): passclass C(D): passclass A(B, C): passif__name__=='__main__': print(getmro(A))
Operation Result:
(<class0x0000000002CEC888><class0x0000000002CECE88>,<class0x0000000002CEC8E8><class0x0000000002CECD68>in0.1s]
- The inheritance mechanism of breadth-first search for new class
# -*- coding:utf-8 -*-fromimport getmroclass D(object): passclass B(D): passclass C(D): passclass A(B, C): passif__name__=='__main__': print(getmro(A))
Operation Result:
(<class'__main__.A'><class'__main__.B'>, <class'__main__.C'><class'__main__.D'>, <type'object'>in0.1s]
Python object-oriented-extension