參考資料luciano ramalho《流暢的python》
from collections import namedtuple
city = namedtuple('city', 'name,country,population,coordinates')
# 建立乙個具名元組需要兩個引數,乙個是類名,另乙個是類的各個欄位的名字。
# name country population coordinates都被稱為「欄位名」
# 後者也可以是由數個字串組成的可迭代物件
# ['name','country','population','coordinates']
# 或者是由空格或逗號分隔開的欄位名組成的字串
# 'name,country,population,coordinates'
# 'name country population coordinates'
tokyo = city('tokyo', 'jp', 36.933, (35.689722, 139.691667))
# 存放在對應欄位裡的資料要以一串引數的形式傳入到建構函式中(注意,元組的建構函式卻只接受單一的可迭代物件)
# 這個「卻」字是相對於上面具名元組的建立而言的,因為在上面,引數各個欄位名的傳入就可以用多種物件
print(tokyo)
# city(name='tokyo', country='jp', population=36.933, coordinates=(35.689722, 139.691667))
print(tokyo.population)
# 36.933
print(tokyo[1])
# jp
# 可以通過「欄位名」或者「位置(index)」來獲取乙個欄位的資訊。
import collections
card = collections.namedtuple('card', 'rank,suit')
class frenchdeck:
ranks = [str(n) for n in range(2, 11)] + list('jqka')
suits = 'spades diamonds clubs hearts'.split()
# [str(n) for n in range(2, 11)] + list('jqka') 即為['2', '3', '4', '5', '6', '7', '8', '9', '10', 'j', 'q', 'k', 'a']
# list('jqka') 即為['j', 'q', 'k', 'a']
# 'spades diamonds clubs hearts'.split()即為['spades', 'diamonds', 'clubs', 'hearts']
def __init__(self):
self._cards = [card(rank, suit) for suit in self.suits
for rank in self.ranks]
# 類frenchdeck的例項已被建立就會擁有屬性_cards,該屬性是乙個list,list中的元素都是有名元組,這些元組都是由生成器
# collections.namedtuple('card', 'rank,suit')生成的。在向這個生成器傳入引數時,運用了遍歷操作。
def __len__(self):
return len(self._cards)
# 定義了乙個例項方法,返回值是這個類的屬性_cards的長度
# 在計算機執行指令len(object)時,會立即對映這個方法,返回該方法的返回值,
# 此時,len指令沒有什麼關於len本身的特定意義,只是簡單地映**這個方法。
def __getitem__(self, position):
return self._cards[position]
# 在定義了方法__getitem__以後,這個物件就變得iterable,可以當做可迭代物件來使用
# 具體把它當做什麼可迭代物件,就要由__getitem__的返回值來定了
# 一般而言,這個可迭代物件儲存在例項的乙個屬性裡
deck = frenchdeck()
# 我們建立了乙個物件deck
# 它具有屬性_cards,它可具有方法__len__和__getitem__
# print(len(deck))
# print(deck[0]) # 第一張紙牌,應該是黑桃2
# print(deck[-1]) # 最後一張紙牌,應該是紅桃a
# 上兩行的**得以實現是因為方法__getitem__
# from random import choice
## print(choice(deck)) # 從乙個iterable中隨機選取乙個
# print(choice(deck))
# print(choice(deck))
# print(choice(deck))
# for card in deck:
# print(card)# 這裡用到了方法__getitem__
# # 還可以反向迭代
# for card in reversed(deck):
# print(card)
suit_values = dict(spades=3, hearts=2, diamonds=1, clubs=0) # suit的值
def spade_high(card):
rank_value = frenchdeck.ranks.index(card.rank) # rank的值
# 在例項deck裡面,每乙個元素都是乙個有名tuple,我們獲取這個tuple的屬性rank,即得到了撲克牌的點數,
# 然後用index函式得到了點數在列表frenchdeck.ranks中對應的索引,並將它作為撲克牌排序的依據之一賦值給rank_value
return rank_value * len(suit_values) + suit_values[card.suit]
# 這個排序依據的含義:
# suit_values[card.suit]就是花色在字典suit_values中對應的值
# len(suit_values)就是4
# rank_value*4,也就是撲克牌的數字乘以4,那麼要注意jqka的處理
for card in sorted(deck, key=spade_high): # deck是我們要進行排序的iterable,key=spade_high是排序依據
print(card)
# 這裡的排序依據是乙個函式,那麼肯定是這樣的:
# 將iterable的每乙個元素作為引數傳入這個函式,得到int型別的返回值,根據這個返回值來進行排序
# 由此可以推測,在spade_high函式體裡的card其實是可迭代物件deck的元素。
# sorted接受兩個引數
# arg1是需要進行排序的iterable
# arg2是乙個函式,這個函式應該滿足以下條件
# 引數是iterable arg1的element
# 返回值是element通過某種法則得到的int
一摞烙餅的排序(0621)
每乙個演算法都值得好好地分析 問題 假設有n塊大小不一的烙餅,那最少要翻幾次,才能達到最後大小有序的結果呢?這個排序問題非常有意思,首先我們要弄清楚解決問題的關鍵操作 單手每次抓幾塊餅,全部顛倒 每次我們只能選擇最上方的一堆餅,一起翻轉。而不能一張張地直接抽出來,然後進行插入,也不能交換任意兩塊餅子...
1 3 一摞烙餅的排序
一摞亂序擺放的烙餅,每次只能抓取最上面幾塊烙餅並翻轉,多次翻轉後能夠實現烙餅的從小到大 從上往下 的有序擺放。問題分析 這裡我們使用回溯法解決這個問題。直接用回溯法效率是低下的,因此要進行剪枝。這裡的剪枝條件是利用翻轉次數的上界和下界完成的。上界 4,2,1,5,3 5,1,2,4,3 3,4,2,...
1 3 一摞烙餅的排序
假設有n塊大小不一樣的烙餅,那麼最少要翻動幾次,才能達到最終有序的結果。思路 每次找到最大的然後從將最大的以及最大的上面的反轉,這時候最大的在最上面,然後將整個反轉,最大的就在最下面了。然後再對除了最下面的n 1個烙餅進行上述的操作,知道全部的烙餅有序。例如 13524 53124 42135 cl...