Computer >> Máy Tính >  >> Lập trình >> Lập trình

Làm thế nào để triển khai cấu trúc dữ liệu bất biến trong Python?

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$