跳到主要內容

[Coding] Python

comment:

  single line: #
  multiple line: ''' ... '''

encode: # -*- coding: utf-8 -*-

math operation:

  • 先乘除後加減
  • 5**2: 5 的平方
  • 5**0.5: 平方根
  • log(8, 2) => 3

Data type

  • None 就是 C 的 null
  • 變數型態不需宣告
  • only int, float, string
  • string
    • 'mystring'
    • mychar = string[0] #mychar is still string type
    • string[2:5]
    • s[2] == 'a'
    • s += "append string"
  • array/linked-list/stack (implemented by array) 
    • fruits = ['orange', 'apple', 'pear', 'banana', 'kiwi', 'apple', 'banana']
    • len(fruits)
    • fruits.count('apple') => 2
    • fruits.index('banana') => 3
    • fruits.index('banana', 4) => 6
    • fruits.remove('banana')
    • del fruits[-1]
    • fruits.insert(3, 'grape')
    • fruits.reverse()
    • fruits.append('grape')
    • fruits += ['orange', 'peach']
    • fruits.sort()
    • fruits.pop() => 'banana'
    • nD
      • 2D array 取值是用 a[i][j],不是用 a[i, j],後者回傳的是 tuple
      • 可用 a[i][j:j+n] 取一截 list,但不可用 a[i:i+n][j:j+n] 取一塊矩陣
      • sum(list) 可用於取 list 的總和,但只能 1D
    • seq[start:end:step]
    • max(list)
  • queue
    • from collections import deque
    • myq = deque(['A', 'B', 'C', 'D', 'E'])
    • myq.append ('F') => deque(['A', 'B', 'C', 'D', 'E', 'F'])
    • myq.popleft() => 'A'
    • if q: # check if its empty queue
  • tuple (不可變動的 list)
    • tp1 = ()
    • tp2 = (1, 2, 3, 4, 5)
    • len(tp2) => 5
    • sum(tp2) => 15
    • tp2[2:4] => (3, 4)
    • tp2[-1] => 5
    • tp3 = tuple([2 * x for x in range(1, 8)]) => (2, 4, 6, 8, 10, 12, 14)
    • print(tuple('Ivy Lin')) => ('I', 'v', 'y', ' ', 'L', 'i', 'n')
    • tp2 + tp3 => (1, 2, 3, 4, 5, 2, 4, 6, 8, 10, 12, 14)
    • tp4 = tuple([1, 2, 3, 4, 5]) => (1, 2, 3, 4, 5)
    • max(tp4) => 5
    • min(tp4) => 1
    • list(tp2) => [1, 2, 3, 4, 5]
    • tp2 == tp4 => true
  • dictionary
    • dic = {'key1': 22, 'key2': 42}
    • dic[key3] = 333
    • for i in sorted (dic.keys()):
        print(dic[i])
    • if key in dic:
    • dict 不可迭代,可使用 next(iter(dict)) 幫助先轉換成可迭代
      或者使用 for k, v in dict.items()
    • sorted_x = sorted(x.items(), key=lambda kv: kv[1])
      sorted_x will be a list of tuples sorted by the second element in each tuple.

Print

  print('...', '...', ...)

  • 若要不換行,指定 end 參數 print('...', end=' ')
  • sep 參數指定每個參數之間 print 時的分隔字元
  • 也有類似 C 的方式:print('%d %.2f %s' % (1, 99.3, 'Justin'))
    % 符號之後要接一個 (tuple)
  • f-string (3.6 以後支援)
    >>> stock = 'tsmc'
    >>> close = 217.5
    >>> f'{stock} price: {close}'

    'tsmc price: 217.

stderr

def eprint(*args, end='\n', **kwargs):
    print(*args, file=sys.stderr, end=end, **kwargs)

Loop

for

  for _ in range(n)  # 執行 n 次,底線代表不在意
  for i in range (0, n)  # 執行 n 次,i 會從 0 到 n-1
  for i in range (n, -1, -1)  # 執行 n+1 次,i 會從 n 到 0
  for m in iterable_object  # m 會依序為可迭代物件的 member

  • 用於定義物件
    mylist = [i for i in range(0, 5)]

while

while i > 0:
    i = i - 1
    print('append ', a[i])

Condition

  • if:
    elif:
    else:
  • .. if ... else ...  # 三元運算子
  • "is" is used for checking reference equality

