常常要用python做一件看起來很簡單的事,
卻不小心寫的很複雜?
本文嘗試收集開發python程式常用的小技巧,
方便查詢使用
使用須知:
為了將程式寫的精簡,
有時語法不是那麼易懂,
所以建議可以將功能包裝成函數增加可讀性
目錄:
這邊將文章收錄的功能整理出來,
可在此瀏覽是否有你想找的
<字串類>
<容器類>(list, set, dict, ...)
<實用內建函數類>
想看到更多python技巧的文章?歡迎點like追蹤
有更多值得收藏的技巧?歡迎留言分享
返回主頁: 系列篇章統整: 小馬的程式語法學習筆記(python為主)
範例input:
s = "apple pie pineapple pen"
delChars = 'aeiou' # 要刪除的字元
範例output: 'ppl p pnppl pn'
程式:
def removeChar(s, delChars):
for c in delChars:
s = s.replace(c,'')
return s
s = "apple pie pineapple pen"
s = removeChar(s,'aeiou')
print(s)
範例input:
s = "A man, a plan, a canal: Panama123987"
範例output: 'amanaplanacanalpanama'
程式:
def strAlpha(s):
return ''.join([c.lower() for c in s if c.isalpha()])
s = "A man, a plan, a canal: Panama"
s = strAlpha(s)
print(s)
說明:
這邊示範統計一個字串由多少「漢字」、「英文」及「其它符號(含數字、空格、…)」組成
網路查詢資料說「漢字」(應該含簡體字)的範圍介於utf-8碼的[u'\u4e00', u'\u9fa5']之間,
注意isalpha()函數很特別,碰到漢字亦返回true,故需要先判斷漢字
def strComposition(string):
result = [0, 0, 0]
for char in string:
if u'\u4e00' <= char <= u'\u9fa5':
result[0] += 1
elif char.isalpha():
result[1] += 1
else:
result[2] += 1
return result
result = strComposition("汉字test @*%")
print(result) # [2, 4, 4]
說明:
全形字元: abcdefghijklmnopqrstuvwxyz123456789
半形字元: abcdefghijklmonpqrstuvwxyz123456789
爬文查到說
全形字元的unicode編碼從65281~65374 (十六進位制 0xFF01 ~ 0xFF5E),
對應到半形字元unicode編碼從33~126 (十六進位制 0x21~ 0x7E)
空格比較特殊,全形為 12288(0x3000),半形為 32(0x20)
因此,除了空格需特別處理外,
可以得到轉換公式為「半形+65248=全形」
def dict_key_val_reverse(D):
# 將字典的鍵-值互換,例: {'a': 1, 'b': 2}-> {1: 'a', 2: 'b'}
return dict(zip(D.values(), D.keys()))
def strConvert(s, mode='Q2B'):
"""
參數說明:
s: input string
mode:
'Q2B'-> 字串全形轉半形
'B2Q'-> 字串半形轉全形
"""
assert mode in {'Q2B', 'B2Q'}, "請輸入合法的模式(e.g. Q2B, B2Q)"
rstring = ""
convertDict = dict(zip(range(33,127),range(65281, 65375)))
convertDict.update({32:12288})
if mode=='Q2B':
convertDict = dict_key_val_reverse(convertDict)
for uchar in s:
u_code = ord(uchar)
if u_code in convertDict:
u_code = convertDict[u_code]
rstring += chr(u_code)
return rstring
if __name__ == '__main__':
s = "你好pythonabdalduizxcvb nm"
print(strConvert(s, mode='B2Q'))
範例input:
List = [30,23,'a',6,97]
target = 6
範例output: True
說明: 程式很簡單,但是你若一開始學其它程式語言而轉換到python的話,
邏輯很容易寫成用for迴圈檢查每個元素是否等於目標值,
其實python有in運算子,可讀性高又簡潔
程式:
def BAD_find_in(List, target):
for e in List:
if e==target:
return True
return False
def find_in(List, target):
return target in List
List = [30,23,'a',6,97]
target = 6
print(find_in(List, target)) # True
範例input: ["a", "b", "a", "c", "c"]
範例output: ["a", "b", "c"]
程式:
def removeDuplicate(x):
"""
自python3.6版以後,
亦可寫 return list(dict.fromkeys(x))
因為python3.6版以後的字典是有序的(3.6版前的字典無序就會錯)
"""
return sorted(set(seq), key = seq.index)
mylist = removeDuplicate(["a", "b", "a", "c", "c"])
print(mylist) #["a", "b", "c"]
範例input:
x = {'a': 1, 'b': 2}
y = {'b': 3, 'c': 4}
z = {'e': 10}
範例output: {'a': 1, 'b': 3, 'c': 4, 'e': 10}
程式:
def merge_dicts(*dict_args):
result = {}
for dictionary in dict_args:
result.update(dictionary)
return result
x = {'a': 1, 'b': 2}
y = {'b': 3, 'c': 4}
z = {'e': 10}
print(merge_dicts(x,y,z))
範例input: [1,1,2,5,-6,0,2]
範例output: [3, 3, 4, 5, 1, 2, 4]
說明: 原陣列由小到大排序為[-6, 0, 1, 2, 5],
第一個元素1第三小,
第二個元素1第三小,
第三個元素2第四小,
程式:
def get_rank(X):
x_rank = dict((x, i+1) for i, x in enumerate(sorted(set(X))))
return [x_rank[x] for x in X]
print(get_rank([1,1,2,5,-6,0,2]))
範例input: [[1,2,3],[4,5],[6,7]]
範例output: [1, 2, 3, 4, 5, 6, 7]
程式:
#最簡單的攤平列表的方法,適用普通的二維列表
def singleFlat(arr):
return sum(arr, [])
# 將一個多重嵌套的list轉為一維list,一行解 (是容器就拆,否則成list)
def flat(arr):
return [x for sub in arr for x in flat(sub)] if isinstance(arr, (list,tuple,set,dict)) else [arr]
L=[{1,2},{1:'A'},(1,"H",3),[5,[2,1],(3,4)],50,(1,['54',0])]
print(flat(L))
範例input:
List = [1,2,3,4,5,6,7,8,9,10,11,20,66]
step = 3
範例output:
(正常分組)[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 20], [66]]
(從尾端分組)[[1], [2, 3, 4], [5, 6, 7], [8, 9, 10], [11, 20, 66]]
程式:
def sepList(L,step):
return [L[i:i+step] for i in range(0,len(L),step)]
#從後面分組
def backSepList(L,step):
return [L[max(0,i-step+1):i+1] for i in range(len(L)-1,-1,-step)][::-1]
# <另解> return list(map(lambda x: list(reversed(x)),sepList(L[::-1],step)))[::-1]
a = [1,2,3,4,5,6,7,8,9,10,11,20,66]
step = 3
print(sepList(a,step)) #[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 20], [66]]
print(backSepList(a,step)) #[[1], [2, 3, 4], [5, 6, 7], [8, 9, 10], [11, 20, 66]]
範例input: ['A', 'B', 'C'], [1, 2, 3]
範例output: {'A': 1, 'B': 2, 'C': 3}
程式:
def mergeListToDict(list1, list2):
return dict(zip(list1, list2))
A = ['A', 'B', 'C']
B = [1, 2, 3]
print(mergeListToDict(A,B))
範例input: {'a': 1, 'b': 2, 'c': 3, 'd': 4}
範例output: {1: 'a', 2: 'b', 3: 'c', 4: 'd'}
程式:
def dict_key_val_reverse(D):
# 將字典的鍵-值互換,例: {'a': 1, 'b': 2}-> {1: 'a', 2: 'b'}
return dict(zip(D.values(), D.keys())) #另解: return {v: k for k, v in m.items()}
範例input: myList = ['A','B','A','A','B','B','A','C','C','C']
範例output: Counter({'A': 4, 'B': 3, 'C': 3})
程式:
from collections import Counter
myList = ['A','B','A','A','B','B','A','C','C','C']
count = Counter(myList)
print(count) # Counter({'A': 4, 'B': 3, 'C': 3})
print(count['A']) # 4
print(count['D']) #對於不存在的值默認為0
print(count.most_common(2)) #出現次數最高的兩個元素: [('A', 4), ('B', 3)]
函數功能:
利用模組itertools的groupby將相鄰的相同性質的元素排序,
input需要事先用key排序過。
以本例來說,
定義重組字(anagram)為同性質
from itertools import groupby
def grouping(arr, KEY_FUNC):
A = sorted(arr, key = KEY_FUNC)
return [(k, list(g)) for k, g in groupby(A,key=KEY_FUNC)]
A = ["eat", "tea", "tan", "ate", "nat", "bat"]
group = grouping(A, lambda x: ''.join(sorted(x)))
print(group) # [('abt', ['bat']), ('aet', ['eat', 'tea', 'ate']), ('ant', ['tan', 'nat'])]
程式功能: 檢查容器A的是否包含容器B(元素可重複)
思路:
利用Counter減法的特性,不會使元素個數減至負數。
計算元素個數,用B去減掉A的所有元素,如果A不包含B,
則一定會有一些東西剩下來。
from collections import Counter
def doesAcontainB(A, B):
return len((Counter(B)-Counter(A)).keys())==0
print(doesAcontainB("ABCD","ACD")) # True
print(doesAcontainB([1,2,2],[1,2,3])) # False
程式功能:
對二維矩陣做轉置、旋轉、翻轉的基本操作,
以二維矩陣表示影像時,同時也是影像的基本操作。
相關:
(LeetCode 48題) Rotate Image
(LeetCode 832題) Flipping an Image
目前包裝成一個class
class Image():
def __init__(self, arr):
self.arr = arr
def show(self):
for a in self.arr:
print(a)
print()
#垂直翻轉
def flipVertical(self):
self.arr = self.arr[::-1]
#水平翻轉
def flipHorizontal(self):
self.arr = [a[::-1] for a in self.arr]
#轉置,即行列互換(沿左上- 右下對角線翻轉)
def T(self):
self.arr = list(map(list,(zip(*self.arr))))
def rotateRight(self):
self.flipVertical()
self.T()
def rotateLeft(self):
self.flipHorizontal()
self.T()
# 以下程式供測試
if __name__ == '__main__':
A = [list(range(i,i+4)) for i in range(1,13,4)]
arr= Image(A)
arr.show()
arr.rotateLeft()
arr.show()
arr.rotateRight()
arr.show()
arr.flipVertical()
arr.show()
arr.flipHorizontal()
arr.show()
arr.T()
arr.show()