您好,登錄后才能下訂單哦!
使用字符串
第二次世界大戰促使了現代電子計算機的誕生,當初的想法很簡單,就是用計算機來計算導彈的彈道,因此在計算機剛剛誕生的那個年代,計算機處理的信息主要是數值,而世界上的第一臺電子計算機ENIAC每秒鐘能夠完成約5000次浮點運算。隨著時間的推移,雖然對數值運算仍然是計算機日常工作中最為重要的事情之一,但是今天的計算機處理得更多的數據都是以文本信息的方式存在的,而Python表示文本信息的方式我們在很早以前就說過了,那就是字符串類型。所謂字符串,就是由零個或多個字符組成的有限序列,一般記為$${\displaystyle s=a_{1}a_{2}\dots a_{n}(0\leq n \leq \infty)}$$。
我們可以通過下面的代碼來了解字符串的使用。
def main(): str1 = 'hello, world!' # 通過len函數計算字符串的長度 print(len(str1)) # 13 # 獲得字符串首字母大寫的拷貝 print(str1.capitalize()) # Hello, world! # 獲得字符串變大寫后的拷貝 print(str1.upper()) # HELLO, WORLD! # 從字符串中查找子串所在位置 print(str1.find('or')) # 8 print(str1.find('shit')) # -1 # 與find類似但找不到子串時會引發異常 # print(str1.index('or')) # print(str1.index('shit')) # 檢查字符串是否以指定的字符串開頭 print(str1.startswith('He')) # False print(str1.startswith('hel')) # True # 檢查字符串是否以指定的字符串結尾 print(str1.endswith('!')) # True # 將字符串以指定的寬度居中并在兩側填充指定的字符 print(str1.center(50, '*')) # 將字符串以指定的寬度靠右放置左側填充指定的字符 print(str1.rjust(50, ' ')) str2 = 'abc123456' # 從字符串中取出指定位置的字符(下標運算) print(str2[2]) # c # 字符串切片(從指定的開始索引到指定的結束索引) print(str2[2:5]) # c12 print(str2[2:]) # c123456 print(str2[2::2]) # c246 print(str2[::2]) # ac246 print(str2[::-1]) # 654321cba print(str2[-3:-1]) # 45 # 檢查字符串是否由數字構成 print(str2.isdigit()) # False # 檢查字符串是否以字母構成 print(str2.isalpha()) # False # 檢查字符串是否以數字和字母構成 print(str2.isalnum()) # True str3 = ' jackfrued@126.com ' print(str3) # 獲得字符串修剪左右兩側空格的拷貝 print(str3.strip()) if __name__ == '__main__': main()
除了字符串,Python還內置了多種類型的數據結構,如果要在程序中保存和操作數據,絕大多數時候可以利用現有的數據結構來實現,最常用的包括列表、元組、集合和字典。
使用列表
下面的代碼演示了如何定義列表、使用下標訪問列表元素以及添加和刪除元素的操作。
def main(): list1 = [1, 3, 5, 7, 100] print(list1) list2 = ['hello'] * 5 print(list2) # 計算列表長度(元素個數) print(len(list1)) # 下標(索引)運算 print(list1[0]) print(list1[4]) # print(list1[5]) # IndexError: list index out of range print(list1[-1]) print(list1[-3]) list1[2] = 300 print(list1) # 添加元素 list1.append(200) list1.insert(1, 400) list1 += [1000, 2000] print(list1) print(len(list1)) # 刪除元素 list1.remove(3) if 1234 in list1: list1.remove(1234) del list1[0] print(list1) # 清空列表元素 list1.clear() print(list1) if __name__ == '__main__': main()
和字符串一樣,列表也可以做切片操作,通過切片操作我們可以實現對列表的復制或者將列表中的一部分取出來創建出新的列表,代碼如下所示。
def main(): fruits = ['grape', 'apple', 'strawberry', 'waxberry'] fruits += ['pitaya', 'pear', 'mango'] # 循環遍歷列表元素 for fruit in fruits: print(fruit.title(), end=' ') print() # 列表切片 fruits2 = fruits[1:4] print(fruits2) # fruit3 = fruits # 沒有復制列表只創建了新的引用 # 可以通過完整切片操作來復制列表 fruits3 = fruits[:] print(fruits3) fruits4 = fruits[-3:-1] print(fruits4) # 可以通過反向切片操作來獲得倒轉后的列表的拷貝 fruits5 = fruits[::-1] print(fruits5) if __name__ == '__main__': main()
下面的代碼實現了對列表的排序操作。
def main(): list1 = ['orange', 'apple', 'zoo', 'internationalization', 'blueberry'] list2 = sorted(list1) # sorted函數返回列表排序后的拷貝不會修改傳入的列表 # 函數的設計就應該像sorted函數一樣盡可能不產生副作用 list3 = sorted(list1, reverse=True) # 通過key關鍵字參數指定根據字符串長度進行排序而不是默認的字母表順序 list4 = sorted(list1, key=len) print(list1) print(list2) print(list3) print(list4) # 給列表對象發出排序消息直接在列表對象上進行排序 list1.sort(reverse=True) print(list1) if __name__ == '__main__': main()
我們還可以使用列表的生成式語法來創建列表,代碼如下所示。
import sys def main(): f = [x for x in range(1, 10)] print(f) f = [x + y for x in 'ABCDE' for y in '1234567'] print(f) # 用列表的生成表達式語法創建列表容器 # 用這種語法創建列表之后元素已經準備就緒所以需要耗費較多的內存空間 f = [x ** 2 for x in range(1, 1000)] print(sys.getsizeof(f)) # 查看對象占用內存的字節數 print(f) # 請注意下面的代碼創建的不是一個列表而是一個生成器對象 # 通過生成器可以獲取到數據但它不占用額外的空間存儲數據 # 每次需要數據的時候就通過內部的運算得到數據(需要花費額外的時間) f = (x ** 2 for x in range(1, 1000)) print(sys.getsizeof(f)) # 相比生成式生成器不占用存儲數據的空間 print(f) for val in f: print(val) if __name__ == '__main__': main()
除了上面提到的生成器語法,Python中還有另外一種定義生成器的方式,就是通過yield關鍵字將一個普通函數改造成生成器函數。下面的代碼演示了如何實現一個生成斐波拉切數列的生成器。所謂斐波拉切數列可以通過下面遞歸的方法來進行定義:
$${\displaystyle F_{0}=0}$$
$${\displaystyle F_{1}=1}$$
$${\displaystyle F_{n}=F_{n-1}+F_{n-2}}({n}\geq{2})$$
def fib(n): a, b = 0, 1 for _ in range(n): a, b = b, a + b yield a def main(): for val in fib(20): print(val) if __name__ == '__main__': main()
使用元組
Python 的元組與列表類似,不同之處在于元組的元素不能修改,在前面的代碼中我們已經不止一次使用過元組了。顧名思義,我們把多個元素組合到一起就形成了一個元組,所以它和列表一樣可以保存多條數據。下面的代碼演示了如何定義和使用元組。
def main(): # 定義元組 t = ('駱昊', 38, True, '四川成都') print(t) # 獲取元組中的元素 print(t[0]) print(t[3]) # 遍歷元組中的值 for member in t: print(member) # 重新給元組賦值 # t[0] = '王大錘' # TypeError # 變量t重新引用了新的元組原來的元組將被垃圾回收 t = ('王大錘', 20, True, '云南昆明') print(t) # 將元組轉換成列表 person = list(t) print(person) # 列表是可以修改它的元素的 person[0] = '李小龍' person[1] = 25 print(person) # 將列表轉換成元組 fruits_list = ['apple', 'banana', 'orange'] fruits_tuple = tuple(fruits_list) print(fruits_tuple) if __name__ == '__main__': main()
這里有一個非常值得探討的問題,我們已經有了列表這種數據結構,為什么還需要元組這樣的類型呢?
1、元組中的元素是無法修改的,事實上我們在項目中尤其是多線程環境(后面會講到)中可能更喜歡使用的是那些不變對象(一方面因為對象狀態不能修改,所以可以避免由此引起的不必要的程序錯誤,簡單的說就是一個不變的對象要比可變的對象更加容易維護;另一方面因為沒有任何一個線程能夠修改不變對象的內部狀態,一個不變對象自動就是線程安全的,這樣就可以省掉處理同步化的開銷。一個不變對象可以方便的被共享訪問)。所以結論就是:如果不需要對元素進行添加、刪除、修改的時候,可以考慮使用元組,當然如果一個方法要返回多個值,使用元組也是不錯的選擇。
2、元組在創建時間和占用的空間上面都優于列表。我們可以使用sys模塊的getsizeof函數來檢查存儲同樣的元素的元組和列表各自占用了多少內存空間,這個很容易做到。我們也可以在ipython中使用魔法指令%timeit來分析創建同樣內容的元組和列表所花費的時間,下圖是我的macOS系統上測試的結果。
使用集合
Python中的集合跟數學上的集合是一致的,不允許有重復元素,而且可以進行交集、并集、差集等運算。
def main(): set1 = {1, 2, 3, 3, 3, 2} print(set1) print('Length =', len(set1)) set2 = set(range(1, 10)) print(set2) set1.add(4) set1.add(5) set2.update([11, 12]) print(set1) print(set2) set2.discard(5) # remove的元素如果不存在會引發KeyError if 4 in set2: set2.remove(4) print(set2) # 遍歷集合容器 for elem in set2: print(elem ** 2, end=' ') print() # 將元組轉換成集合 set3 = set((1, 2, 3, 3, 2, 1)) print(set3.pop()) print(set3) # 集合的交集、并集、差集、對稱差運算 print(set1 & set2) # print(set1.intersection(set2)) print(set1 | set2) # print(set1.union(set2)) print(set1 - set2) # print(set1.difference(set2)) print(set1 ^ set2) # print(set1.symmetric_difference(set2)) # 判斷子集和超集 print(set2 <= set1) # print(set2.issubset(set1)) print(set3 <= set1) # print(set3.issubset(set1)) print(set1 >= set2) # print(set1.issuperset(set2)) print(set1 >= set3) # print(set1.issuperset(set3)) if __name__ == '__main__': main()
說明: Python中允許通過一些特殊的方法來為某種類型或數據結構自定義運算符(后面的章節中會講到),上面的代碼中我們對集合進行運算的時候可以調用集合對象的方法,也可以直接使用對應的運算符,例如&運算符跟intersection方法的作用就是一樣的,但是使用運算符讓代碼更加直觀。
使用字典
字典是另一種可變容器模型,類似于我們生活中使用的字典,它可以存儲任意類型對象,與列表、集合不同的是,字典的每個元素都是由一個鍵和一個值組成的“鍵值對”,鍵和值通過冒號分開。下面的代碼演示了如何定義和使用字典。
def main(): scores = {'駱昊': 95, '白元芳': 78, '狄仁杰': 82} # 通過鍵可以獲取字典中對應的值 print(scores['駱昊']) print(scores['狄仁杰']) # 對字典進行遍歷(遍歷的其實是鍵再通過鍵取對應的值) for elem in scores: print('%s\t--->\t%d' % (elem, scores[elem])) # 更新字典中的元素 scores['白元芳'] = 65 scores['諸葛王朗'] = 71 scores.update(冷面=67, 方啟鶴=85) print(scores) if '武則天' in scores: print(scores['武則天']) print(scores.get('武則天')) # get方法也是通過鍵獲取對應的值但是可以設置默認值 print(scores.get('武則天', 60)) # 刪除字典中的元素 print(scores.popitem()) print(scores.popitem()) print(scores.pop('駱昊', 100)) # 清空字典 scores.clear() print(scores) if __name__ == '__main__': main()
練習
練習1:在屏幕上顯示跑馬燈文字
import os import time def main(): content = '北京歡迎你為你開天辟地…………' while True: # 清理屏幕上的輸出 os.system('cls') # os.system('clear') print(content) # 休眠200毫秒 time.sleep(0.2) content = content[1:] + content[0] if __name__ == '__main__': main()
練習2:設計一個函數產生指定長度的驗證碼,驗證碼由大小寫字母和數字構成。
import random def generate_code(code_len=4): """ 生成指定長度的驗證碼 :param code_len: 驗證碼的長度(默認4個字符) :return: 由大小寫英文字母和數字構成的隨機驗證碼 """ all_chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' last_pos = len(all_chars) - 1 code = '' for _ in range(code_len): index = random.randint(0, last_pos) code += all_chars[index] return code
練習3:設計一個函數返回給定文件名的后綴名。
def get_suffix(filename, has_dot=False): """ 獲取文件名的后綴名 :param filename: 文件名 :param has_dot: 返回的后綴名是否需要帶點 :return: 文件的后綴名 """ pos = filename.rfind('.') if 0 < pos < len(filename) - 1: index = pos if has_dot else pos + 1 return filename[index:] else: return ''
練習4:設計一個函數返回傳入的列表中最大和第二大的元素的值。
def max2(x): m1, m2 = (x[0], x[1]) if x[0] > x[1] else (x[1], x[0]) for index in range(2, len(x)): if x[index] > m1: m2 = m1 m1 = x[index] elif x[index] > m2: m2 = x[index] return m1, m2
練習5:計算指定的年月日是這一年的第幾天
def is_leap_year(year): """ 判斷指定的年份是不是閏年 :param year: 年份 :return: 閏年返回True平年返回False """ return year % 4 == 0 and year % 100 != 0 or year % 400 == 0 def which_day(year, month, date): """ 計算傳入的日期是這一年的第幾天 :param year: 年 :param month: 月 :param date: 日 :return: 第幾天 """ days_of_month = [ [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31], [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] ][is_leap_year(year)] total = 0 for index in range(month - 1): total += days_of_month[index] return total + date def main(): print(which_day(1980, 11, 28)) print(which_day(1981, 12, 31)) print(which_day(2018, 1, 1)) print(which_day(2016, 3, 1)) if __name__ == '__main__': main()
練習6:打印楊輝三角。
def main(): num = int(input('Number of rows: ')) yh = [[]] * num for row in range(len(yh)): yh[row] = [None] * (row + 1) for col in range(len(yh[row])): if col == 0 or col == row: yh[row][col] = 1 else: yh[row][col] = yh[row - 1][col] + yh[row - 1][col - 1] print(yh[row][col], end='\t') print() if __name__ == '__main__': main()
綜合案例
案例1:雙色球選號
from random import randrange, randint, sample def display(balls): """ 輸出列表中的雙色球號碼 """ for index, ball in enumerate(balls): if index == len(balls) - 1: print('|', end=' ') print('%02d' % ball, end=' ') print() def random_select(): """ 隨機選擇一組號碼 """ red_balls = [x for x in range(1, 34)] selected_balls = [] selected_balls = sample(red_balls, 6) selected_balls.sort() selected_balls.append(randint(1, 16)) return selected_balls def main(): n = int(input('機選幾注: ')) for _ in range(n): display(random_select()) if __name__ == '__main__': main()
說明: 上面使用random模塊的sample函數來實現從列表中選擇不重復的n個元素。
綜合案例2:約瑟夫環問題
""" 《幸運的基督徒》 有15個基督徒和15個非基督徒在海上遇險,為了能讓一部分人活下來不得不將其中15個人扔到海里面去,有個人想了個辦法就是大家圍成一個圈,由某個人開始從1報數,報到9的人就扔到海里面,他后面的人接著從1開始報數,報到9的人繼續扔到海里面,直到扔掉15個人。由于上帝的保佑,15個基督徒都幸免于難,問這些人最開始是怎么站的,哪些位置是基督徒哪些位置是非基督徒。 """ def main(): persons = [True] * 30 counter, index, number = 0, 0, 0 while counter < 15: if persons[index]: number += 1 if number == 9: persons[index] = False counter += 1 number = 0 index += 1 index %= 30 for person in persons: print('基' if person else '非', end='') if __name__ == '__main__': main()
綜合案例3:井字棋游戲
import os def print_board(board): print(board['TL'] + '|' + board['TM'] + '|' + board['TR']) print('-+-+-') print(board['ML'] + '|' + board['MM'] + '|' + board['MR']) print('-+-+-') print(board['BL'] + '|' + board['BM'] + '|' + board['BR']) def main(): init_board = { 'TL': ' ', 'TM': ' ', 'TR': ' ', 'ML': ' ', 'MM': ' ', 'MR': ' ', 'BL': ' ', 'BM': ' ', 'BR': ' ' } begin = True while begin: curr_board = init_board.copy() begin = False turn = 'x' counter = 0 os.system('clear') print_board(curr_board) while counter < 9: move = input('輪到%s走棋, 請輸入位置: ' % turn) if curr_board[move] == ' ': counter += 1 curr_board[move] = turn if turn == 'x': turn = 'o' else: turn = 'x' os.system('clear') print_board(curr_board) choice = input('再玩一局?(yes|no)') begin = choice == 'yes' if __name__ == '__main__': main()
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。