Python Medium sys Modules are extremely basic and important , It mainly provides some for the interpreter to use ( Or maintained by it ) The variable of , And some functions that strongly interact with the interpreter .
This article will make frequent use of the module's getsizeof() Method , therefore , Let me briefly introduce :
Here is an intuitive example :
import sys
a = [1, 2]
b = [a, a] # namely [[1, 2], [1, 2]]
# a、b There are only two elements , So the size of the direct occupancy is the same
sys.getsizeof(a) # result :80
sys.getsizeof(b) # result :80
The example above illustrates one thing : A statically created list , If there are only two elements , So the memory it uses is 80 byte , No matter what the element points to .
Okay , Have this measuring tool , Let's explore Python What little secrets are hidden in the built-in objects of .
1、 Empty object is not “ empty ” Of !
For some of the empty objects we are familiar with , For example, an empty string 、 An empty list 、 Empty dictionary, etc , I wonder if you have ever been curious , Have you ever thought about these problems :
Empty objects do not occupy memory ? If it takes up memory , How much does it take ? Why is it allocated like this ?
Go straight to the code , Let's take a look at the size of empty objects of several basic data structures :
import sys
sys.getsizeof("") # 49
sys.getsizeof([]) # 64
sys.getsizeof(()) # 48
sys.getsizeof(set()) # 224
sys.getsizeof(dict()) # 240
# As a reference :
sys.getsizeof(1) # 28
sys.getsizeof(True) # 28
so , Although they are all empty objects , But these objects are not in memory allocation “ empty ”, And the distribution is quite large ( Remember these numbers , I will take the exam later ).
Arrange the order : Basic figures < An empty tuple < An empty string < An empty list < Empty set < An empty dictionary .
How to explain this little secret ?
Because these empty objects are containers , We can understand in abstract : Part of their memory is used to create the skeleton of the container 、 Record container information ( Such as reference count 、 Usage information, etc )、 Some of the memory is pre allocated .
2、 Memory expansion is not uniform !
Empty object is not empty , Part of the reason is Python The interpreter allocates some initial space for them . Without exceeding the initial memory , Every time you add elements , Just use the existing memory , Thus, it avoids applying for new memory .
that , If the initial memory is allocated , How is the new memory allocated ?
import sys
letters = "abcdefghijklmnopqrstuvwxyz"
a = []
for i in letters:
a.append(i)
print(f'{len(a)}, sys.getsizeof(a) = {sys.getsizeof(a)}')
b = set()
for j in letters:
b.add(j)
print(f'{len(b)}, sys.getsizeof(b) = {sys.getsizeof(b)}')
c = dict()
for k in letters:
c[k] = k
print(f'{len(c)}, sys.getsizeof(c) = {sys.getsizeof(c)}')
Add... To three types of variable objects respectively 26 Elements , See what happens :
So we can see the secret of mutable objects when they are extended :
3、 A list is not equal to a list !
When the above mutable objects are extended , There is a similar distribution mechanism , The effect can be seen clearly in dynamic capacity expansion .
that , Is there such an allocation mechanism for statically created objects ? It's the dynamic expansion ratio , Is there a difference ?
First look at the collection and Dictionary :
# Create objects statically
set_1 = {1, 2, 3, 4}
set_2 = {1, 2, 3, 4, 5}
dict_1 = {'a':1, 'b':2, 'c':3, 'd':4, 'e':5}
dict_2 = {'a':1, 'b':2, 'c':3, 'd':4, 'e':5, 'f':6}
sys.getsizeof(set_1) # 224
sys.getsizeof(set_2) # 736
sys.getsizeof(dict_1) # 240
sys.getsizeof(dict_2) # 368
See the result , Compare the screenshot of the previous section , It can be seen that : When the number of elements is equal , Statically created collections / The memory occupied by the dictionary is exactly the same as that of dynamic expansion .
Does this apply to list objects ? Look at it together. :
list_1 = ['a', 'b']
list_2 = ['a', 'b', 'c']
list_3 = ['a', 'b', 'c', 'd']
list_4 = ['a', 'b', 'c', 'd', 'e']
sys.getsizeof(list_1) # 80
sys.getsizeof(list_2) # 88
sys.getsizeof(list_3) # 96
sys.getsizeof(list_4) # 104
The screenshot from the previous section shows , The list is at the front 4 Every element takes up 96 byte , stay 5 The elements take up 128 byte , There is a clear contradiction .
therefore , The secret is clear : When the number of elements is equal , It is possible that the memory occupied by statically created list is smaller than that of dynamic expansion !
in other words , The two lists look the same , It's actually different ! A list is not equal to a list !
4、 Pruning elements does not free memory !
As mentioned earlier , When expanding a mutable object , May apply for new memory .
that , If you reduce the mutable objects in turn , After subtracting some elements , Will the newly applied memory be recycled automatically ?
import sys
a = [1, 2, 3, 4]
sys.getsizeof(a) # Initial value :96
a.append(5) # After expansion :[1, 2, 3, 4, 5]
sys.getsizeof(a) # After expansion :128
a.pop() # After reduction :[1, 2, 3, 4]
sys.getsizeof(a) # After reduction :128
As the code shows , The list expands and shrinks , Although back to the original , But the memory space occupied is not automatically released . Other mutable objects are the same .
This is it. Python The little secret of ,“ Fat people can't lose weight ”: It's easy for thin people to get fat , It's easy to cut back , But you can't lose weight , ha-ha ~~~
5、 An empty dictionary is not equal to an empty dictionary !
Use pop() Method , Only the elements in the mutable object are reduced , But it doesn't free up the memory space that has been requested .
There's another. clear() Method , It will empty all elements of the mutable object , Let's try :
import sys
a = [1, 2, 3]
b = {1, 2, 3}
c = {'a':1, 'b':2, 'c':3}
sys.getsizeof(a) # 88
sys.getsizeof(b) # 224
sys.getsizeof(c) # 240
a.clear() # After emptying :[]
b.clear() # After emptying :set()
c.clear() # After emptying :{}, That is to say dict()
call clear() Method , We get a few empty objects .
In the first section , Their memory size has been checked .( I said that I will take the exam , Please write it back )
however , If we check again at this time , You will be surprised to find out , The size of these empty objects is not exactly the same as the previous query !
# Take the previous empty operation :
sys.getsizeof(a) # 64
sys.getsizeof(b) # 224
sys.getsizeof(c) # 72
The size of empty lists and empty tuples remains the same , But an empty dictionary (72) It's better than the empty dictionary (240) It's a lot smaller !
in other words , Lists and tuples are empty after the elements , Go back to the starting point , However , The dictionary is “ throw the helve after the hatchet ”, Not only the “ eat ” All the people who went in vomited out , I also lost my old book !
The secret of the dictionary is very deep , To tell you the truth, I just learned , puzzled ……
That's all Python A few secrets when allocating memory , After watching the , Do you think you have gained insight ?
How many have you figured out
The above is all the content shared this time , Want to know more python Welcome to official account :Python Programming learning circle , send out “J” Free access to , Daily dry goods sharing