Built-in Functions
按字母整理 Python 的 built-in functions,從 abs、all、any 到 breakpoint 的實際用法與範例,當作一份可以隨時翻回來的筆記。
這是一系列關於我拿到天文碩士學位,我一路所學到的技能,以及我認為必須延伸的技能組的文章,技能主線會保留在 Medium 上,以中英文方式呈現,而技能支線,會以中文形式在 GitHub.io,也就是這裡發表。 預計兩邊加起來會有 27 篇文章,透過這些文章來檢核天文學位帶來給我哪些影響。
前言
這篇文章假設你已經安裝好 Python,並且能夠 Compile your code,如果還不清楚,建議先閱讀Starting Python。
Built-in Functions
如標題所寫,今天會先了解到 Python 本身內建的函數,使用這些函數可以更快的編譯,減少呼叫外在套件達成一樣目的的時間。
A*
abs()
Short for absolute. 絕對值
回傳數值的絕對值,如果輸入為複數,則回傳 magnitude.
>>> abs(-2)
2
>>> abs(0.3)
0.3
>>> abs(-12)
12
>>> abs(-12.0)
12.0
>>> abs(-12.000)
12.0all()
From documentation: Return True if all elements of the iterable are true (or if the iterable is empty)
def all(iterable):
for element in iterable:
if not element:
return False
return True從官方解釋其實很好理解了,只要你的 list 裡面或是可迭代的物件裡面,全部不為空值,則回傳 True。 我們可以藉由一些例子來更好理解,也可以判別 None,np.nan 這些物件會被判別成怎樣
import numpy as np
print(all([]))
print(all([1,2,3]))
print(all([0,1,2,3]))
print(all([np.nan]))
print(all([None]))
True
True
False
True
Falseany()
any 是跟 all 相反的一種模式,只要迭代物件裡面任一是有值,就會回傳 True
From documentation:
def any(iterable):
for element in iterable:
if element:
return True
return Falseimport numpy as np
print(all([]))
print(all([1,2,3]))
print(all([0,1,2,3]))
print(all([np.nan]))
print(all([None]))
False
True
True
True
FalseB*
bool()
回傳 boolean ,布林值, True or False,與 any(),all()類似。
print(bool(1))
print(bool(0))
True
Falsebreakpoint()
在 Python3.7 之後,新增了 breakpoint 的功能,過往在 debug,通常都是透過 print 來了解變數值,或者了解函數進行到哪個階段,或是透過 IDE 有的 debug 功能,去設定 breakpoint 的點,這些功能現在可以透過給 breakpoint()來達成。 如果是對於使用 debug 不熟悉的人,建議可以觀看CS50 Lecture2,關於 debugger 的用法與操作。
breakpoint()可以想像是一個暫停點,程式會在 breakpoint 處停下來,你可以檢視目前的變數值等等。 舉個例子,這以下的迴圈當中,i 的值也許很好判斷,那 j 的值已經跑到哪裡了,也許是我們有興趣的
for i in range(10):
i = 0
for j in range(10):
j += ifor i in range(10):
i = 0
breakpoint()
for j in range(10):
j += i
## first breakpoint --> 進入到第一次breakpoint
(Pdb) print(i)
0
(Pdb) print(j)
*** NameError: name 'j' is not defined
(Pdb)
## second breakpoint --> 進入到第二次breakpoint
(Pdb) print(i)
0
(Pdb) print(j)
9
(Pdb)
## third breakpoint --> 進入到第三次breakpoint
(Pdb) print(j)
9
(Pdb) 如果有經驗,可能一眼就看出這個迴圈有問題,然而一開始沒經驗,可能會想說 j 怎麼沒有一直加上去,然後最後 output 出來就完全抓不到 bug 在哪裡。此時設立 breakpoint,就可以知道每跑一次迴圈,數值的變化如何,那問題點會在第一個或是第二個回圈裡面。
從 code 裡面,我們看到了(Pdb),也就是當遇到 breakpoint()時,Python 會叫出了指令,在這個環境下,可以對於參數進行檢核,像我們使用 print()的方式,那麼要進到下一個 breakpoint(),或者其他操作,有相對應的指令:
- 看變數值:
p [var] - 看目前位置:
l - 繼續到下一個 breakpoint():
c - 離開:
q
當中還有其他指令,不過這些就足以應付大部分 debug 的需求了。
D*
delattr()
在講到 Class 之前,我們先講到如何刪除屬性。由於 Python 語法是基於物件導向,任何東西都是視為一個物件在處理,類別(Class)也不例外,所以類別就會有屬性(attribute)。 舉個例子, 一個立方體的類別我們叫做 cube,那立方體有的就是三邊的邊長,我們各自叫 x,y,z,我們呼叫一個 a 為一個立方體,那他有三個屬性就分別是 x,y,z,我們可以透過 a.x, a.y, a.z 來檢視 a 的屬性。當要刪除 x 的屬性時,可以使用 delattr()。
class cube():
def __init__(self,x,y,z) -> None:
self.x = x
self.y = y
self.z = z
def volume(self):
return self.x * self.y * self.z
a = cube(x = 2, y = 3, z = 1)
print(a.x, a.y, a.z)
print(a.volume())
2 3 1
6
# 當我們添加刪除屬性之後
a = cube(x = 2, y = 3, z = 1)
print(a.x, a.y, a.z)
delattr(a,'x')
print(a.x, a.y, a.z)
print(a.volume())
# Python 會告訴我們立方體a並沒有x的屬性
print(a.x, a.y, a.z)
AttributeError: 'cube' object has no attribute 'x'
delattr(a,'x')也等同於del a.x
dict()
dict 為字典類別,用法類似於 list(), set(),會創造出一個字典物件。
根據官方文件指出,底下 6 種方式皆可以創造出{"one": 1, "two": 2, "three": 3}。
a = dict(one=1, two=2, three=3)
b = {'one': 1, 'two': 2, 'three': 3}
c = dict(zip(['one', 'two', 'three'], [1, 2, 3]))
d = dict([('two', 2), ('one', 1), ('three', 3)])
e = dict({'three': 3, 'one': 1, 'two': 2})
f = dict({'one': 1, 'three': 3}, two=2) 從其中幾種方式不難看出,在創建字典物件時,內建的dict()並不是必須,單純的使用{} 就可以創立字典物件。但在多個 list 物件時,或是要用 zip 將 list 合併成字典時,dict()會是更好用的選擇。
dir()
dir()提供the list of names in the current local scope。
這句話有點難翻譯,白話文的意思是回傳當下本地的變數範圍。
簡單的不同範例應該可以更好理解,在沒有給參數的 python 檔案裡面,我們直接 print(dir()),會得到一串變數名稱,如果針對個別變數去看他的值,不能看出這是在跑檔案時他本身的資訊。
這邊特別去 print __name__這個變數,這個變數會在很多 Python 裡面看到,以
if __name__ == __main__的形式。
print(dir())
>>> ['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__']
print(__name__)
>>> __main__divmod()
處理 division 除法的函式,可搭配下方語法糖做合併閱讀。 divmod()會回傳 quotient, remainder,而語法糖都只回傳數值。
print(divmod(1,2)) ---> (0, 1)
print(divmod(4,2)) ---> (2, 0)
print(divmod(4,3)) ---> (1, 1)
print(divmod(12.5,2)) ---> (6.0, 0.5)
print(divmod(12.5,1.5)) ---> (8.0, 0.5)
print(divmod(125.543,10.2)) ---> (12.0, 3.143000000000015)import math
print(5/2) --> 2.5
print(5//2) --> 2
print(5%2) --> 1
print(math.floor(5/2)) --> 2
print(-2/3) --> -0.6666666666666666
print(-2//3) --> -1
print(-2%3) --> 1F*
filter()
filter()顧名思義會做濾除的動作,依照判斷式來回傳一個 iterator。
a = [1,2,3,4,5,6,7,8]
filted = filter(lambda x: x<5 ,a)
for i in filted:
print(i)
>>>
1
2
3
4I*
input()
當我們需要使用者輸入參數時,input 可以擷取使用者在 Terminal 裡輸入的內容。 這是非常常使用的函數,畢竟我們不想要隨時 hard coding 我們的程式,每次都要進入程式碼修改參數。
name = input("What's you name? ")
print(f"Hello {name}")int()
將字串或浮點數轉換成整數。 這將會在處理檔案數字(通常是字串)或者取整數位時常用。
len()
Len 為 length 縮寫,回傳物件的長度。 物件可以是一個 list, tuple, string 或是 dictionary.
dictionary = {"a": "Anal","b":"Breast","c":"Cunt","d":"Dick"}
country = ['Chicago','Edinburgh','Yourkshire']
ages = (12,14,20)
name = "Tyler"
print(f"""
length of dictionary: {len(dictionary)}
length of country: {len(country)}
length of ages: {len(ages)}
length of name: {len(name)}
""")list()
List 的功用很廣,這邊舉幾個例子,主要是可以把一些可迭代物件轉換成 list 的形式。
以上一個例子來說
dictionary = {"a": "Anal","b":"Breast","c":"Cunt","d":"Dick"}
country = ['Chicago','Edinburgh','Yorkshire']
ages = (12,14,20)
name = "Tyler"
print(f"""
list of dictionary: {list(dictionary)}
list of country: {list(country)}
list of ages: {list(ages)}
list of name: {list(name)}
list of range: {list(range(1,10,2))}
""")
>>>
list of dictionary: ['a', 'b', 'c', 'd']
list of country: ['Chicago', 'Edinburgh', 'Yorkshire']
list of ages: [12, 14, 20]
list of name: ['T', 'y', 'l', 'e', 'r']
list of range: [1, 3, 5, 7, 9]map()
Return an iterator that applies function to every item of iterable, yielding the results. Map 就我經驗來說,他是非常好用,但不常用,屬於比較進階,當有些經驗之後,漸漸的 map 會是手上很好用的工具之一。
以一個例子來說,對於一個 list 如果需要取整數,勢必要用 int 取整數值,此時我們可以藉由 map 將大量數值一併作轉換。 但要注意的是 map 回傳的並不是 list 而是迭代器,所以再用 list 轉換。
print(list(map(int,[1.23,2.24,3.96,4.4,5.95387])))
>>> [1, 2, 3, 4, 5]max()
Maximum 顧名思義取最大值
max([1,2,3,4,5])
>>> 5min()
Minimum 顧名思義取最小值
min([1,2,3,4,5])
>>> 1N*
next()
當我們處理到迭代器(iterator)時,next 可以迭代到下一個值。
a = iter([1,2,3,4,5])
print(a)
print(next(a))
print(next(a))
print(next(a))
print(next(a))
>>>
<list_iterator object at 0x7fae2da6a940>
1
2
3
4O*
open()
Open 是常常使用來打開檔案的方式,在參數裡面可以選擇打開文件的 mode,簡單來說檔案打開並不是直覺的打開而擁有改寫刪的權限,相對的你必須選擇要以哪種方式打開,常用的方式是r,w,a,分別為讀寫以及增加(read, write, append)
通常在打開檔案時,我們會希望資源管理做好,畢竟如果檔案起來,資料讀完,我們想要把檔案關閉把資源拿到該用的地方,所以 open 常搭配的事 with 的用法,這樣就不必多寫一行把檔案關閉,也可以避免忘記。
藉由下面的範例我們可以更清楚知道使用方法,在一份 sample 文件裡面:
This is the first line.
Second line is about nothing.
Third line is the end.此時只有使用'r',所以只能夠讀,並不能寫,如果寫檔案時會出現
io.UnsupportedOperation: not writable
可以在範例裡面看到,讀取檔案有很多種方式,而開啟檔案的 f 會是一個迭代器,如果要將檔案內容取出當變數,則是要另外給var = f.readlines(), 那麼變數就會是 var = ['This is the first line.\n', 'Second line is about nothing.\n', 'Third line is the end.\n']
with open('sample.txt','r') as f:
# print(f.readline())
# print(f.readlines())
# print(f.read())
# for line in f:
# print(line)
# print(f)
# print(next(f))
# print(next(f))當然我們有時候要寫入檔案,此時就要注意選擇的模式會將你的游標放在哪裡,如果是 w,游標會在開頭,也就是會將原本內容覆寫過去,如果是 a,游標則會在最末端,以添加方式寫進檔案。
要注意的是要換行必須手動給換行符
'\n'
with open('sample.txt','r') as f:
for line in context:
f.write(line)
f.write('\n')P*
print()
Print 或者任何印出文字的方式,在任何程式語言裡面是 Debug 相當重要的一環,藉由 print 出當下的變數值,我們可以更清楚了解目前程式運作到哪一段落,或者變數哪裡出現問題,很多 IDE 目前有提供 Debugger 的操作,也是可以藉由暫停程式,查看當下變數值。
R*
range()
Range 是一個不變的數列,很常使用在於 for loop 當中,比如說我要印出 1~10,我可以輕易的使用:
for i in range(1,11,1):
print(i)要注意的是 range(start, stop, step),stop 的值是不會印出來的,所以要多加 1 上去。
如果想要整個數列,也可以使用list(range(5))來回傳一個[0,1,2,3,4]
round()
round 的意思是取整數,所以是進位的意思,在第二個參數可以給要到第幾位。
print(round(2.4)) --> 2
print(round(2.7)) --> 3
print(round(1.23245,2)) --> 1.23
print(round(1.23245,4)) --> 1.2325
print(round(0.4)) --> 0
print(round(-2.3)) --> -2
print(round(-2.7)) --> -3
print(round(-2.43583,2)) --> -2.44
print(round(-2.43583,4)) --> -2.4358S*
set()
set 是數一數二常用的函式之一,他會把一個可迭代的物件(list,tuple),回傳一個 set,而 set 裡面不會有重複的值。
a = [1,1,1,2,3,4,5,6,6,4,6,7]
print(set(a)) --> {1, 2, 3, 4, 5, 6, 7}
print(list(set(a))) --> [1, 2, 3, 4, 5, 6, 7]sorted()
排序迭代物件。
a = [1,1,1,2,3,4,5,6,6,4,6,7]
print(sorted(a))
print(sorted(a,reverse=True))
>>>[1, 1, 1, 2, 3, 4, 4, 5, 6, 6, 6, 7]
>>>[7, 6, 6, 6, 5, 4, 4, 3, 2, 1, 1, 1]str()
string()回傳字串版本的物件,這情況會使用在分析數字時,有時候以字串形式判斷或者要將字串與數字做合併。 不過自從使用f-string之後,這方法就比較少用了。
print('I am '+ str(24) + ' years old')
>>> I am 24 years oldsum()
回傳迭代物件的總和。
a = [1,1,1,2,3,4,5,6,6,4,6,7]
sum(a)
>>> 46super()
super 是一個比較難的概念,多半不會用到,但如果你是進階的使用者,那這項概念就必須了解。
先淺談 class 的想法,Python 語言是物件導向,所以可以想像類別(class)顧名思義是一個族群,那這個族群也會有細分成小族群。
以 MLB 為例子,MLB 是 Major League Baseball,美國職棒大聯盟,又可分成國家聯盟與美國聯盟,那麼底下有很多球隊,球隊底下又有不同細部員工。 所以我們可以說 MLB 是一個類別,底下單一隊伍也是一個類別,但是他們有一些類似的性質存在,比如說都打棒球?(這什麼廢話😂) 當你認為某些功能或行為是 subclass 也需要時,使用 super 來繼承
底下這個例子可以看看利用 super 承接 Parent class 的功能以及屬性。
class MLB():
def __init__(self):
self.level = 'MLB'
self.age = 119
def TeamNumber(self):
print('29 Teams in US')
print('1 Team in Canada')
class AL(MLB):
def __init__(self):
super().__init__()
self.level = 'AL'
def TeamNumber(self):
super().TeamNumber()
print('15 Temas in AL')
al = AL()
print(al.level)
al.TeamNumber()T*
tuple()
tuple 與 list,str 功用類似,會回傳物件的 tuple 性質,tuple 可以想像成是 list 的鎖定版本,裡面的值沒辦法做更動,如果要直接寫 list 可以用[]而要直接寫 tuple 可以使用()即是 tuple 物件。
type()
type 會回傳物件的類別,有時候不確定物件類別,這是好用的方法。
Z*
zip()
zip 也是前三常用好用的函式之一,可以將兩個迭代物件做平行合併。這樣講也許有點抽象,不過我們先看一個例子來了解一下,晚些就知道他的強大。
score = [89,76,83]
name = ['John', 'Fecco', 'Ryan']
for i in zip(score,name):
print(i)
>>>(89, 'John')
(76, 'Fecco')
(83, 'Ryan')References
Python 3.10.1 Documentation
別再用 print 來 Debug 啦!來用 Python Debugger 吧!
Python 繼承 543