2009-10-08 24 views
46

Tôi không chắc chắn lý do tại sao các chuỗi và bộ dữ liệu được tạo thành bất biến; lợi thế và bất lợi của việc biến chúng thành bất biến là gì?Tại sao các chuỗi python và tuple được thực hiện bất biến?

+1

ngoài việc thực hiện nội bộ trình thông dịch python, thiết kế này có tạo cảm giác tốt về viết chương trình không? (ví dụ, nó sẽ làm cho nó dễ dàng hơn nếu tuples và dây có thể thay đổi?) nếu có, những gì sẽ là ví dụ về việc chọn tuples không thay đổi vs danh sách? (hoặc có thể đọc được, các chuỗi có thể thay đổi được với các chuỗi python) – user186477

+3

Có toàn bộ kiểu lập trình được gọi là Lập trình chức năng, nơi mọi thứ đều không thay đổi được. http://en.wikipedia.org/wiki/Functional_programming –

+2

Python * KHÔNG * có chuỗi và bộ dữ liệu có thể thay đổi; chúng được đánh vần 'bytearray' và' list', tương ứng. – SingleNegationElimination

Trả lời

31

Một là hiệu suất: biết rằng một chuỗi là bất biến làm cho nó dễ dàng để đẻ nó ra vào thời điểm xây dựng - cố định và không thay đổi lưu trữ yêu cầu. Đây cũng là một trong những lý do cho sự khác biệt trong số giữa tuples và danh sách. Điều này cũng cho phép triển khai để tái sử dụng một cách an toàn chuỗi đối tượng. Ví dụ: CPython thực hiện sử dụng các đối tượng được phân bổ trước cho các chuỗi ký tự đơn, và thường trả lại chuỗi gốc cho các hoạt động chuỗi không thay đổi nội dung.

Khác là các chuỗi trong Python được coi là "nguyên tố" là số. Không có hoạt động nào sẽ thay đổi giá trị 8 thành bất kỳ điều gì khác, và bằng Python, không có hoạt động sẽ thay đổi chuỗi "tám" thành bất kỳ thứ gì khác.

http://effbot.org/pyfaq/why-are-python-strings-immutable.htm

2

ưu: Hiệu suất

khuyết điểm: bạn không thể thay đổi mutables.

+6

ưu: bạn không thể thay đổi chúng –

10

Một ưu điểm lớn của việc biến chúng thành bất biến là chúng có thể được sử dụng làm khóa trong từ điển. Tôi chắc rằng các cấu trúc dữ liệu nội bộ được sử dụng bởi các từ điển sẽ trở nên khá lộn xộn nếu các phím được phép thay đổi.

+3

Buuuuut bạn có thể khóa bằng bất kỳ cá thể đối tượng do người dùng tạo nào, mà rõ ràng là có thể thay đổi. "Chìa khóa" sau đó có lẽ chỉ là địa chỉ bộ nhớ và nếu chuỗi có thể thay đổi, bạn vẫn có thể khóa bằng địa chỉ bộ nhớ duy nhất của chúng. – Triptych

+0

@Triptych không phải là thứ bạn muốn cho chuỗi - bạn muốn chúng khóa theo giá trị, các từ điển khác sẽ ít hoặc không sử dụng .... – Hejazzman

+0

@Hejazzman đó không phải là cách mà các con trăn hoạt động. Giá trị chuỗi chữ không được sử dụng làm khóa dict, thay vào đó một giá trị băm của chuỗi được lấy. Chứng minh điều này cho chính bạn bằng ''abc' .__ hash __()'. – Triptych

69

Hãy tưởng tượng một ngôn ngữ được gọi là FakeMutablePython, nơi bạn có thể thay đổi dây sử dụng giao danh sách và như vậy (như mystr[0] = 'a')

a = "abc" 

Điều đó tạo ra một mục trong bộ nhớ trong địa chỉ bộ nhớ 0x1, có chứa "abc", và số nhận dạng a trỏ đến nó.

Bây giờ, nói rằng bạn làm ..

b = a 

Điều này tạo ra sự nhận dạng b và cũng chỉ đến địa chỉ bộ nhớ cùng một 0x1

Bây giờ, nếu chuỗi là có thể thay đổi, và bạn thay đổi b :

b[0] = 'z' 

này làm thay đổi các byte đầu tiên của chuỗi được lưu trữ tại 0x1 để z .. Kể từ khi nhận dạng 01.được trỏ đến đây để, do đó chuỗi đó sẽ thay đổi cũng có, vì vậy ..