Function

def reverseArray(a):
    return a
  • 若 function 內要使用到全域變數,需加上 "global" 宣告
  • python 無法指定參數傳值或傳址,是其可變形態而定
    • 不可變,相當於傳值:數字,字串,元組
    • 可變,相當於傳址:列表,字典
  • 實際上 def 是個陳述句,Python 執行到 def 時會產生一個函式物件,為 function 的實例,即然函式是個物件,它可以指定給其它的變數
  • Python 不支援重載,在同一個名稱空間中,不能有相同的函式名稱。如果定義了兩個函式具有相同的名稱但擁有不同的參數個數,則後者定義會覆蓋前者定義
  • 指定可變動物件陷阱
    >>> def appendTo(element, arr = []):
    ...     arr.append(element)
    ...     return arr
    >>> appendTo(10)
    [10]
    >>> appendTo(20, [4, 5, 6])
    [4, 5, 6, 20]
    >>> appendTo(20)  # 這個串列是在 def 時就已經被創立
    [10, 20]
def sum(*numbers):
  • 不定長度引數,傳入函式的引數,會被收集在一個 Tuple 中,再設定給 numbers
  • 如果有個函式擁有固定的參數,也可以將一個 Tuple 傳入,只要在傳入時加上*,則 Tuple 中每個元素會自動指定給各個參數
    def sum3(a, b, c):
        return a + b + c
    numbers = (1, 2, 3)
    print(sum3(*numbers))
>>> def dosome(**args):
...     print(args)
>>> dosome(name = 'Justin', passwd = 123456, job = '?')
{'passwd': 123456, 'job': '?', 'name': 'Justin'}
  • **則可以將關鍵字引數收集在一個字典物件中
  • 同理,如果函式參數個數固定,也可以傳給函式一個字典物件,只要在物件前加上**,則 Python 會依字典物件的鍵名稱,將值指定給對應名稱的參數
    def sum3(a, b, c):
        return a + b + c
    args = {'a' : 1, 'b' : 2, 'c' : 3}
    print(sum3(**args))
  • 可以在一個函式中,同時使用*與**
>>> def some(*arg1, **arg2):
...     print(arg1)
...     print(arg2)
>>> some(1, 2, 3)
(1, 2, 3)
{}
>>> some(a = 1, b = 22, c = 3)
()
{'a': 1, 'c': 3, 'b': 22}
>>> some(2, a = 1, b = 22, c = 3)
(2,)
{'a': 1, 'c': 3, 'b': 22}
    • *arg1 必須要在 **arg2 的前面,因為 *arg1 搜集的是有順序感的參數
      def fun(a, *args, **kwargs):
          print("a={}".format(a))
          for arg in args:
              print('Optional argument: {}'.format( arg ) )
          for k, v in kwargs.items():
              print('Optional kwargs argument key: {} value {}'.format(k, v))
  • 函式中還可以定義函式,稱之為區域函式(Local function),好處之一就是可以直接存取包裹它的外部函式之參數(或宣告在區域函式之前的區域變數),如此可減少呼叫函式時引數的傳遞
  • 匿名函式 lambda,就不不需要有名字的暫時使用的函式
    lambda 的語法是
    lambda arg1, arg2, ....: expression
    • max = lambda m, n: m if m > n else n

Data Structure

Array

  from array import array
  b = array('i')
  b.fromlist(list)

Class

class SinglyLinkedListNode:
    def __init__(self, node_data):
        self.data = node_data
        self.next = None

private member/function

  會以兩個底線開頭,但基本上只是命明區別,而並非真的 private

繼承

class CheckingAccount(Account):
    def __init__(self, id, name):
        super(CheckingAccount, self).__init__(id, name) # 呼叫父類別__init__()
        self.overdraftlimit = 30000
    def withdraw(self, amount):  # 從子類別開始尋找是否有定義,否則就搜尋父類別中是否有定義方法
        if amount <= self.balance + self.overdraftlimit:
            self.balance -= amount
        else:
            raise ValueError('超出信用')
    def __str__(self):
        return (super(CheckingAccount, self).__str__() +
                '\nOverdraft limit\t' + str(self.overdraftlimit));

