Fluent Python 예제 코드 공부 - data-model.ipynbPython/Fluent Python 공부2024. 1. 18. 09:17
Table of Contents
반응형
Fluent Python 2판 깃허브 저장소에 있는 코드를 분석해보고 있습니다.
https://github.com/fluentpython/example-code-2e
2024. 1. 18 최초작성
이름붙은 튜플(collections)을 다루어봅니다.
# https://github.com/fluentpython/example-code-2e/blob/master/01-data-model/data-model.ipynb # Chapter 1 -- The Python Data Model # A deck as a sequence of playing cards import collections # collections 모듈을 사용하면 collections 컬렉션을 사용할 수 있습니다. # collections는 튜플처럼 순서를 가진 컬렉션이지만 필드에 이름을 부여할 수 있습니다. Card = collections.namedtuple('Card', ['rank', 'suit']) # 'Card' 이름의 튜플을 생성합니다. 이 튜플은 2개의 값을 저장하는데 각각 'rank'와 'suit'라는 이름을 가집니다. # 이름있는 튜플 Card를 선언하고 포함된 갯수와 지정한 인덱스의 값을 가져오는 클래스를 정의합니다. class FrenchDeck: # FrenchDeck 클래스의 클래스 변수 ranks와 suits를 선언합니다. ranks = [str(n) for n in range(2, 11)] + list('JQKA') # print(ranks) # ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A'] # 앞 부분은 숫자 2 ~ 10까지를 문자로 바꾼 리스트를 생성하고 뒷부분은 J,Q,K,A 문자를 포함하는 리스트를 생성하여 둘을 더합니다. suits = 'spades diamonds clubs hearts'.split() # print(suits) # ['spades', 'diamonds', 'clubs', 'hearts'] # 공백을 기준으로 문자열을 분리하여 리스트에 저장합니다. def __init__(self): self._cards = [Card(rank, suit) for suit in self.suits for rank in self.ranks] # 클래스 변수 suits와 ranks에 저장된 리스트로부터 값을 꺼내와 튜플 Card에 저장하여 클래스 변수 _cards에 대입합니다. def __len__(self): return len(self._cards) # 클래스 변수 _cards의 원소 개수를 리턴합니다. def __getitem__(self, position): return self._cards[position] # 클래스 변수 _cards의 인덱스 position에 있는 값을 출력합니다. # beer_card = Card('7', 'diamonds') # print(beer_card) # # Card(rank='7', suit='diamonds') # # 시험삼아 Card 튜플에 값을 저장하고 출력해봅니다. # 클래스 FrenchDeck의 인스턴스를 생성하면 __init__ 함수에 의해서 이름 있는 튜플 Card에 값이 채워집니다. deck = FrenchDeck() # # 인스턴스 deck에 저장되어있는 원소의 개수가 출력됩니다. # print(len(deck)) # # 52 # # 인스턴스 deck에 저장되어있는 첫번째 원소와 마지막 원소를 출력합니다. # print(deck[0]) # # Card(rank='2', suit='spades') # print(deck[-1]) # # Card(rank='A', suit='hearts') from random import choice # print(choice(deck)) # # Card(rank='9', suit='spades') # # 무작위로 하나의 값을 선택합니다. 코드를 실행할때 마다 값이 달라지게 됩니다. # print(deck[:3]) # # [Card(rank='2', suit='spades'), Card(rank='3', suit='spades'), Card(rank='4', suit='spades')] # # 처음 3개의 원소를 출력합니다. # print(deck[12::13]) # # [Card(rank='A', suit='spades'), Card(rank='A', suit='diamonds'), Card(rank='A', suit='clubs'), Card(rank='A', suit='hearts')] # # 인덱스 12부터 시작하여 13 간격으로 원소를 리스트에 저장합니다. # for card in deck: # print(card) # # 인스턴스 deck에 있는 원소를 순서대로 출력합니다. # for card in reversed(deck): # print(card) # # 인스턴스 deck에 있는 원소를 역순서대로 출력합니다. # 인스턴스 deck에 해당 튜플이 있는지 체크합니다. # print(Card('Q', 'hearts') in deck) # # True # print(Card('7', 'beasts') in deck) # # False suit_values = dict(spades=3, hearts=2, diamonds=1, clubs=0) # # 각 카드 무늬에 가중치를 부여하기 위해 딕셔너리를 생성합니다. # print(suit_values) # # {'spades': 3, 'hearts': 2, 'diamonds': 1, 'clubs': 0} def spades_high(card): rank_value = FrenchDeck.ranks.index(card.rank) # 카드의 순위(rank)에 해당하는 인덱스를 가져옵니다. 이 인덱스는 '2'에서부터 시작하여 'A'에서 끝나는 순서입니다. return rank_value * len(suit_values) + suit_values[card.suit] # 이 순위 인덱스 rank_value에 len(suit_values)(무늬의 개수, 여기서는 4)를 곱하고, 해당 카드 무늬의 가중치(suit_values[card.suit])를 더합니다. 이로써 각 카드에 고유한 점수를 부여합니다. for card in sorted(deck, key=spades_high): # sorted 함수는 deck에 있는 카드들을 spades_high 함수에 정의된 규칙에 따라 정렬합니다. # key=spades_high는 정렬 기준으로 spades_high 함수의 반환 값을 사용한다는 의미입니다. print(card) # 이 코드의 목적은 카드 덱을 특정한 순서(스페이드, 하트, 다이아몬드, 클럽 순으로 그리고 각 무늬 내에서는 '2'부터 'A'까지의 순서)에 따라 정렬하고, 이를 출력하는 것입니다. |
Vecor 클래스를 정의하여 Vector 데이터 타입을 생성하고 몇가지 연산을 재정의해봅니다.
# https://github.com/fluentpython/example-code-2e/blob/master/01-data-model/data-model.ipynb # Example 1-2. A simple two-dimensional vector class import math # Vector 클래스를 정의합니다. class Vector: # 주어진 두개의 값을 클래스 변수 x,y에 저장합니다. def __init__(self, x=0, y=0): self.x = x self.y = y # Vector 클래스의 인스턴스를 출력시 어떻게 출력할지를 정합니다. def __repr__(self): return 'Vector(%r, %r)' % (self.x, self.y) # abs 함수에서 Vector 클래스의 인스턴스를 어떻게 계산한지를 정합니다. - 벡터의 크기를 계산합니다. def __abs__(self): return math.hypot(self.x, self.y) # bool 함수에서 Vector 클래스의 인스턴스를 어떻게 계산한지를 정합니다. - 원점이면 False, 그외에는 True를 반환합니다. def __bool__(self): return bool(abs(self)) # + 연산에서 Vector 클래스의 인스턴스를 어떻게 계산한지를 정합니다. - 벡터의 덧셈을 계산합니다. def __add__(self, other): x = self.x + other.x y = self.y + other.y return Vector(x, y) # * 연산에서 Vector 클래스의 인스턴스를 어떻게 계산한지를 정합니다. - 벡터와 스칼라곱을 계산합니다. def __mul__(self, scalar): return Vector(self.x * scalar, self.y * scalar) v0 = Vector(0, 0) v1 = Vector(2, 4) v2 = Vector(2, 1) print(v1) # Vector(2, 4) print(v2) # Vector(2, 1) print(abs(v1)) # 4.47213595499958 print(bool(v0)) # False print(bool(v1)) # True print(v1 + v2) # Vector(4, 5) print(v1 * 3) # Vector(6, 12) |
반응형