print a 
print b 

..would cả sản lượng zbc

này có thể làm cho một số hành vi thực sự kỳ lạ, bất ngờ.phím từ điển sẽ là một ví dụ tốt về điều này:

mykey = 'abc' 
mydict = { 
    mykey: 123, 
    'zbc': 321 
} 

anotherstring = mykey 
anotherstring[0] = 'z' 

Bây giờ trong FakeMutablePython, mọi thứ trở nên khá kỳ quặc - ban đầu bạn có hai phím có trong từ điển, "abc" và "ZBC" .. Sau đó, bạn thay đổi "abc "string (thông qua mã định danh anotherstring) đến" zbc ", do đó dict có hai khóa," zbc "và" zbc "...

Một giải pháp cho sự kỳ quặc này sẽ là, bất cứ khi nào bạn gán chuỗi cho số nhận dạng (hoặc sử dụng nó như một khóa dict), nó sao chép chuỗi tại 0x1 đến 0x2.

Điều này ngăn chặn điều trên, nhưng nếu bạn có chuỗi yêu cầu 200MB bộ nhớ thì sao?

a = "really, really long string [...]" 
b = a 

Đột nhiên tập lệnh của bạn chiếm 400 MB bộ nhớ? Điều này không tốt lắm.

Còn nếu chúng tôi trỏ nó vào cùng một địa chỉ bộ nhớ, cho đến khi chúng tôi sửa đổi nó? Copy on write. Vấn đề là, điều này có thể khá phức tạp để làm ..

Đây là nơi bất biến xuất hiện .. Thay vì yêu cầu phương thức .replace() để sao chép chuỗi từ bộ nhớ vào địa chỉ mới, sau đó sửa đổi và trả về. chỉ làm cho tất cả các chuỗi không thay đổi được, và do đó hàm phải tạo một chuỗi mới để trả về. Điều này giải thích đoạn mã sau:

a = "abc" 
b = a.replace("a", "z") 

Và được chứng minh bởi:

>>> a = 'abc' 
>>> b = a 
>>> id(a) == id(b) 
True 
>>> b = b.replace("a", "z") 
>>> id(a) == id(b) 
False 

(các id() chức năng trả về địa chỉ bộ nhớ của đối tượng)

+2

+1 Câu trả lời hay nhất. Có thật không. – wassimans

+1

Giải thích tốt nhất mà tôi đã nghe! –

+0

vì vậy nếu tôi nói a = "abc", b = "abcd" nó sẽ chia sẻ abc? như b [: 4] là một? – Dineshkumar

4

loại bất di bất dịch là khái niệm đơn giản hơn nhiều so với những người có thể thay đổi . Ví dụ, bạn không cần phải gây rối với các nhà xây dựng bản sao hoặc tính chính xác như trong C++. Càng nhiều loại không thay đổi, ngôn ngữ càng dễ dàng. Vì vậy, các ngôn ngữ đơn giản nhất là các hàm thuần túy mà không có bất kỳ trạng thái toàn cục nào (vì lambda calculus dễ dàng hơn nhiều so với các máy Turing, và cũng không kém phần mạnh mẽ), mặc dù nhiều người dường như không đánh giá cao điều này.

3

Perl có chuỗi có thể thay đổi và dường như hoạt động tốt. Ở trên có vẻ như rất nhiều bàn tay vẫy tay và hợp lý hóa cho một quyết định thiết kế tùy ý.

Câu trả lời của tôi cho câu hỏi tại sao Python có chuỗi bất biến, bởi vì người sáng tạo Python Guido van Rossum muốn nó theo cách đó và bây giờ anh ta có nhiều người hâm mộ sẽ bảo vệ quyết định tùy ý đó. Bạn có thể đặt ra một câu hỏi tương tự về lý do tại sao Perl không có chuỗi bất biến và toàn bộ số người sẽ viết ra ý tưởng rất tồi tệ của chuỗi không thay đổi và tại sao Đó là ý tưởng hay nhất mà Perl làm không có chúng.

+1

Perl không thực sự có chuỗi: nó có vô hướng, có thể hoạt động như chuỗi hoặc số (nhiều hơn một loại sau này). Nếu vô hướng là bất biến, nó sẽ trở thành hoàn toàn chức năng các nhà phát triển Perl và Perl trên toàn thế giới sẽ tự tử bằng cách gán undef cho chính họ. –

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