acct = CheckingAccount('E1234', 'Justin Lin')
print(acct, end='\n\n')
acct.deposit(1000)      # 使用 Account 的 deposit() 定義
print(acct, end='\n\n')
acct.withdraw(2000)     # 使用 CheckingAccount 的 withdraw() 定義
print(acct, end='\n\n')
  • 可以進行多重繼承,使用時搜尋正確 func 定義該用誰的,的順序是從子類別開始,接著是同一階層父類別由左至右搜尋,再至更上層同一階層父類別由左至右搜尋,直到達到頂層為止
  • 每個類別有個__bases__特性,記錄著所繼承的父類別,__bases__是個 Tuple

I/O

input

  input('請輸入你的名稱:')  # 從 stdin 取得 input,支援提示字串
  • int('...'), float('...'), bool('...') 支援將字串轉為其他形態
  file = open(name, 'r', encoding='UTF-8')
  content = file.read()  # 全部讀入
  print(content)
  file.close()

  file = open(name, 'r', encoding='UTF-8')
  for line in file.readlines():  # 逐行讀取
      print(line, end='')
  file.close()

  for line in open(name, 'r', encoding='UTF-8'):  # for 會嘗試呼叫檔案物件的 next() 方法,next() 方法每次傳回下一行,並在沒有資料可讀取時丟出 StopIteration
    print(line, end='')

output

  • print(1, 2, 3, file = open('data.txt', 'w'))  # file 指定輸出位置,可為 stderr 或實際檔

Error Handling

try:
  #嘗試執行的程式碼
except 例外名稱:
  #當遇到例外時要執行的程式碼,except 的區塊可以有很多個

try:
    a = int(input())
    b = int(input())
    print(a/b)
except ZeroDivisionError:
    print("Cannot divide by 0!")
except:
    print("Wrong input")

try:
  #嘗試執行的程式碼
except 例外名稱:
  #當遇到特定的例外時要執行的程式碼
except:
  #當未指定的例外發生時要執行的程式碼
else:
  #若 try 當中的程式碼並未產生例外時要執行的區塊
finally:
  #無論如何都要執行的程式碼

try:
    a = int(input())
    b = int(input())
    c = a/b
except ZeroDivisionError:
    print("Cannot divide by 0!")
except:
    print("Wrong input")
else:
    print("The answer is " + str(c))
finally:
    print("Program finished")

Useful functions

map

Apply function to every item of iterable and return a list of the results
  • map(int, listA)  # return 一個 list 其內容為 listA 中各元素轉換為 int 
  • print map(multiple2, list1)  # multiple2 為一個自定義 func,將 list1 中的各元素作為 multiple2 的參數傳入,得到相應的 multiple2 的回傳值組成一個 list 回傳
  • map(adder, list1, list2, list3)  # adder 這個 func 有三個參數

sort

list.sort()
sorted_list = sorted(list)
  • sorted() 會回傳一個排序好新的 list,sort() 會直接修改原始的 list 並排序完成
  • sort() 只能用在 list 上排序,而 sorted() 可用來排序任何的 iterable(string, dictionary, tuple...)
  • sorted()
    • 可指定 reverse 為 True,會把排序的結果由預設的 ascending 改成 descending
    • 可設定一個 func 給 key 這個參數,在排序之前會自動對每個 element call 一次所指定的 function,比如將 element 都先轉為 lower case。key 只能接受 function 物件,所以常見藉由 lambda 來提取複雜物件中欲用來 sort 的 key 
students = [
        ('john', 'A', 15),
        ('jane', 'B', 12),
        ('dave', 'B', 10),
]
sorted(students, key = lambda x : x[2])  # x 為 iterable 中的每個元素,作為參數傳入 lambda,lambda 定義的 expression 為 x[2] 即為結果回傳
    • Python 另外有 operator module,可以不用自己撰寫 key 的 function 可以簡單提取複數個物件中的元素作為 key 值
      from operator import itemgetter, attrgetter

filter

filter() 函数用于过滤 list,过滤掉不符合条件的元素,返回由符合条件元素组成的新 list。
接收两个参数,第一个为 function object,第二个为 list,list 的每个元素作为参数传递给function object 进行判,function 返回 True 或 False,将返回 True 的元素放到新 list 中

