문제
Python에서 불변 데이터 구조를 구현해야 합니다.
소개..
불변 데이터 구조는 여러 사람이 동시에 병렬 프로그래밍에서 데이터 조각을 수정하는 것을 방지하려는 경우에 매우 편리합니다. 가변 데이터 구조(예:Array)는 언제든지 변경할 수 있지만 불변 데이터 구조는 변경할 수 없습니다.
그것을 하는 방법..
변경할 수 없는 데이터 구조를 처리하는 방법을 단계별로 보여드리겠습니다.
예시
# STEP 01 - 가변 배열 생성.# 배열 정의atp_players =['Murray', 'Nadal', 'Djokovic']print(f" *** 내 배열의 원본 데이터는 - {atp_players}")사전>*** 내 어레이의 원본 데이터는 -
['머레이', '나달', '조코비치']
# 플레이어 이름을 Murray에서 Federeratp_players[0] ='Federer'print(f" *** 내 배열의 수정된 데이터는 - {atp_players}")로 변경*** 내 어레이의 수정된 데이터는 -
['페더러', '나달', '조코비치']결론
우리는 당신이 이 배열의 독점적인 사용자인 경우에 유용할 수 있는 배열 값을 변경할 수 있었습니다. 그러나 실시간 프로덕션에서는 여러 프로그램이 변경을 위해 이 배열을 사용할 수 있으며 예기치 않은 데이터가 발생할 수 있습니다.
반면 튜플은 약간 다르게 동작합니다. 아래 예를 살펴보세요.
# STEP 02 - Tupletry를 변경해 보세요:atp_players_tuple =('Murray', 'Nadal', 'Djokovic')print(f" *** 내 튜플의 원본 데이터는 - {atp_players_tuple}")atp_players_tuple[0] ='Federer'except Exception as error:print(f" *** 데이터 수정을 시도했지만 결국 - {error}")
*** 내 튜플의 원본 데이터는 - ('Murray', 'Nadal', 'Djokovic')*** 데이터 수정을 시도했지만 결국 - 'tuple' 개체가 항목 할당을 지원하지 않습니다.결론:
위에서 본 것은 튜플을 수정할 수 없다는 것입니다. 그러나 한 가지 예외가 있습니다. 튜플에 배열이 있는 경우 값을 변경할 수 있습니다.
atp_players_array_in_tuple =(['Murray'], ['Nadal'], ['Djokovic'])print(f" *** 배열이 있는 내 튜플의 원본 데이터는 - {atp_players_array_in_tuple}")atp_players_array_in_tuple[0][ 0] ='Federer'print(f" *** 배열이 있는 튜플의 수정된 데이터는 - {atp_players_array_in_tuple}")
*** 배열이 있는 튜플의 원본 데이터는 - (['Murray'], ['Nadal'], ['Djokovic'])*** 배열이 있는 튜플의 수정된 데이터는 - (['Federer '], ['나달'], ['조코비치'])그렇다면 데이터를 보호하는 방법은 무엇입니까? 흠, 배열을 튜플로 변환하기만 하면 됩니다.
try:atp_players_tuple_in_tuple =(('Murray'), ('Nadal'), ('Djokovic'))print(f" *** 내 튜플의 원본 데이터는 - {atp_players_tuple_in_tuple}")atp_players_tuple_in_tuple[0] ='Federer' 예외 오류:print(f" *** 내 튜플의 데이터 수정을 시도했지만 결국 - {error}")
*** 내 튜플의 원본 데이터는 - ('Murray', 'Nadal', 'Djokovic')*** 내 튜플의 데이터 수정을 시도했지만 결국 - '튜플' 개체가 항목 할당을 지원하지 않음사전>더 많은 것이 있습니다. Python에는 NamedTuple이라는 훌륭한 내장 도구가 있습니다. 생성자를 만들기 위해 확장할 수 있는 클래스입니다. 프로그래밍 방식으로 이해합시다.
# 파이썬에서 그랜드슬램 타이틀에 대한 간단한 클래스 생성 way.class GrandSlamsPythonWay:def __init__(self, player, titles):self.player =playerself.titles =titlesstats =GrandSlamsPythonWay("Federer", 20)print(f" *** 통계에는 {stats.player} - {stats.titles}")세부정보가 있습니다.
*** 통계에는 Federer - 20과 같은 세부 정보가 있습니다.이 클래스에 대해 어떻게 생각하세요? 불변인가요? Federer를 Nadal로 변경하여 확인해 보겠습니다.
stats.player ='Nadal'print(f" *** 통계는 {stats.player} - {stats.titles}") 세부 정보를 가집니다.
*** 통계에는 Nadal과 같은 세부 정보가 있습니다 - 20따라서 Federer를 Nadal로 업데이트할 수 있으므로 데이터 구조가 변경되지 않습니다. 이제 NamedTuple을 사용하여 클래스를 만들고 기본 동작이 무엇인지 살펴보겠습니다.
입력에서 import NamedTupleclass GrandSlamsWithNamedTuple(NamedTuple):player:strtitles:intstats =GrandSlamsWithNamedTuple("Federer", 20)print(f" *** 통계에는 {stats.player} - {stats.titles}") 세부 정보가 있습니다. stats.player ='Djokovic'print(f" *** 통계에는 {stats.player} - {stats.titles}") 세부 정보가 있습니다.
*** 통계에는 Federer - 20과 같은 세부 정보가 있습니다.
---------------------------------------------- ---------------------------- AttributeError Traceback(가장 최근 호출 마지막)in10 print(f" *** Stats의 세부 정보는 {stats .player} - {stats.titles}")11---> 12 stats.player ='Djokovic'13 print(f" *** 통계의 세부정보는 {stats.player} - {stats.titles}")AttributeError :속성을 설정할 수 없습니다조코비치가 그랜드슬램 20회를 달성하려면 시간이 좀 더 필요했던 것 같습니다.
그러나 _replace 메서드를 사용하여 _replace 동안 값을 복사하고 업데이트할 수 있습니다.
djokovic_stats =stats._replace(player="Djokovic", titles=17)print(f" *** djokovic_stats의 세부정보는 {djokovic_stats.player} - {djokovic_stats.titles}")
*** djokovic_stats에는 Djokovic - 17과 같은 세부 정보가 있습니다.예시
마지막으로 위에서 설명한 모든 내용을 다루는 한 가지 예를 제시하겠습니다.
이 예에서는 야채 가게를 위한 소프트웨어를 작성한다고 가정해 보겠습니다.
입력에서 import Tuple# 하나의 구매 클래스를 나타내는 클래스 만들기 가격(NamedTuple):id:intname:strprice:int # 가격(달러)# 구매 클래스를 추적하는 클래스 만들기 Purchase(NamedTuple):purchase_id:intitems:Tuple[ 가격]# 야채 항목 및 해당 가격 생성carrot =Price(1, "carrot", 2)tomato =Rates(2, "tomato", 3)eggplant =Price(3, "eggplant", 5)# 이제 우리의 첫 번째 고객 Mr.Tom은 당근과 토마토를 구매했습니다.tom_order =Purchase(1, (당근, 토마토))# 청구해야 하는 총 비용을 알고 있습니다. Mr.Tomtotal_cost =sum(tom_order.items의 item.price)print(f" *** Mr.Tom의 총 비용은 - {total_cost}$")출력
*** Mr.Tom의 총 비용은 - 5$입니다.