I'm writing a space trading game in Python, and I've decided that the map needs to be split into smaller chunks to reduce the number of objects that need to be considered for drawing on the screen at any given time.
This is handled by having a Sector object, which is defined as such:
class Sector:
x=0 #Position of the sector. The galactic (absolute) position of any object is its in-sector position
y=0 #plus the galactic position offset times the size of a sector.
stardict=dict()
Then, the generator code populates each sector (100 of them at the moment) with 75 stars, kept in stardict.
thesector=Sector()
size=size/2
#Generate stars
for t in range(stars):
#name="Star "+str(t)
name=generate_name().capitalize()
thesector.stardict[name]=Star( name, (random.randint(-size,size), random.randint(-size,size)), (random.randint(0,255), random.randint(0,255), random.randint(0,255)), random.randint(3,7))
if math.floor((t/stars)*100)==(t/stars)*100: print("Generating stars: "+str((t/stars)*100)+"% done.")
However, there's some strange bugs when trying to actually run the program, and opening it with the debugger shows why: the stardict attribute of each sector is identical, they each contain the exact same stars (not duplicates, they have the same memory address). As far as I can tell, each Sector.stardict is actually referencing the same dict object.
I have no idea why this is happening. Can anyone shed some light on this?
They are refering to the same object. This is a very common gotcha. If you want them to each have their own dict
, you need to have it created in the __init__
method.
class Sector:
x = 0 #Position of the sector. The galactic (absolute) position of any object is its in-sector position
y = 0 #plus the galactic position offset times the size of a sector.
def __init__(self):
self.stardict = dict()
As your code currently stands, when you try to access stardict
via self.stardict
, python first looks for stardict
on the instance, but when it doesn't find a stardict
attribute there, it looks on the class. It finds stardict
on the class, so it uses that. But, this implies that all instances find the same stardict
(since they all instances of the same class) -- an update to one of their stardict
and all of the others will know (faster than light speed!)*.
*Note that this doesn't voilate any laws of physics. Since they are the same object, there is no distance for the information to travel ...
来源:https://stackoverflow.com/questions/15489567/all-instances-of-a-class-have-the-same-dict-as-an-attribute-in-python-3-2