目錄 | 上一節 (3.6 設計討論) | 下一節 (4.2 繼承)python
本節介紹 class 語句以及建立新對象的方式。git
面向對象編程是一種將代碼組織成對象集合的編程技術。github
一個對象包括:編程
在本課程中,你已經使用了面向對象編程技術。segmentfault
例如,操做列表。數據結構
>>> nums = [1, 2, 3] >>> nums.append(4) # Method >>> nums.insert(1,10) # Method >>> nums [1, 10, 2, 3, 4] # Data >>>
nums
是列表的實例(instance)。app
方法(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
簡而言之,類是一組函數,對所謂的 實例(instance) 執行各類操做。設計
實例是你在程序中操做的實際對象。
經過像調用函數同樣調用類來建立實例。
>>> 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): # Any value stored on `self` is instance data self.x = x self.y = y self.health = 100
對屬性的總數或者類型沒有限制。
應用於對象實例的函數稱爲實例方法。
class Player: ... # `move` is a method def move(self, dx, dy): self.x += dx self.y += dy
對象自己始終做爲第一個參數傳遞。
>>> a.move(1, 2) # matches `a` to `self` # matches `1` to `dx` # matches `2` to `dy` def move(self, dx, dy):
按照慣例,實例稱爲 self
。可是,使用的實際名字不重要。對象始終做爲第一個參數傳遞。將這個參數稱爲 self
只是 Python 的編程風格。
類未定義名稱的做用域。
class Player: ... def move(self, dx, dy): self.x += dx self.y += dy def left(self, amt): move(-amt, 0) # NO. Calls a global `move` function self.move(-amt, 0) # YES. Calls method `move` from above.
若是想要對實例進行操做,那麼你始終須要顯式地引用它(如: self
)。
從本組練習開始,咱們將對前面章節的現有代碼進行一系列更改。從練習 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']
可是,隨着程序規模的不斷擴大,你可能但願建立更好的代碼組織意識(sense)。所以,能夠定義一個類表示數據。請建立一個名爲 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}') ... look at the output ... >>>
須要強調的一點是,在這裏, 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('Data/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
的實例列表裏面。修改完後,修復(fix)report.py
和 pcost.py
裏面全部的代碼,以便使用 Stock
的實例進行工做,而不是使用字典。
提示:你沒必要對代碼進行大量更改,主要是將字典訪問,如 s['shares']
更改成 s.shares
。
修改完後應該可以像以前同樣運行函數:
>>> import pcost >>> pcost.portfolio_cost('Data/portfolio.csv') 44671.15 >>> import report >>> report.portfolio_report('Data/portfolio.csv', 'Data/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 >>>