Asynchronous I/O

  要達成非同步 (Asynchronous) I/O 有很多種策略,常聽到的是使用多執行緒(multithreading) 達到非同步。但另外 python 提供協同程序 (coroutine) 的概念。
  簡單說協同程序是在 single thread 下允許程式來決定程式執行的順序,而有效達成非同步 I/O 的一種方法。
  • 事件迴圈
    • 異步程式可以在多個任務之間切換,這個程式的架構裡一定有一個任務 list,這樣程式才知道有什麼樣的任務可以做切換,而這個任務的 list 以及中間切換的機制,就是由事件迴圈 (Event loop) 來處理
  • 事件 (Event) 與 回調函數 (Callback)
    • 現在 Event loop 裏面有一個 list,若程式有一些任務需要以異步的方式去執行就需要以 "Event:Callback" 的型式註冊進 Event loop 的 list,之後 Event loop 以 for 迴圈的方式去察看 list 裏面的 Event 是否發生,若發生了就執行相對應的 Callback,並註銷這個Event的監聽
    • 比如正在監聽的 Event_B 發生了,就會註銷 Event_B 的監聽 (也就是把Event_B從list中移除),然後執行Callback_B,執行完後在繼續監聽剩下的事件
  • 協程 (coroutine)
    • 協程可以看做是 "能在中途中斷、中途返回值給其他協程、中途恢復、中途傳入參數的函數",和一般的函數只能在起始傳入參數,不能中斷,而且最後返回值給父函數之後就結束的概念不一樣
    • 定義協程很簡單,只要在定義函數時再前面加入"async" 這個關鍵字就行了
import asyncio
loop = asyncio.get_event_loop() #建立一個Event Loop

loop.run_until_complete(coroutine)
# 這個函數註冊參數裡的任務並執行,等到任務完成就關閉 Event Loop
# 這裏被註冊進去的事件的定義是 loop 一啟動就直接觸發的,所以 coroutine 裡面的任務內容會馬上執行

loop.run_forever()
# 這個函數一執行,Event Loop 就會永遠執行不會被關閉,除非在程式中出現loop.stop()就停止

import asyncio
loop = asyncio.get_event_loop() #建立一個Event Loop

async def example1(): # 定義一個中間會被中斷的協程
    print("Start example1 coroutin.")
    await asyncio.sleep(1) # 中斷協程一秒
# 使用await可以針對耗時的操作進行掛起,就像生成器裏的 yield 一樣,函數讓出控制權。協程遇到 await,事件循環將會掛起該協程,執行別的協程,直到其他的協程也掛起或者執行完畢,再進行下一個協程的執行。耗時的操作一般是一些IO操作,例如網絡請求,文件讀取等
    print("Finish example1 coroutine.")

async def example2(): # 定義一個協程
    print("Start example2 coroutine.")
    # do some process...
    print("Finish example2 coroutine.")

tasks = [ # 建立一個任務列表
    asyncio.ensure_future(example1()),
    asyncio.ensure_future(example2()),
]
# 把協程封裝成一個 task 對象,這個對象儲存了任務的 "上下文"(context),協程才能順利的恢復執行,因為暫停時的變數內容都存在 task 對象裡

loop.run_until_complete(asyncio.wait(tasks))
# asyncio.wait():把任務列表都註冊到Event Loop,並要求 Event Loop 必須確定裡面的兩個任務都執行完才能結束 Event Loop 機制

# 把 example1, example2 這兩個 coroutin 註冊到事件循環裡
# loop 啟動,先執行 example1,中途暫停 example1 之後切換到 example2,最後再切回example1

output:
Start example1 coroutine.
Start example2 coroutine.
Finish example2 coroutine.
Finish example1 coroutine.

ref:
https://ithelp.ithome.com.tw/articles/10199403


留言

這個網誌中的熱門文章

