Python has mutable and immutable types. Modifiable differ in that their contents can be changed without changing the link to them. Immutable objects must be recreated to reflect state changes. In this case, all the old links do not see this update, because they point to the old object.
I will explain in practice. Lists, dictionaries, sets are mutable objects:
l1 = [1, 2, 3] l2 = l1 print(l1, l2, id(l1), id(l2)) # [1, 2, 3] [1, 2, 3] 139917408901064 139917408901064 l1[1] = 10 print(l1, l2, id(l1), id(l2)) # [1, 10, 3] [1, 10, 3] 139917408901064 139917408901064
Numbers, strings, tuples are immutable objects:
v1 = 1024 v2 = v1 print(v1, v2, id(v1), id(v2)) # 1024 1024 ...7040 ...7040 v1 = 2048 print(v1, v2, id(v1), id(v2)) # 2048 1024 ...5312 ...7040 t1 = (1, 2, 3) t2 = t1 print(t1, t2, id(t1), id(t2)) # (1, 2, 3) (1, 2, 3) ...6232 ...6232 # t1[1] = 10 # Π½Π΅ ΡΡΠ°Π±ΠΎΡΠ°Π΅Ρ, ΡΠ°ΠΊ ΠΊΠ°ΠΊ ΠΊΠΎΡΡΠ΅ΠΆΠΈ Π½Π΅ΠΈΠ·ΠΌΠ΅Π½ΡΠ΅ΠΌΡΠ΅ t1 = (1, 10, 3) print(t1, t2, id(t1), id(t2)) # (1, 10, 3) (1, 2, 3) ...7240 ...6232
In your code, you use mutable data structures such as dictionaries and lists ( user
, userdata
, server
) and immutable strings and numbers.
Thus, without changing anything in the information storage structure, you can only minimize access to the list of numbers.
my_userdata = server[serveraddr][username] # ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ my_userdata Π²Π»Π΅ΡΡΡ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ server[serveraddr][username], # ΡΠ°ΠΊ ΠΊΠ°ΠΊ ΡΡΠΎ ΠΎΠ΄ΠΈΠ½ ΠΈ ΡΠΎΡ ΠΆΠ΅ ΠΎΠ±ΡΠ΅ΠΊΡ
Since the numbers are immutable, saving them to a variable and further changing this variable does not affect the original number (that is, the joincount
variable joincount
never change when changing server[serveraddr][username][0]
and vice versa). changing the numbers in this list will not affect the variables storing these values
But if you try to improve the code a bit, you should create a class UserData
, which will store the necessary values ββin itself and allow them to be changed. The minimum example would be as follows:
class UserData: def __init__(self, joincount, leftcount, gamescount, wincount): self.joincount = joincount self.leftcount = leftcount self.gamescount = gamescount self.wincount = wincount username = "test" userdata = UserData(10, 2, 30, 15) user = {username:userdata}
After that, if we get our user from somewhere, we can change the desired values:
user_data = server[serveraddr][username] user_data.joincount = 20 user_data.leftcount = 9 user_data.gamescount = 10 user_data.wincount = 3 print (server[serveraddr][username].joincount, server[serveraddr][username].leftcount, server[serveraddr][username].gamescount, server[serveraddr][username].wincount) print (user_data.joincount, user_data.leftcount, user_data.gamescount, user_data.wincount)
Using a similar structure will increase the readability of your code, compared to using list indexes.
If you have access to change the contents of the dictionary, I would recommend that you use the namedtuple
from the standard collections
module, which allows you to create an object similar in behavior to a tuple, but providing access to the fields like the one above (but only for reading) instead of the samopisny class.
UserData = collections.namedtuple('UserData', ['joincount', 'leftcount', 'gamescount', 'wincount'])
In this case, you will have to replace the old UserData
object with a new one:
old_userdata = server[serveraddr][username] new_userdata = UserData(joincount=20, leftcount=9, gamescount=10, wincount=3) server[serveraddr][username] = new_userdata print(new_userdata, old_userdata, server[serveraddr][username])
Getting the field to read will be performed in the same way as in the example above:
print(old_userdata.joincount, old_userdata.gamescount)