소개
이 섹션에서는 클래스 문 (class statement) 과 새로운 객체를 생성하는 아이디어를 소개합니다.
이 섹션에서는 클래스 문 (class statement) 과 새로운 객체를 생성하는 아이디어를 소개합니다.
코드가 객체들의 모음으로 구성되는 프로그래밍 기법입니다.
객체는 다음으로 구성됩니다:
이 과정에서 이미 일부 객체 지향 프로그래밍을 사용해 왔습니다.
예를 들어, 리스트를 조작하는 경우를 살펴보겠습니다.
>>> nums = [1, 2, 3]
>>> nums.append(4) ## Method
>>> nums.insert(1,10) ## Method
>>> nums
[1, 10, 2, 3, 4] ## Data
>>>
nums는 리스트의 인스턴스입니다.
메서드 (append() 및 insert()) 는 인스턴스 (nums) 에 연결됩니다.
class 문새로운 객체를 정의하려면 class 문을 사용합니다.
class Player:
def __init__(self, x, y):
self.x = x
self.y = y
self.health = 100
def move(self, dx, dy):
self.x += dx
self.y += dy
def damage(self, pts):
self.health -= pts
간단히 말해서, 클래스는 소위 인스턴스에 대해 다양한 연산을 수행하는 함수들의 집합입니다.
인스턴스는 프로그램에서 조작하는 실제 객체입니다.
클래스를 함수처럼 호출하여 생성됩니다.
>>> a = Player(2, 3)
>>> b = Player(10, 20)
>>>
a와 b는 Player의 인스턴스입니다.
강조: class 문은 단지 정의일 뿐이며 (그 자체로는 아무것도 하지 않습니다). 함수 정의와 유사합니다.
각 인스턴스는 자체 로컬 데이터를 가지고 있습니다.
>>> a.x
2
>>> b.x
10
이 데이터는 __init__()에 의해 초기화됩니다.
class Player:
def __init__(self, x, y):
## `self` 에 저장된 모든 값은 인스턴스 데이터입니다.
self.x = x
self.y = y
self.health = 100
저장되는 속성의 총 개수나 유형에 대한 제한은 없습니다.
인스턴스 메서드는 객체의 인스턴스에 적용되는 함수입니다.
class Player:
...
## `move` 는 메서드입니다.
def move(self, dx, dy):
self.x += dx
self.y += dy
객체 자체는 항상 첫 번째 인수로 전달됩니다.
>>> a.move(1, 2)
## `a` 를 `self` 에 매칭
## `1` 을 `dx` 에 매칭
## `2` 를 `dy` 에 매칭
def move(self, dx, dy):
관례적으로, 인스턴스는 self라고 불립니다. 하지만 실제로 사용되는 이름은 중요하지 않습니다. 객체는 항상 첫 번째 인수로 전달됩니다. 이 인수를 self라고 부르는 것은 단지 파이썬 프로그래밍 스타일일 뿐입니다.
클래스는 이름의 스코프를 정의하지 않습니다.
class Player:
...
def move(self, dx, dy):
self.x += dx
self.y += dy
def left(self, amt):
move(-amt, 0) ## NO. 전역 `move` 함수를 호출합니다.
self.move(-amt, 0) ## YES. 위의 메서드 `move` 를 호출합니다.
인스턴스에 대해 작업을 수행하려면 항상 명시적으로 참조해야 합니다 (예: self).
이 일련의 연습부터 이전 섹션의 기존 코드에 일련의 변경 사항을 적용하기 시작합니다. 시작하려면 Exercise 3.18 의 작동하는 버전이 있는 것이 중요합니다. 그렇지 않은 경우, Solutions/3_18 디렉토리에서 찾을 수 있는 솔루션 코드를 사용하십시오. 복사해도 괜찮습니다.
2 절과 3 절에서 우리는 튜플과 딕셔너리로 표현된 데이터를 사용했습니다. 예를 들어, 주식 보유는 다음과 같은 튜플로 표현될 수 있습니다.
s = ('GOOG',100,490.10)
또는 다음과 같은 딕셔너리로 표현될 수 있습니다.
s = { 'name' : 'GOOG',
'shares' : 100,
'price' : 490.10
}
이러한 데이터를 조작하기 위한 함수를 작성할 수도 있습니다. 예를 들어:
def cost(s):
return s['shares'] * s['price']
하지만 프로그램이 커지면 더 나은 조직감을 만들고 싶을 수 있습니다. 따라서 데이터를 표현하는 또 다른 방법은 클래스를 정의하는 것입니다. stock.py라는 파일을 만들고 단일 주식 보유를 나타내는 Stock 클래스를 정의합니다. Stock의 인스턴스가 name, shares, price 속성을 갖도록 합니다. 예를 들어:
>>> import stock
>>> a = stock.Stock('GOOG',100,490.10)
>>> a.name
'GOOG'
>>> a.shares
100
>>> a.price
490.1
>>>
몇 개의 Stock 객체를 더 만들고 조작합니다. 예를 들어:
>>> b = stock.Stock('AAPL', 50, 122.34)
>>> c = stock.Stock('IBM', 75, 91.75)
>>> b.shares * b.price
6117.0
>>> c.shares * c.price
6881.25
>>> stocks = [a, b, c]
>>> stocks
[<stock.Stock object at 0x37d0b0>, <stock.Stock object at 0x37d110>, <stock.Stock object at 0x37d050>]
>>> for s in stocks:
print(f'{s.name:>10s} {s.shares:>10d} {s.price:>10.2f}')
... 출력을 확인하세요 ...
>>>
여기서 강조할 한 가지는 Stock 클래스가 객체의 인스턴스를 생성하는 팩토리처럼 작동한다는 것입니다. 기본적으로 함수처럼 호출하면 새로운 객체를 생성합니다. 또한 각 객체는 고유하다는 점을 강조해야 합니다. 즉, 각 객체는 생성된 다른 객체와 별개인 자체 데이터를 가지고 있습니다.
클래스에 의해 정의된 객체는 딕셔너리와 다소 유사합니다. 단지 약간 다른 구문을 사용합니다. 예를 들어, s['name'] 또는 s['price']를 쓰는 대신, 이제 s.name과 s.price를 씁니다.
클래스를 사용하면 객체에 함수를 연결할 수 있습니다. 이것을 메서드라고 하며, 객체 내부에 저장된 데이터를 조작하는 함수입니다. Stock 객체에 cost() 및 sell() 메서드를 추가합니다. 다음과 같이 작동해야 합니다.
>>> import stock
>>> s = stock.Stock('GOOG', 100, 490.10)
>>> s.cost()
49010.0
>>> s.shares
100
>>> s.sell(25)
>>> s.shares
75
>>> s.cost()
36757.5
>>>
딕셔너리 목록에서 Stock 인스턴스 목록을 만들려면 다음 단계를 시도해 보세요. 그런 다음 총 비용을 계산합니다.
>>> import fileparse
>>> with open('portfolio.csv') as lines:
... portdicts = fileparse.parse_csv(lines, select=['name','shares','price'], types=[str,int,float])
...
>>> portfolio = [ stock.Stock(d['name'], d['shares'], d['price']) for d in portdicts]
>>> portfolio
[<stock.Stock object at 0x10c9e2128>, <stock.Stock object at 0x10c9e2048>, <stock.Stock object at 0x10c9e2080>,
<stock.Stock object at 0x10c9e25f8>, <stock.Stock object at 0x10c9e2630>, <stock.Stock object at 0x10ca6f748>,
<stock.Stock object at 0x10ca6f7b8>]
>>> sum([s.cost() for s in portfolio])
44671.15
>>>
report.py 프로그램의 read_portfolio() 함수를 수정하여 연습 문제 4.3 에서 보여준 것처럼 포트폴리오를 Stock 인스턴스 목록으로 읽도록 합니다. 그런 다음 report.py 및 pcost.py의 모든 코드를 수정하여 딕셔너리 대신 Stock 인스턴스로 작동하도록 합니다.
힌트: 코드에 큰 변경을 할 필요는 없습니다. 주로 s['shares']와 같은 딕셔너리 접근을 s.shares로 변경하게 됩니다.
이전과 동일하게 함수를 실행할 수 있어야 합니다.
>>> import pcost
>>> pcost.portfolio_cost('portfolio.csv')
44671.15
>>> import report
>>> report.portfolio_report('portfolio.csv', 'prices.csv')
Name Shares Price Change
---------- ---------- ---------- ----------
AA 100 9.22 -22.98
IBM 50 106.28 15.18
CAT 150 35.46 -47.98
MSFT 200 20.89 -30.34
GE 95 13.48 -26.89
MSFT 50 20.89 -44.21
IBM 100 106.28 35.84
>>>
축하합니다! 클래스 랩을 완료했습니다. LabEx 에서 더 많은 랩을 연습하여 기술을 향상시킬 수 있습니다.