1 formatted output of object
(1) If you need to format the output of an object (instance), you can override the class__ repr__ () and__ str__ () method.
The difference between the two: when using the interactive interpreter to output objects, the result is__ repr__ () the string returned by the method; Using the str() or print() function will output__ str__ The string returned by () method.
See the following example:
class Point: """Points in 2D coordinate system""" def __init__(self, x, y): self.x = x self.y = y def __repr__(self): return "Point({0.x!r}, {0.y!r})".format(self) def __str__(self): return "({0.x!s}, {0.y!s})".format(self)
Results in the interactive command line [ipython]:
In [2]: point = Point(1, 2) In [3]: point Out[3]: Point(1, 2) In [4]: print(point) (1, 2)
It can be seen that in the interactive environment, the formatted output object is Point(1, 2); The objects printed by print() are (1, 2).
(2) Note that it is used in formatting! r indicates output usage__ repr__ () instead of the default__ str__ ().
In [5]: print("point is {!r}".format(point)) point is Point(1, 2) In [6]: print("point is {!s}".format(point)) point is (1, 2) In [7]: print("point is {}".format(point)) point is (1, 2)
If__ str__ () is not defined and will be used__ repr__ () instead of output. Generally speaking, custom__ repr__ () and__ str__ () is a good habit because it simplifies debugging and instance output.
2 get the description of the class
Can pass__ doc__ This special field obtains the class description (i.e. class annotation), usage and class name__ doc__, See the following examples:
''' No one answers the problems encountered in learning? Xiaobian created a Python exchange of learning QQ Group: 531509025 Look for like-minded friends to help each other,There are also good videos and tutorials in the group PDF e-book! ''' class A: """description...""" def func(self): pass print(A.__doc__) # description...
3 get all members of a class or object
Can pass__ dict__ Get all the member information (dictionary form) of the class or object, usage and class name__ dict__ Or object__ dict__, See the following example:
class A: def __init__(self, name): self.name = name def func(self): pass # Gets all members of the class print(A.__dict__) #{'__module__': '__main__', 'func': <function A.func at 0x00000000025976A8>, '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None} # Gets all members of the object obj = A("Liu You Yuan") print(obj.__dict__) # {'name': 'Liu You Yuan'}
You can see that among the class and object members, only the general field is stored in the object, and other members are in the class.
4 get the class name of the object creating the current operation
Pass__ class__ It can get which class the object of the current operation is created by and the usage object__ class__, See the following example:
''' No one answers the problems encountered in learning? Xiaobian created a Python exchange of learning QQ Group: 531509025 Look for like-minded friends to help each other,There are also good videos and tutorials in the group PDF e-book! ''' class A: def func(self): pass obj = A() # Get the class name where [object of current operation] is located print(obj.__class__) # <class '__main__.A'>
5 get the module name of the class that creates the object of the current operation
Pass__ module__ Can get the module and usage object of the class that creates the object of the current operation__ module__, See the following example:
class A: def func(self): pass obj = A() # Get the module name where [object of current operation] is located print(obj.__module__) # __main__
6 make objects iteratable
You just need to implement it in a class__ iter__ () method to make the object act on the for loop. See the following example:
class A: def __init__(self, lis): self.lis = lis def __iter__(self): return iter(self.lis) obj = A([2018, 0, 3, 1, 9]) for i in obj: # When an object is used for iteration, it is actually equivalent to iteration__ iter__ Method. print(i) # 2018 # 0 # 3 # 1 # 9
In the above example, if it is not implemented__ iter__ () method, object obj cannot be cycled. In fact, all data structures such as list, dict, str can be iterated is that they are implemented in their classes__ iter__ () method.
7 let the object support dictionary operation
Realize__ getitem__ / __setitem__ / __delitem__, The object can be operated like a dictionary, as shown in the following example:
''' No one answers the problems encountered in learning? Xiaobian created a Python exchange of learning QQ Group: 531509025 Look for like-minded friends to help each other,There are also good videos and tutorials in the group PDF e-book! ''' class Person: def __init__(self, name): self.name = name def __getitem__(self, k): return self.name def __setitem__(self, k, v): self.name = v def __delitem__(self, k): del self.name obj = Person("Jeo Chen") result = obj['name'] # Automatic trigger execution__ getitem__ print(result) # Jeo Chen obj['name'] = 'Liu You Yuan' # Automatic trigger execution__ setitem__ print(obj['name']) # Liu You Yuan del obj['name'] # Automatic trigger execution__ delitem__
8 optimize the memory occupied by a large number of objects
If you need to create a large number (thousands of) objects, which takes up a lot of memory, you can use special static fields__ solts__ To reduce the memory occupied by objects.
The following example compares definitions__ solts__ And undefined__ solts__ The memory size occupied by the two classes when creating a large number of objects, including [reflection knowledge] and [tracemalloc package].
The tracemalloc package is a debugging tool that tracks memory blocks allocated by Python. Of which:
(1) The tracemalloc.start() method means to start tracking Python memory allocation. At the beginning, the memory occupation is set to 1; tracemalloc.stop() means to stop tracking;
(2)tracemalloc.get_ traced_ The memory () method can obtain the current size and peak size of the memory block tracked by the tracemalloc module as tuples: (current: int, peak: int), in bytes.
See the following example for details:
import tracemalloc ITEM_NUM = 10 class HaveSlots: __slots__ = ['item%s' % i for i in range(ITEM_NUM)] def __init__(self): for i in range(len(self.__slots__)): setattr(self, 'item%s' % i, i) class NoSlots: def __init__(self): for i in range(ITEM_NUM): setattr(self, 'item%s' % i, i) # Start tracking tracemalloc.start() obj = [NoSlots() for i in range(100)] # Obtain the current size and peak size of the memory block tracked by the tracemalloc module as tuples: (current: int, peak: int) print(tracemalloc.get_traced_memory()) # cease tracking tracemalloc.stop() # Start tracking again, which is equivalent to resetting tracemalloc.start() obj2 = [HaveSlots() for i in range(100)] print(tracemalloc.get_traced_memory()) # (21832, 22219) # Undefined__ slots__ Field, creating 100 objects takes about 21832 bytes of memory # (13760, 14147) # Definition__ slots__ Field, creating 100 objects takes about 13760 bytes of memory
As can be seen from the above example, when defined__ slots__ Field, the memory used to create a large number of objects (13760) is significantly less than that not defined__ slots__ Field memory (21832). Perhaps, the memory size you get is inconsistent with what I get, but it does not affect the final conclusion.
__ slots__ What has been done to reduce memory?
(1) By default, custom objects use dict to store attributes (viewed through obj. _dict_). The bottom layer of dict in python needs to consider "reducing hash conflict". Therefore, dict occupies a larger storage space than the actually stored elements, which will waste some space.
(2) Use__ slots__ Only these are used for the objects created by the later class_ slots__ Defined fields, that is, each object constructs fields through a small fixed size array, not a dictionary.
It should be noted that:
(1) If so__ slots__, Then there will be no more objects__ dict__ Properties.
(2) Use__ slots__ This means that you can't add new attributes to the instance. You can only use the__ slots__ Property names defined in.
(3) Defined__ slots__ The new class no longer supports some common class features, such as multi inheritance.
So if you need to create thousands of objects__ slots__ More applicable; In other cases, it is still necessary to reduce__ slots__ Impulse to use.
9 construction method
Class__ init__ () method is the construction method of a class. When an object is created through a class, execution is automatically triggered. See the following example:
''' No one answers the problems encountered in learning? Xiaobian created a Python exchange of learning QQ Group: 531509025 Look for like-minded friends to help each other,There are also good videos and tutorials in the group PDF e-book! ''' class A: def __init__(self, name): self.name = name print("this is __init__") # Automatically triggered when an object is created__ ini__ method. obj = A("Jeo Chen") # this is __init__
Until this time, the construction method is introduced to pave the way for the following content. It is not accurate to automatically trigger the execution of the construction method when creating an object. Read on to introduce it__ init__ The real role of.
10 deconstruction method
__ del__ Method is the destructor method of a class. When the object is released in memory, it will automatically trigger execution. However, Python is a high-level language with garbage collection mechanism. We don't need to care about memory allocation and release. A destructor method that is automatically triggered by the interpreter during garbage collection.
class A: def __del__(self): pass
11 __call__ method
When parentheses are added after the object, that is, [object ()] will be triggered automatically__ call__ Method, which should be different from the construction method. The construction method is to add parentheses after the class name, that is, the [class name ()] is triggered.
class A: def __call__(self): print("this __call__") obj = A() obj() # Object is followed by parentheses to trigger__ call__ # this __call__
12 __new__ method
In fact, when you create an object, you call__ init__ Method is called__ new__ method. We can prove by the following example:
''' No one answers the problems encountered in learning? Xiaobian created a Python exchange of learning QQ Group: 531509025 Look for like-minded friends to help each other,There are also good videos and tutorials in the group PDF e-book! ''' class A: def __init__(self, name): print("In A init") self.name = name def __new__(cls, *args, **kwargs): print("In A new",) return object.__new__(cls) # Creation object obj = A("Liu You Yuan") # In A new # In A init
So__ new__ What's the use of this method? The following example demonstrates not calling__ init__ Method to create an object, as shown below:
class Person: def __init__(self, name): print("in Person init") self.name = name def __new__(cls, *args, **kwargs): print("In Person new",) return object.__new__(cls) # Do not call__ init__ () method to create a Person object obj = Person.__new__(Person) print(obj) print(obj.name)
The results are as follows:
In Person new <__main__.Person object at 0x00000000025E8EB8> Traceback (most recent call last): File "D:/githubfile/pythonclub/object-oriented/new.py", line 34, in <module> print(obj.name) AttributeError: 'Person' object has no attribute 'name'
Analysis output:
(1) "In Person new" is printed on the first line, indicating that it is indeed called__ new__ method; In addition, the "in Person init" description is not printed, and there is indeed no call__ init__ method.
(2) The second line is printed<__ main__. Person object at 0x00000000025e8eb8 > indicates that an object has indeed been created.
(3) Then there is an error. The error content says AttributeError: 'Person' object has no attribute 'name', and the object has no name attribute (field).
In conclusion, the result of the above example is self-evident:
(1)__ new__ Method is the one that really creates the object, but the object it creates is not called__ init__ It has not been initialized before.
(2)__ init__ The method is to initialize the object. The [initialization] process is to encapsulate the field into the object, which can be accessed through the object. Field.
How did class 13 come into being
It is often heard that "everything in python is an object". In this way, the "class" itself is also an object. Since it is an object, there must be a class to create it. In other words, the object "class" is instantiated from "a special class". This special class is type(), also known as metaclass.
In addition to the class keyword described earlier, classes can also be defined through type(), as shown in the following example:
''' No one answers the problems encountered in learning? Xiaobian created a Python exchange of learning QQ Group: 531509025 Look for like-minded friends to help each other,There are also good videos and tutorials in the group PDF e-book! ''' def __init__(self, name): self.name = name def hello(self): print("hello {}".format(self.name)) # Define the class with type(). The first parameter is the class name, the second parameter is the base class of the current class, and the third parameter is the member of the class Person = type('Person', (object,), {'sayHi': hello, "__init__": __init__}) obj = Person("Liu") print(obj) # <__main__.Person object at 0x0000000002368E80> obj.sayHi() # hello Liu
This proves that a class can also be defined through the metaclass type(), and the effect is the same as that defined with the class keyword, but this method is not commonly used.
What is the relationship between type() and the classes and objects we usually create? We can find out through the following example:
class MyType(type): def __init__(self, child_cls, bases=None, dict=None): print("In MyType init") super(MyType, self).__init__(child_cls, bases, dict) def __new__(cls, *args, **kwargs): print("In MyTyPe new") return type.__new__(cls, *args, **kwargs) def __call__(self, *args, **kwargs): print("In MyType call") obj = self.__new__(self, args, kwargs) self.__init__(obj, *args, **kwargs) class Person(object, metaclass=MyType): def __init__(self, name): print("In Person init") self.name = name def __new__(cls, *args, **kwargs): print("In Person new",) return object.__new__(cls)
In the above example code, it is worth noting that:
(1) MyType inherits the type class and customizes it__ init__ / __new__ / __call__ method.
(2) There is a parameter metaclass in the Person class, which is used to specify the class to create the Person. That is, metaclass specifies that the MyType class creates the Person object through instantiation.
(3) Here's another word. For us, Person is a class defined by us; For MyType, Person is an object created by MyType.
The output results of the above example are as follows:
In MyTyPe new In MyType init
It can be seen that we only defined two classes and made some custom modifications. When you run the above code, you have called the of the MyType class__ new__ And__ init__ Method, that is, at this time, the Person object has been created through MyType.
Then we add a line in the above example and run:
obj = Person("Liu You Yuan")
The operation results are as follows:
In MyTyPe new In MyType init In MyType call In Person new In Person init
analysis:
(1) When the code obj = Person("Liu You Yuan") is executed, we regard Person as an object created by MyType, so this line of code adds parentheses after the Person object, which will trigger the error in the MyType class__ call__ Method, print "In MyType call";
(2) At this point__ call__ Self in is the object of Person, through self__ new__ / self.__ init__ Active call to in Person__ new__ And__ init__, This creates the obj object.
So far, we know that when we create a Class A and create the object obj through class A, we actually go through two processes:
(1) Create the class A defined by us through the metaclass type.
(2) Create object obj through class A.