[Development] Deep Learning over Python 深度學習基於 Python 1/3

  用 Python 練習實作深度學習,主要包含 Tensorflow 以及 SVM,著重於實作範例,未深入涉及各 DL 演算法模型原理及其數學。 大綱 [Development] Deep Learning over Python  深度學習基於 Python  1/3 Basic Tools: 基於 python- numpy, matplotlib, scipy, Pandas [Development] Deep Learning over Python 深度學習基於 Python 2/3 Keras (基於 Tensorflow)  Tensorflow [Development] Deep Learning over Python 深度學習基於 Python 3/3 Support Vector Machine (SVM) 強化學習 Reinforcement Learning (RL) Reference: 本篇基於  Udemy 課程 "吳佳諺- Python 深度學習"  為架構出發衍生,其他引用資料個別在段落中標示 Basic Tools numpy import numpy as np from scipy import linalg   # linear algebra import matplotlib.pyplot as plt myarray = np.array([[1, 2, 3], [4, 5, 6]]) print('myarray:', myarray) myarray_allzero = np.zeros((3, 5), dtype = np.int16) print('myarray_allzero:', myarray_allzero) myarray_2 = np.arange(15, dtype = np.int64) print('myarray_2:', myarray_2) myarray_2 = myarray_2.reshape((3, 5)) print('myarray_2 reshape:', myarray_2) myarray: [[1 2 3...

[Development] Deep Learning over Python 深度學習基於 Python 2/3

  用 Python 練習實作深度學習,主要包含 Tensorflow 以及 SVM,著重於實作範例,未深入涉及各 DL 演算法模型原理及其數學。 大綱 [Development] Deep Learning over 深度學習基於 Python Python 1/3 Basic Tools: 基於 python- numpy, matplotlib, scipy, Pandas [ Development] Deep Learning over Python  深度學習基於 Python  2/3 Keras (基於 Tensorflow) , 使用 Sequential 模型(範例 實作 "MINST 手寫辨識") CNN (Convolutional Neural Networks) 卷積神經網路 (範例 實作 "MINST 手寫辨識") RNN (Recurrent Neural Networks) 遞歸(迴)神經網路 (範例 實作 "IMPb 評論辨識") Tensorflow 基礎應用 NN 基本作用原理 CNN (Convolutional Neural Networks) 卷積神經網路 (範例 實作 "MINST 手寫辨識") [Development] Deep Learning over Python 深度學習基於 Python 3/3 Support Vector Machine (SVM) 強化學習 Reinforcement Learning (RL) Reference: 本篇基於 Udemy 課程 "吳佳諺- Python 深度學習" 為架構出發衍生,其他引用資料個別在段落中標示 Keras Keras 是一个用 Python 编写的高级神经网络 API,它能够以  TensorFlow ,  CNTK , 或者  Theano  作为后端运行 Keras 的核心数据结构是  model ,一种组织网络层的方式。最简单的模型是  Sequential 顺序模型 ,它由多个网络层线性堆叠。对于更复杂的结构,你应该使用  Keras 函数式 API ,它允许构建任意的...

[Development] Deep Learning over Python 深度學習基於 Python 3/3

  用 Python 練習實作深度學習,主要包含 Tensorflow 以及 SVM,著重於實作範例,未深入涉及各 DL 演算法模型原理及其數學。 大綱 [Development] Deep Learning over Python 深度學習基於 Python 1/3 Basic Tools: 基於 python- numpy, matplotlib, scipy, Pandas [Development] Deep Learning over Python 深度學習基於 Python 2/3 Keras (基於 Tensorflow)  Tensorflow [Development] Deep Learning over Python 深度學習基於 Python 3/3 Support Vector Machine (SVM) 萬用分類機 Reinforcement Learning (RL) 強化學習 Reference: 本篇基於  Udemy 課程 "吳佳諺- Python 深度學習"  為架構出發衍生,其他引用資料個別在段落中標示 Support Vector Machine (SVM) 萬用分類機   SVM 就是用統計上風險最小化的方法,來產生一個分類的超平面 (hyperplane),也就是找到一個決策邊界 (decision boundary),該邊界可以讓「兩類」之間的邊界 margins 最大化。   SVM 是一個二元分類器,也就是只能做非黑即白的分類判斷。   如果資料只有二維,如在二維直線座標系中標記了許多點,若這些點概念上可以被分成兩類,我們就可以透過迴歸分析的幫助,找出一條線來最適當的把這兩類的點切分開來,這條線如果是直線,那就是一個一元一次方程式,如果是曲線那當然就是二次三次或更高。   而該怎麼找出最佳的一個切割面?SVM 的提議也很簡單,他假設如果存在一個 hyperplane,這個 hyperplane 距離所有 A/B 類節點的距離總和最長,那他就是一個最佳的分割面,這裡的距離的概念也就是 margin。簡單理解就是,處在兩個點的「最中間」位置的那條線就是這兩點的最佳切割線。  ...