Vấn đề
Bạn cần triển khai các cấu trúc dữ liệu bất biến trong Python.
Giới thiệu ..
Cấu trúc dữ liệu bất biến rất tiện dụng khi bạn muốn ngăn nhiều người sửa đổi một phần dữ liệu trong lập trình song song cùng một lúc. Cấu trúc dữ liệu có thể thay đổi (ví dụ:Mảng) có thể được thay đổi bất kỳ lúc nào trong khi không thể thay đổi cấu trúc dữ liệu bất biến.
Cách thực hiện ..
Hãy để tôi chỉ cho bạn từng bước cách đối phó với cấu trúc dữ liệu không thể thay đổi và có thể thay đổi.
Ví dụ
# STEP 01 - Create a Mutable array. # Define an array atp_players = ['Murray', 'Nadal', 'Djokovic'] print(f" *** Original Data in my array is - {atp_players}")
*** Dữ liệu gốc trong mảng của tôi là -
['Murray', 'Nadal', 'Djokovic']
# Changing the player name from Murray to Federer atp_players[0] = 'Federer' print(f" *** Modified Data in my array is - {atp_players}")
*** Dữ liệu được Sửa đổi trong mảng của tôi là -
['Federer', 'Nadal', 'Djokovic']
Kết luận
Chúng tôi có thể thay đổi giá trị mảng giống như vậy, điều này có thể hữu ích nếu bạn là người dùng độc quyền của mảng này. Tuy nhiên, trong sản xuất thời gian thực, nhiều chương trình có thể đang sử dụng mảng này để thay đổi và có thể dẫn đến dữ liệu không mong muốn.
Mặt khác, Tuples hoạt động hơi khác một chút, hãy xem ví dụ dưới đây.
# STEP 02 - Try changing a Tuple try: atp_players_tuple = ('Murray', 'Nadal', 'Djokovic') print(f" *** Original Data in my tuple is - {atp_players_tuple}") atp_players_tuple[0] = 'Federer' except Exception as error: print(f" *** Tried modifying data but ended up with - {error}")
*** Original Data in my tuple is - ('Murray', 'Nadal', 'Djokovic') *** Tried modifying data but ended up with - 'tuple' object does not support item assignment
Kết luận:
Những gì bạn đã thấy ở trên là, tuple không thể được sửa đổi phải không ?. Tuy nhiên có một ngoại lệ, nếu có các mảng trong một bộ giá trị, các giá trị có thể được thay đổi.
atp_players_array_in_tuple = (['Murray'], ['Nadal'], ['Djokovic']) print(f" *** Original Data in my tuple with arrays is - {atp_players_array_in_tuple}") atp_players_array_in_tuple[0][0] = 'Federer' print(f" *** Modified Data in my tuple with arrays is - {atp_players_array_in_tuple}")
*** Original Data in my tuple with arrays is - (['Murray'], ['Nadal'], ['Djokovic']) *** Modified Data in my tuple with arrays is - (['Federer'], ['Nadal'], ['Djokovic'])
Vậy làm thế nào để bảo vệ dữ liệu? Rất tiếc, chỉ bằng cách chuyển đổi các mảng thành các bộ giá trị.
try: atp_players_tuple_in_tuple = (('Murray'), ('Nadal'), ('Djokovic')) print(f" *** Original Data in my tuple is - {atp_players_tuple_in_tuple}") atp_players_tuple_in_tuple[0] = 'Federer' except Exception as error: print(f" *** Tried modifying data in my tuple but ended up with - {error}")
*** Original Data in my tuple is - ('Murray', 'Nadal', 'Djokovic') *** Tried modifying data in my tuple but ended up with - 'tuple' object does not support item assignment
Còn nữa .. Python có một công cụ tích hợp tuyệt vời có tên là NamedTuple. Đó là một lớp bạn có thể mở rộng để tạo một phương thức khởi tạo. Hãy để chúng tôi hiểu theo chương trình.
# Create a simple class on Grandslam titles in pythons way. class GrandSlamsPythonWay: def __init__(self, player, titles): self.player = player self.titles = titles stats = GrandSlamsPythonWay("Federer", 20) print(f" *** Stats has details as {stats.player} - {stats.titles}")
*** Stats has details as Federer - 20
Bạn nghĩ gì về lớp học này, nó có phải là bất biến không? Hãy để chúng tôi kiểm tra bằng cách đổi Federer thành Nadal.
stats.player = 'Nadal' print(f" *** Stats has details as {stats.player} - {stats.titles}")
*** Stats has details as Nadal - 20
Vì vậy, không có gì ngạc nhiên khi đây là một cấu trúc dữ liệu bất biến vì chúng ta có thể cập nhật Federer với Nadal. Bây giờ chúng ta hãy tạo một lớp với NamedTuple và xem nó là hành vi mặc định nào.
from typing import NamedTuple class GrandSlamsWithNamedTuple(NamedTuple): player: str titles: int stats = GrandSlamsWithNamedTuple("Federer", 20) print(f" *** Stats has details as {stats.player} - {stats.titles}") stats.player = 'Djokovic' print(f" *** Stats has details as {stats.player} - {stats.titles}")
*** Stats has details as Federer - 20
--------------------------------------------------------------------------- AttributeError Traceback (most recent call last) in 10 print(f" *** Stats has details as {stats.player} - {stats.titles}") 11 ---> 12 stats.player = 'Djokovic' 13 print(f" *** Stats has details as {stats.player} - {stats.titles}") AttributeError: can't set attribute
Có vẻ như Djokovic phải đợi thêm một thời gian nữa để đạt được 20 danh hiệu Grandslam.
Tuy nhiên, chúng ta có thể sử dụng phương thức _replace để tạo bản sao và cập nhật các giá trị trong _replace.
djokovic_stats = stats._replace(player="Djokovic", titles=17) print(f" *** djokovic_stats has details as {djokovic_stats.player} - {djokovic_stats.titles}")
*** djokovic_stats has details as Djokovic - 17
Ví dụ
Cuối cùng, tôi sẽ đưa ra một ví dụ bao gồm mọi thứ được giải thích ở trên.
Đối với ví dụ này, giả sử chúng tôi đang viết phần mềm cho cửa hàng rau.
from typing import Tuple # Create a Class to represent one purchase class Prices(NamedTuple): id: int name: str price: int # Price in dollars # Create a Class to track the purchase class Purchase(NamedTuple): purchase_id: int items: Tuple[Prices] # Create vegetable items and their corresponding prices carrot = Prices(1, "carrot", 2) tomato = Prices(2, "tomato", 3) eggplant = Prices(3, "eggplant", 5) # Now let say our first cusotmer Mr.Tom had purchased carrot and tomato tom_order = Purchase(1, (carrot, tomato)) # Know the total cost we need to charge Mr.Tom total_cost = sum(item.price for item in tom_order.items) print(f"*** Total Cost from Mr.Tom is - {total_cost}$")
Đầu ra
*** Total Cost from Mr.Tom is - 5$