2017-01-01 27 views
5

Tôi đang xây dựng một tiện ích Python sẽ liên quan đến việc ánh xạ các số nguyên thành chuỗi từ, trong đó nhiều số nguyên có thể ánh xạ tới cùng một chuỗi. Từ sự hiểu biết của tôi, Python thực tập các chuỗi ngắn và hầu hết các chuỗi được mã hóa cứng theo mặc định, tiết kiệm phí trên bộ nhớ là kết quả bằng cách giữ một phiên bản "chuẩn" của chuỗi trong bảng. Tôi nghĩ rằng tôi có thể hưởng lợi từ điều này bằng cách thực hiện các giá trị chuỗi, mặc dù chuỗi interning được xây dựng nhiều hơn cho tối ưu hóa băm then chốt. Tôi đã viết một bài kiểm tra nhanh để kiểm tra chuỗi bình đẳng cho các chuỗi dài, đầu tiên chỉ với các chuỗi được lưu trữ trong một danh sách, và sau đó các chuỗi được lưu trữ trong từ điển dưới dạng các giá trị. Hành vi bất ngờ đối với tôi:Trong Python, tại sao các giá trị chuỗi từ điển riêng biệt vượt qua "trong" kiểm tra bình đẳng? (chuỗi Thử nghiệm Interning)

import sys 

top = 10000 

non1 = [] 
non2 = [] 
for i in range(top): 
    s1 = '{:010d}'.format(i) 
    s2 = '{:010d}'.format(i) 
    non1.append(s1) 
    non2.append(s2) 

same = True 
for i in range(top): 
    same = same and (non1[i] is non2[i]) 
print("non: ", same) # prints False 
del non1[:] 
del non2[:] 


with1 = [] 
with2 = [] 
for i in range(top): 
    s1 = sys.intern('{:010d}'.format(i)) 
    s2 = sys.intern('{:010d}'.format(i)) 
    with1.append(s1) 
    with2.append(s2) 

same = True 
for i in range(top): 
    same = same and (with1[i] is with2[i]) 
print("with: ", same) # prints True 

############################### 

non_dict = {} 
non_dict[1] = "this is a long string" 
non_dict[2] = "this is another long string" 
non_dict[3] = "this is a long string" 
non_dict[4] = "this is another long string" 

with_dict = {} 
with_dict[1] = sys.intern("this is a long string") 
with_dict[2] = sys.intern("this is another long string") 
with_dict[3] = sys.intern("this is a long string") 
with_dict[4] = sys.intern("this is another long string") 

print("non: ", non_dict[1] is non_dict[3] and non_dict[2] is non_dict[4]) # prints True ??? 
print("with: ", with_dict[1] is with_dict[3] and with_dict[2] is with_dict[4]) # prints True 

Tôi nghĩ rằng kiểm tra không chính thống sẽ dẫn đến việc in ra "False", nhưng tôi đã hiểu nhầm. Có ai biết điều gì đang xảy ra không, và liệu chuỗi thực tập có mang lại lợi ích gì trong trường hợp của tôi không? Tôi có thể có nhiều, nhiều hơn nhiều khóa hơn giá trị duy nhất nếu tôi hợp nhất dữ liệu từ một số văn bản nhập, vì vậy tôi đang tìm cách tiết kiệm dung lượng bộ nhớ. (Có lẽ tôi sẽ phải sử dụng một cơ sở dữ liệu, nhưng đó là ngoài phạm vi của câu hỏi này.) Cảm ơn bạn trước!

+1

Điều 2357112 cho biết. Lưu ý rằng các chuỗi được xây dựng thường sẽ không tái chế một giá trị tập trung, ví dụ: 'a = 'một chuỗi dài"; b = "một chuỗi dài" + "; in (id (a) == id (b))' in ' Sai' –

Trả lời

4

Một trong các tối ưu hóa được thực hiện bởi trình biên dịch bytecode, tương tự nhưng khác với thực tập, là nó sẽ sử dụng cùng một đối tượng cho các hằng số bằng nhau trong cùng một khối mã. Các chuỗi ký tự ở đây:

non_dict = {} 
non_dict[1] = "this is a long string" 
non_dict[2] = "this is another long string" 
non_dict[3] = "this is a long string" 
non_dict[4] = "this is another long string" 

nằm trong cùng một khối mã, vì vậy các chuỗi bằng nhau được biểu diễn bởi cùng một đối tượng chuỗi.

+0

Ah đúng vậy! Tôi vừa thử điều này, và giới thiệu sự thay đổi thời gian chạy dẫn đến việc in ra sai mong đợi. Cảm ơn bạn đã làm rõ. u_in = input ("nhập vào một chuỗi thời gian chạy:") non_dict = {} non_dict [1] = "đây là một chuỗi dài" + u_in non_dict [2] = "đây là một chuỗi dài" + u_in non_dict [3] = "Đây là một chuỗi dài" + u_in không bị hủy bỏ [4] = "đây là một chuỗi dài" + u_in – synchronizer

Các vấn đề liên quan