您需要在Python中实现不可变的数据结构。
当您要防止多个人同时在并行编程中修改一条数据时,不可变数据结构非常方便。可变数据结构(例如Array)可以随时更改,而可变数据结构则不能更改。
让我逐步向您展示如何处理不可变和可变的数据结构。
# STEP 01 - Create a Mutable array. # Define an array atp_players = ['Murray', 'Nadal', 'Djokovic'] print(f" *** Original Data in my array is - {atp_players}")
***我数组中的原始数据是-
['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}")
***我数组中的修改数据是-
['Federer', 'Nadal', 'Djokovic']
结论
我们已经能够像更改数组值一样,如果您是该数组的独占用户,这可能会很有用。但是,在实时生产中,多个程序可能正在使用此数组进行更改,并可能导致意外的数据。
另一方面,元组的行为有所不同,请看下面的例子。
# 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
结论:
您在上面看到的是,元组不能被修改对吗?但是,有一个例外,如果元组中包含数组,则可以更改值。
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'])
那么如何保护数据呢?嗯,只需将数组转换为元组即可。
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
还有更多.. Python有一个很棒的内置工具,名为NamedTuple。您可以扩展该类以创建构造函数。让我们以编程方式理解。
# 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
您如何看待这个课程,这是一成不变的吗?让我们将Federer更改为Nadal进行检查。
stats.player = 'Nadal' print(f" *** Stats has details as {stats.player} - {stats.titles}")
*** Stats has details as Nadal - 20
因此,这毫无疑问是一个不变的数据结构,因为我们能够将Federer更新为Nadal。现在,让我们使用NamedTuple创建一个类,看看它的默认行为是什么。
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
德约科维奇似乎不得不再等一段时间才能获得20个大满贯冠军。
但是,我们可以使用_replace方法进行复制并在_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
最后,我将举一个涵盖以上所有内容的示例。
对于此示例,假设我们正在为蔬菜店编写软件。
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}$")
输出结果
*** Total Cost from Mr.Tom is - 5$