Actual case :
In an online game , Defines the player class Player(id, name, status, ...), Every online player , Inside the server program is a Player Example , When there are a lot of people online , There will be a lot of examples .( Like a million )
How to reduce the memory overhead of these large instances ?
Solution :
Defining a class __slots__ attribute , It is a list for declaring instance attribute names , Reduce the number of instances __dict__ Dictionary to achieve the purpose of saving memory overhead .
class Player(object):
def __init__(self, uid, name, status=0, level=1):
self.uid = uid
self.name = name
self.status = status
self.level = level
class Player2(object):
# Definition __slots__ Variable , It is used to declare which attributes the instance has
# The function is to prevent the instance from being allocated when the class is instantiated dict
__slots__ = ['uid', 'name', 'status', 'level']
def __init__(self, uid, name, status=0, level=1):
self.uid = uid
self.name = name
self.status = status
self.level = level
'''
__slots__ Introduction to built-in methods :
(1)__slots__ Allows you to declare and qualify class members , And refuse to create __dict__
and __weakref__ Property to save memory space .
(2) Is defined. __slots__ After the variable , Class instances can no longer be created at will _
_slots__ Properties defined , At the same time, there are no more __dict__ structure .
(3) Inheritance tree :
Subclass not declared __slots__ when , Does not inherit from the parent class __slots__,
That is, the subclass can assign attributes at will .
Subclass declares __slots__ when , Inherited from the parent class __slots__, That is, of the subclass at this time
__slots__ For itself + Of the parent class __slots__.
'''
# establish Player and Player2 Example
p1 = Player('0001', 'Bob')
p2 = Player2('0001', 'Bob')
# p1 Than p2 Use more memory , View through the difference of the set
print(set(dir(p1)) - set(dir(p2)))
# The output is :{'__dict__', '__weakref__'}
'''
It can be seen that p1 Than p2 More __dict__ and __weakref__ attribute , Without using weak references
__weakref__ It doesn't take up much memory , Eventually, the occupation will fall to __dict__ On .
'''
# __dict__ Is a dictionary for dynamically binding attributes to instances
print(p1.__dict__)
# Such as p1 No, x attribute , by p1 Dynamically bind a x attribute
p1.x = 123
p1.__dict__['y'] = 99
# You can find x and y Into the dictionary
print(p1.__dict__)
# You can also dynamically delete ( relieve )
del p1.__dict__['y']
print(p1.__dict__)
'''
Such a feature of dynamically binding attributes is at the expense of memory ,
To save memory, turn off the feature of dynamic binding attributes and use __slots__.
'''
import sys
# Get the memory used by an object
print(sys.getsizeof(p1.__dict__))
'''
It is not allowed to define additional attributes in advance . Such as : by p2 Bind new properties ,
Will report a mistake AttributeError: 'Player2' object has no attribute 'x'
This is similar to C The structure of language , Allocate these spaces in advance , This achieves the goal of saving memory .
There is one missing __dict__ Dictionaries ,__slots__ The side effect is to prevent dynamic attribute binding .
'''
# p2.x = 123