Successfully reported this slideshow.
Your SlideShare is downloading. ×

Python元組,字典,集合

Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Upcoming SlideShare
Python串列資料應用
Python串列資料應用
Loading in …3
×

Check these out next

1 of 36 Ad

Python元組,字典,集合

Download to read offline

Python的資料結構, 元組資料與應用, 字典資料與應用, 集合資料與應用, 使用sorted()函式, 使用enumerate()函式, 應用實例 – 井字棋遊戲

Python的資料結構, 元組資料與應用, 字典資料與應用, 集合資料與應用, 使用sorted()函式, 使用enumerate()函式, 應用實例 – 井字棋遊戲

Advertisement
Advertisement

More Related Content

Advertisement

More from 吳錫修 (ShyiShiou Wu) (20)

Recently uploaded (20)

Advertisement

Python元組,字典,集合

  1. 1. Python元組,字典,集合 Revised on August 26, 2021  Python的資料結構  元組資料與應用  字典資料與應用  集合資料與應用  使用sorted()函式  使用enumerate()函式  應用實例 – 井字棋遊戲
  2. 2.  Python 支援四種資料結構:list、tuple、set及dictionary,而且彼此 問可以相互轉換  串列類似其它程式語言的陣列 (Array),但Python 串列中的元素允許 是不同資料型別 list1 = ['apple', 23, 'orange', 15, 'melon', 19]  元組 (tuple) 類似串列,但建立資料後,內容就不可變更 tuple1 = ('apple', 23, 'orange', 15, 'melon', 19)  集合 (set) 為不重複的非排序元素集,可進行數學上的集合運算 set1 = {'apple', 23, 'orange', 15, 'melon', 19}  字典 (dictionary) 用於儲存由 key 索引的鍵⋅值配對 (Key-Value Pair) 資料,鍵必須是唯⼀ dict1 = {'apple':23, 'orange':15, 'melon':19} Python的資料結構 2
  3. 3.  元組 (tuple) 類似串列,元組的元素可以由不同型別的資料型別來組成, 但元組建立後元素個數及內容都不可變更  讀取元組內的元素時,使用的註標即建立時的順序,運算速度最快  元組的宣告  元組變數 = 元素A, 元素B, 元素C, ...  元組變數 = (元素A, 元素B, 元素C, ...) tuple1 = () #宣告空元組 dummy1 = 65 #整數資料 tuple2 = 65, #宣告只有⼀個元素的元組,元素之後必須加上逗號 dummy2 = (65) #整數資料 tuple3 = (65,) #宣告只有⼀個元素的元組,元素之後必須加上逗號 tuple4 = (65, 'A') #元素可以是不同資料型別 print(tuple4[1]) #A 元組資料 1/2
  4. 4.  list 函式可將元組資料轉換為串列 mytuple = (1, 2, 3, 4, 5) list1 = list(mytuple)  tuple 函式可將串列資料轉換為元組 mylist = [1, 2, 3, 4, 5] tuple1 = tuple(mylist) 元組資料 2/2 4
  5. 5. tuple1 = ('apple', 23, 'orange', 15, 'melon', 19) tuple2 = (7, 20, 15, 40, 19.5)  value in 元組 檢查元組中是否存在value元素值 print(50 in tuple1) #False  元組[i] 回傳註標為i的元素值 print(tuple2[0]) #apple  len(元組) 取得元組元素數目 print(len(tuple1)) #6  min(元組) 取得元組中最小的元素值,只適用於元素皆為數值資料之元組 print(min(tuple2)) #7 元組的基本操作 1/2
  6. 6.  max(元組) 取得元組中最大的元素值,只適用於元素皆為數值資料之元組 print(max(tuple2)) #40  sum(元組) 計算元組元素的總和,只適用於元素皆為數值資料之元組 print(sum(tuple2)) #101.5 tuple1 = ('apple', 23, 'orange', 15, 'melon', 19) tuple1[1] = 25 #錯誤 元組的基本操作 2/2 TypeError: 'tuple' object does not support item assignment
  7. 7.  字典資料 (dict) 的元素由「鍵(Key):值(Value)」組成,元素間用逗號 分隔,所有元素被 {} 大括號包圍  字典 = {鍵1:值1, 鍵2:值2, ...}  鍵必須是唯⼀,如果鍵值重覆,前⾯鍵值的元素會被後⾯鍵值的元素覆 蓋。鍵可以使用數值、字串或元組  值可以是任何資料型別 dict1 = {'香蕉':20, '蘋果':50, '橘子':30} dict2 = dict(⻄瓜 = 30, 葡萄 = 45, 百香果 = 60) print(dict1) print(dict2) 測試結果: {'香蕉': 20, '蘋果': 50, '橘子': 30} {'⻄瓜': 30, '葡萄': 45, '百香果': 60} 字典資料 7
  8. 8. dict1 = {'香蕉':20, '蘋果':50, '橘子':30}  字典[key] = value 在字典新增key:value元素,若已存在鍵,表示更新值 dict1['鳯梨'] = 40  del 字典[key] 刪除字典中鍵為 key 的元素 del dict1['鳯梨']  字典.clear() 可刪除字典的所有元素 dict1.clear()  del 字典 刪除整個字典資料 del dict1 字典資料維護 1/2 8
  9. 9. dict1 = {'香蕉':20, '蘋果':50, '橘子':30} dict1['鳯梨'] = 40 print(dict1) #{'香蕉':20, '蘋果':50, '橘子':30, '鳯梨':40} del dict1['蘋果'] print(dict1) #{'香蕉':20, '橘子':30, '鳯梨':40} dict1.clear() print(dict1) #{} del dict1 print(dict1) #錯誤 字典資料維護 2/2 NameError: name 'dict1' is not defined
  10. 10. dict1 = {'香蕉':20, '蘋果':50, '橘子':30}  len(字典) 計算字典的元素個數 print(len(dict1)) #3  字典.fromkeys(元組或串列[, 預設值]) 以元組或串列元素為鍵,建立字典,如有重複元素會自動去除 fruits = ('apple', 'orange', 'melon') fruitdic = {}.fromkeys(fruits, 30) print(fruitdic) #{'apple': 30, 'orange': 30, 'melon': 30}  字典.keys() 傳回字典中所有的鍵,傳回資料可用 list 函式轉換為串列 print(list(dict1.keys())) #['香蕉', '蘋果', '橘子']  字典.values() 傳回字典中所有的值,傳回資料可用 list 函式轉換為串列 print(list(sites. values())) #[20, 50, 30] 字典資料處理 1/5 10
  11. 11. dict1 = {'香蕉':20, '蘋果':50, '橘子':30}  字典.items() 傳回字典中所有的元素,每⼀對鍵值會形成⼀個元組。傳回資料可用 list 函式 轉換為串列 print(list(dict1.items())) #[('香蕉', 20), ('蘋果', 50), ('橘子', 30)]  字典.get(key, value) 取得 key 對應的值,若 key 不存在,則傳回參數中的 value 值 print(dict1.get('鳯梨', 40)) #40  字典.setdefault(key, value) 取得key 對應的值,若 key 不存在,則以參數的 key, value 建立新元素,並傳 回 value 值 print(dict1.setdefault('鳯梨', 40)) #40 print(dict1) #{'香蕉': 20, '蘋果': 50, '橘子': 30, '鳯梨': 40} 字典資料處理 2/5 11
  12. 12. dict1 = {'香蕉':20, '蘋果':50, '橘子':30}  字典.pop(key[, value]) 傳回 key 對應的值,並刪除該元素;如果找不到 key,則回傳 value;如果找 不到 key,又沒指定 value,則會造成 KeyError 異常 print(dict1.pop('蘋果')) #50 print(dict1) #{'香蕉': 20, '橘子': 30}  字典.popitem() 傳回最後⼀筆元素 (元組資料型式),並刪除該元素;如果字典已經為空,卻調 用了此方法,就報出KeyError異常 print(dict1.pop('蘋果')) #('橘子', 30) print(dict1) #{'香蕉': 20}  字典.update(字典2) 以字典2的元素,更新字典 dict1.update({'香蕉':25, '蘋果':50}) print(dict1) #{'香蕉': 25, '蘋果': 50} 字典資料處理 3/5 12
  13. 13. dict1 = {'香蕉':20, '蘋果':50, '橘子':30}  key in 字典 檢查字典中是否存在key鍵 print('香蕉' in dict1) #True for key in dict1: print(key, end = ', ') #香蕉, 蘋果, 橘子, 字典資料處理 4/5 13
  14. 14. sites = {'Google': 'www.google.com', 'Runoob': 'www.runoob.com'} print(sites.get('Google')) print(sites.popitem()) print(sites.setdefault('Python', 'www.python.org')) print(list(sites.keys())) print(list(sites.values())) sites.update({'Python':'python.org'}) print(sites.items()) for k in sites: print(k) 測試結果: www.google.com ('Runoob', 'www.runoob.com') www.python.org ['Google', 'Python'] ['www.google.com', 'www.python.org'] dict_items([('Google', 'www.google.com'), ('Python', 'python.org')]) Google Python 字典資料處理 5/5
  15. 15.  在 Python 不支援其它語言中的 switch 指令,以下程式結合字典物件 與 lambda 函式模擬 switch 指令功能 score = int(input('請輸入分數:')) level = score // 10 { 10 : lambda: print('Perfect'), 9 : lambda: print('A'), 8 : lambda: print('B'), 7 : lambda: print('C'), 6 : lambda: print('D') }.get(level, lambda: print('E'))() 測試結果: 請輸入分數:67 D 字典資料應用
  16. 16.  集合 (Set) 儲存的是無序、元素不重複的資料集  集合名稱 = {元素1, 元素2, ...} programmers = {'Jack', 'Sam', 'Susan', 'Janice'}  會重新排列元素順序  元素可以是不同資料型別  set 函式可將串列資料轉換為集合,並自動剔除重複元素 engineers = set(['John', 'Jane', 'Jack', 'Jack', 'Janice'])  set 函式可將字典資料中的鍵轉換為集合 s = set({1:'A', 2:'B', 3:'C', 4:'D'}) #{1,2,3,4}  建立空集合必须用 set() 而不是使用 {} (空字典) 集合資料 16
  17. 17.  集合.add(x) 將元素 x 添加到集合中,如果元素已存在,則不進行任何操作  集合.update(x) 將 x 添加到集合中,x 可以是元素、串列、元組或字典  集合.remove(x) 將元素 x 從集合中移除,如果元素不存在,則會發生 KeyError 錯誤  集合.discard(x) 將元素 x 從集合中移除,如果元素不存在,則不進行任何操作  集合.pop() 取從集合中取出第⼀個元素,並移除該元素;如果是空集合,則會發生 KeyError 錯誤  集合.clear() 清空集合 集合的基本操作 1/3 17
  18. 18.  len(集合) 回傳集合的元素個數  max(集合) 回傳集合中的最大元素  min(集合) 回傳集合中的最小元素  x in 集合 檢查集合中是否存在元素 x 集合的基本操作 2/3 18
  19. 19. programmer = {'Jack', 'Sam', 'Susan', 'Janice'} programmer.add('Tony') print(programmer) programmer.discard('Susan') print('Susan' in programmer) print(programmer) programmer.pop() print(programmer) for e in programmer: print(e) 測試結果: {'Sam', 'Susan', 'Tony', 'Jack', 'Janice'} False {'Sam', 'Tony', 'Jack', 'Janice'} {'Tony', 'Jack', 'Janice'} Tony Jack Janice 集合的基本操作 3/3
  20. 20.  交集運算  集合1 & 集合2  集合1.intersection(集合2)  聯集運算  集合1 | 集合2  集合1.union(集合2)  差集運算  集合1 – 集合2  集合1.difference(集合2) 集合運算 1/3 20
  21. 21.  對稱差集 (排除相同元素)  集合1 ^ 集合2  集合1.symmetric_difference(集合2)  子集合  集合1 < 集合2 #測試s1是否為s2的子集合  集合1.issubset(集合2)  父集合  集合1 > 集合2 #測試s1是否為s2的父集合  集合1.issuperset(集合2)  判断两集合是否包含相同的元素,如果没有回傳True,否则回傳False  集合1.isdisjoint(集合2) 集合運算 2/3 21
  22. 22. engineer = set(['Tony', 'John', 'Jane', 'Jack', 'Janice']) print(engineer) programmer = {'Tina', 'Jack', 'Sam', 'Susan', 'Janice', 'Tom'} manager = set(['Tony', 'Tina', 'Mike']) employee = engineer | programmer | manager #union print(employee) print('engineer and manager:', engineer & manager) #intersection print('fulltime manager:', manager - engineer - programmer) #difference engineer.remove('Jane') print(engineer) print(len(engineer)) 測試結果: {'John', 'Jane', 'Tony', 'Jack', 'Janice'} {'Tom', 'Sam', 'John', 'Jane', 'Tony', 'Susan', 'Mike', 'Jack', 'Tina', 'Janice'} engineer and manager: {'Tony'} fulltime manager: {'Mike'} {'John', 'Tony', 'Jack', 'Janice'} 4 集合運算 3/3
  23. 23.  只有字典提供鍵值索引,而串列、元組及集合這三者極為相似;串列 因為限制少,方便使用但效率會低於其他型別  依資料的性質  如果資料有兩個以上,且包含唯⼀的關鍵字,那麼字典是絕佳的選擇  如果資料有前後順序的時間因素,或者有可能會重複時,就不能使用集合  資料如果有增減的需求,元組就無法達成要求  考量資料內建的函式和方法,是否能對資料進行處理  集合型別可以有效率的進行聯集、交集等運算 元組、字典和集合使用時機
  24. 24.  sorted() 函式可用來排序任何的 iterable 資料 (string, dictionary, tuple...),並串列型別回傳排序後之資料  sorted(iterable, key = None, reverse = False)  iterable 可迭代運算物件  key key 參數的值應該是⼀個函數,它接受⼀個參數並返回⼀個用於排序目的 的鍵。只有當可迭代運算物件的元素為複合資料時,才需  reverse 排序規則,reverse = True 降冪,reverse = False 昇冪 (預設) sorted ()函式 1/4
  25. 25. programmers = {'Jack', 'Sam', 'Allen', 'David'} print(sorted(programmers)) print(sorted(programmers, reverse = True)) fruits = {'apple':23, 'orange':15, 'melon':19} print(sorted(fruits)) #字典資料預設以key排序 print(sorted(fruits, key = lambda x:fruits[x])) #使用value排序字典資料 測試結果: ['Allen', 'David', 'Jack', 'Sam'] ['Sam', 'Jack', 'David', 'Allen'] ['apple', 'melon', 'orange'] ['orange', 'melon', 'apple'] sorted ()函式 2/4
  26. 26.  由於經常會用到 key 函式,Python 提供 operator 模組,其中 itemgetter() 函式可以直接做為 key 函式 fruits = {'apple':23, 'orange':15, 'melon':19} print(sorted(fruits, key = itemgetter(0))) #使用key排序字典資料 print(sorted(fruits, key = itemgetter(1))) #使用value排序字典資料 students = [('Bill', 'B', 15), ('Danny', 'A', 14), ('Geoff', 'B', 14)] print(sorted(students)) print(sorted(students, key = lambda x:x[1])) #以成績排序資料 print(sorted(students, key = itemgetter(1))) #以成績排序資料 print(sorted(students, key = lambda x:(x[1], x[2]))) #先以成績再以年齡排序資料 print(sorted(students, key = itemgetter(1, 2))) #先以成績再以年齡排序資料 測試結果: ['apple', 'melon', 'orange'] ['melon', 'apple', 'orange'] [('Bill', 'B', 15), ('Danny', 'A', 14), ('Geoff', 'B', 14)] [('Danny', 'A', 14), ('Bill', 'B', 15), ('Geoff', 'B', 14)] [('Danny', 'A', 14), ('Bill', 'B', 15), ('Geoff', 'B', 14)] [('Danny', 'A', 14), ('Geoff', 'B', 14), ('Bill', 'B', 15)] [('Danny', 'A', 14), ('Geoff', 'B', 14), ('Bill', 'B', 15)] sorted ()函式 3/4
  27. 27.  如果要排序的物件是class object的話,也可以使用operator模組中的 attrgetter() 做為 key 函式 class Student: def __init__(self, name, grade, age): self.name = name self.grade = grade self.age = age def __repr__(self): return repr((self.name, self.grade, self.age)) students = [Student('Bill', 'B', 15), Student('Danny', 'A', 14), Student('Geoff', 'B', 14)] print(sorted(students, key = attrgetter('grade'))) #比成績 print(sorted(students, key = attrgetter('grade', 'age'))) #先比成績再比年齡 測試結果: [('Danny', 'A', 14), ('Bill', 'B', 15), ('Geoff', 'B', 14)] [('Danny', 'A', 14), ('Geoff', 'B', 14), ('Bill', 'B', 15)] 註:有關類別宣告後續單元再介紹 sorted ()函式 4/4
  28. 28.  enumerate() 函式用來自可叠代對象 (如串列、元組、集合等) 中依序 列舉出元素值,並加以順序編號  enumerate(sequence, [start = 0])  start 為將列舉所取得資料進行編號之起始值,預設值為 0  enumerate 多用於在 for 循環中得到計數,利用它可以同時獲得索引 和值,即需要 index 和 value 值的時候可以使用 programmer = {'Jack', 'Sam', 'Susan', 'Janice'} for index, name in enumerate(programmer, start = 1): print('%s. %s' %(index, name)) 測試結果: 1. Susan 2. Sam 3. Janice 4. Jack enumerate()函式
  29. 29.  遊戲規則  由玩家 (X) 與電腦 (O) 輪流對奕,隨機決定先手  先連成⼀線者勝出  電腦落子策略 1. 檢查棋盤,如有決勝點即落子 2. 檢查棋盤,如存在對手決勝點,落子阻斷 3. 依據棋盤空格優先序落子 1) 四個角落空格 2) 中間空格 3) 四個邊空格 應用實例:井字棋遊戲 1/8
  30. 30.  建立board串列儲存對奕資料,元素 1 ~元素 9 對應井字棋盤九格,元 素 0 沒使用;'X'表示玩家落子,'O'表示電腦落子,' '表示空格 import random board = [' ' for x in range(10)]  printBoard() 自訂函式用來顯示井字棋 def printBoard(): print(' ' + board[1] + '|' + board[2] + '|' + board[3] + ' ') print('--+-+--') print(' ' + board[4] + '|' + board[5] + '|' + board[6] + ' ') print('--+-+--') print(' ' + board[7] + '|' + board[8] + '|' + board[9] + ' ') 應用實例:井字棋遊戲 2/8 1 2 3 4 5 6 7 8 9
  31. 31.  isWinner(bo, c)自訂函式用來檢查是否連線,有連線時回傳 True  bo 井字棋對奕資料  c 為棋子符號,'X'代表玩家,'O'代表電腦 def isWinner(bo, c): return (bo[1]==bo[2]==bo[3]==c) or (bo[4]==bo[5]==bo[6]==c) or (bo[7]==bo[8]==bo[9]==c) or (bo[1]==bo[4]==bo[7]==c) or (bo[2]==bo[5]==bo[8]==c) or (bo[3]==bo[6]==bo[9]==c) or (bo[1]==bo[5]==bo[9]==c) or (bo[3]==bo[5]==bo[7]==c)  isBoardFull(bo)自訂函式用來檢查井字棋是否填滿了 def isBoardFull(): return board.count(' ') == 1 #只剩⼀個空格時(元素0),表示棋盤已填滿  selectRandom(li)自訂函式用來自li串列中隨機挑選⼀個元素值 def selectRandom(li): r = random.randrange(0, len(li)) return li[r] 應用實例:井字棋遊戲 3/8
  32. 32.  playerTurn()自訂函式為玩家回合處理作業,若玩家輸入的棋盤位 置編號為空格則落子'X',否則重新輸入 def playerTurn(): while True: try: move = int(input('Select a position to place an 'X' (1-9): ')) if move > 0 and move < 10: if (board[move] == ' '): board[move] = 'X' break else: print('Sorry, this space is occupied!') else: print('Please type a number within the range!') except: print('Please type a number!') printBoard() #顯示棋盤目前結果 應用實例:井字棋遊戲 4/8 1 2 3 4 5 6 7 8 9
  33. 33.  evaluateMove()自訂函式為電腦回合計算最佳落子位置  落子優先序:連線決勝點、阻斷對手連線點、四個角落、中間、四個邊 def evaluateMove(): candiate = tuple([x for x, c in enumerate(board) if c == ' ' and x != 0]) for let in ('O', 'X'): #檢查決勝點及阻斷對手決勝點 for i in candiate : boardCopy = board[:] #複製棋盤以便測試 boardCopy[i] = let if isWinner(boardCopy, let): return i cornersOpen = [] for i in candiate : if i in (1, 3, 7, 9): cornersOpen.append(i) if len(cornersOpen) > 0: #選擇四個角落位置 return selectRandom(cornersOpen) 應用實例:井字棋遊戲 5/8
  34. 34. if 5 in candiate: #選擇中間位置 return 5 edgesOpen = [] for i in candiate: if i in (2, 4, 6, 8): edgesOpen.append(i) if len(edgesOpen) > 0: #選擇四邊位置 return selectRandom(edgesOpen)  computerTurn()自訂函式為電腦回合處理作業 def computerTurn(): move = evaluateMove() board[move] = 'O' print('Computer placed an 'O' in position', move) printBoard() #顯示棋盤目前結果 應用實例:井字棋遊戲 6/8
  35. 35.  game()自訂函式為遊戲流程控制作業 def game(turn): while True: if (turn): playerTurn() #玩家回合 turn = 1 - turn #換手 if isWinner(board, 'X'): print('You won this time!') break; else: computerTurn() #電腦回合 turn = 1 - turn #換手 if isWinner(board, 'O'): print('Computer won this time!') break; if isBoardFull(): print('Tie Game!') break; 應用實例:井字棋遊戲 7/8
  36. 36.  程式主流程 while True: print('Welcome to Tic Tac Toe!', end = ', ') turn = random.randint(0, 9) % 2 #隨機決定先手,0電腦, 1玩家 if (turn == 1): print('玩家先下') printBoard() #畫出空棋盤 else: print('電腦先下') game(turn) answer = input('Do you want to play again? (Y/N)') if answer.lower() == 'y' or answer.lower == 'yes': board = [' ' for x in range(10)] print('-----------------------------------') else: break 應用實例:井字棋遊戲 8/8

×