[Udemy] 課堂筆記 – Complete python bootcamp

Hits: 406


python 環境設定

在上課之前,先把python的開發環境布署起來吧,詳細的布署筆記請參考這篇文章


課堂筆記

CH6: Command line in Windows

  • 先教command line
* cd: current directory
* cd ..回到上一層
* cd+D+tap,可自動顯示D開頭的資料夾
* cls: clear screen

CH8: Running Python Code

  • 可以跑python的環境
  • Text Editors
  • IDE
  • Notebook
  • 啟動ipynb
  • 在pycharm中安裝
  • File>Setting>Project>新增package

CH9

https://github.com/Pierian-Data/Complete-Python-3-Bootcamp

CH10 Introduction to python data types

file

CH11 Data types簡介

  • Integers: 整數
  • Float: 浮點小數
  • Strings: 字串,python中,可接受"" or ”
  • Lists: 有順序的清單
  • Dictionaries: 沒順序的key-value配對
  • Tuples: 有順序的清單,但內容物不可變更
  • Sets: 沒順序的物件
  • Booleans: 布林(T or F)

CH12 Numbers

  • %得出餘數(remainder)
    • 7 % 4 -- 3
  • 開根號(square root)
    • 9 ** 0.5 -- 3
  • 次方(power)
    • 2 ** 3 -- 8

CH13 Variable Assignment

  • Rules for variable names
    • 不能以數字開頭
    • 不能有空白
    • 不能有特殊符號
    • 小寫佳
    • Dynamic Typing,下列code是可以運行的,因為python不像其他語言是statitic typing
my_dogs=2
my_dogs=["sammy", "frankie"] 
  • Dynamic typing的優缺點
    • 優點
      • 不用指定資料型別
    • 缺點
      • data type用在函數中,容易導致資料型別錯誤而產生bug,要特別注意每個input的資料型別
  • 要注意這樣data type有沒有錯,可使用type()檢查

CH14 Strings

  • 'hello'or"hello"都可以,但是建議用"hello",因為英文會有遇到"I don't care"的時候,才不會出錯
  • 要取順序,是從0開始,也可反著取順序
    • file
  • slice [start:stop:step]
  • 跳脫字元:
    • \n這是new line
    • \t新增tab
  • len(算字元字數)

CH15 Indexing and slicing with strings

mystring='abcdefghijk'
mystring[2:] -> 'cdefghijk' # 類似大於等於2的概念
mystring[:3] -> 'abc' # 類似小於3的概念
mystring[3:6] -> 'def'
mystring[::2] -> 'acegik'
mystring[::-1] -> 'kjihgfedcba' # 字元反轉

CH16 String properties and methods

  • Immutability of string: 字串沒辦法直接修改第幾個字元的內容(doesn’t support item assignment)

    name = 'Sam'
    name[0] = 'P' # TypeError: 'str' object does not support item assignment
  • 字串相加用 +

  • 字串相乘

  • print(‘z’ * 10) -> zzzzzzzzzz

  • 字串切割

  • 字串函數
    x.upper/lower/split … etc

    • split()要有括號才會執行這個method
'This is a string'.split() -> ['This', 'is', 'a', 'string'] # 以空格分隔
'This is a string'.split(i) -> ['Th', 's ', 's a str', 'ng'] # 把i當作分隔符號來split

CH18 Print with Strings

  • 將字串輸出成特別的形式,有兩種方法
    • .format() … python 2的舊用法
    • f-strings … python 3的新用法
.format的方法
* print('The {2} {1} {0}'.format('fox', 'brown', 'quick')) -> The quick brown fox #.format可以依照位置,填入值
* print('The {q} {b} {f}'.format(f='fox', b='brown', q='quick')) # 也可用變數指派,比較好讀
  • Float formatting
  • 本功能可用於調整字串的位置
  • 設定字串位元數,四捨五入
  • 用法:value:width.precision+f
    • value: 變數
    • width: 變數的寬
    • precision: 小數位數,會四捨五入
result = 100/777 # 0.1287001287001287
print("The result was {r:1.3f}".format(r=result)) -> The result was 0.129
print(f'The result was {result:1.3f}') -> The result was 0.129
f-strings的方法
name = "Jose"
print(f'Hello, his name is {name}') # Hello, his name is Jose
print('Hello, his name is {}.format(name)') # Hello, his name is Jose

CH20 List

mix_list = ['string', 2, 100] # 可以混合資料型態
list1 = ['a', 'b', 'c']
list2 = ['d', 'e']
list1 + list2 -> ['a', 'b', 'c', 'd', 'e']

# 可直接取代
list1[0] = ['gg']
list1 -> ['gg', 'b', 'c']

# 可直接新增(在最後一筆)
list1.append('ggininder') # 注意寫法,這邊會直接對list1執行append()這個method
list1 -> ['gg', 'b', 'c', 'ggininder']

# 可直接移除(可設定index position)
list1.pop()
list1 -> ['gg', 'b', 'c'] # position沒寫,預設為最後一筆(-1)

可排序(sort),但要注意無法另存起來,他會直接把list做變更,沒辦法另存
可反排序(reverse)

CH22 Dictionary

  • {‘key1’: ‘value1’, ‘key2’: ‘value2’}
  • 要叫出資料要針對key
  • dictionary不能被排序,list可以被排序
  • dictionary裡面可以再放list或是其他distionary
  • 也可直接新增字典內的物件
d = {'k1': 100, 'k2': 120}
d['k3'] = 130
d -> {'k1': 100, 'k2': 120, 'k3': 130}
d.keys() -> ['k1', 'k2', 'k3']
d.values() -> [100, 120, 130]
d.tiems() -> [('k1', 100), ('k2', 120), ('k3', 130)] # it's a tuple

CH24 Tuples: a structure of data that has several parts

  • 跟list很像但具有不可修改(immutability)的特性
  • tuple = (‘a’,’a’,’b’)
  • tuple.count(‘a’) -> 2
  • tuple.index(‘a’) -> 0 #傳回第一個a的位置
  • Tuple的不具彈性,適合用來保留不能一直被變更的資料/物件,list與dictionary則是很有彈性

CH25 Sets

  • sets裡面的資料必須是不重複的
  • myset=set()
  • myset.add(1,1,2) -> {1,2}

CH26 Booleans

  • True/False

CH27 I/O with files

  • 要開啟檔案,要跟jupyter notebook放在一樣的位置才行
open('file.name')
pwd # 可得知現在的working directory

%%writefile myfile.txt # jupyter notebook限定的建立檔案的方法
This is first line.
This is second line.
This is third line.

myfile = open(myfile.txt)
myfile.read()
>> This is first line.\nThis is second line.\nThis is third line.
#把所有資料讀成一長串字串(包含換行符號) # 讀完之後,要用myfile.seek(0),才能重新讀取一次read()

myfile.readlines()
>>
['This is first line.\n',
'This is second line.\n',
'This is third line.'
]

myfile=open("C:\\path\\ttt.txt") # windows
myfile=open("C:/path/ttt.txt") # Mac/Linux
myfile.close() # 檔案讀進來之後要養成關掉的習慣,才能在OS進行其他操作

# 使用with可以自動關閉檔案,須注意縮排
with open ('myfile.txt') as newfile:
    content = newfile.read()content

CH30 object and data structure

作業

CH32 Chaining Comparison Operator

  • ‘2’ == 2 -> False
  • 2.0 == 2 -> True
  • 1 < 2 < 3 -> True
  • 1 < 2 > 3 -> False
  • 1 < 2 and 2 > 3 -> False
  • 1 < 2 or 2 > 3 -> True
  • 在所有判斷前加個not,則傳回判斷結果的相反
  • not 1 == 1 -> False

CH33 if else

  • if, elif, else
  • if else elif要在同一個縮排中,execute要在下一個縮排中,要對準
    file

CH35 For loop

  • my_iterable就是要被迴圈處理的物件
  • item_name就自已取(a,b,c,ee,xx…等諸如此類)
  • 範例如下
for num in [1, 2, 3, 4, 5]: # num是在迴圈中會用到的自訂變數名稱,用來代表for迴圈中in後面的每個物件,要被下一行的print(num)來處理
    print(num)
>> 1
>> 2
>> 3
>> 4
>> 5

CH35 While loop

  • 跟ifelse一樣,要注意縮排

  • while + else
    file

  • break, continue, pass

    • break: 停止距離最近的while迴圈
    • continue: 從頭(距離最近的while迴圈的第一行)開始進行
    • pass: 什麼都別做
  • 範例
    file

CH36 Useful Operator

  • range是generator,是function裡面的一種類型,可以產出訊息而非存在記憶體中
  • list(range(0,11,2)) -> [0,2,4,6,8,10]
  • enumerate() -> 列舉
    file
# 使用enumerate,回傳物件的自動遞迴並包含自動遞增的整數,以tuples的形式
word = "abcde"
for item in enumerate(word):
    print(item)
>> (0, 'a')
>> (1, 'b')
>> (2, 'c')
>> (3, 'd')
>> (4, 'e')
  • zip() -> 像是enumerate的反操作

    • file
    • 回傳tuples
    • 所有要被zip的物件,必須等長,不然只會回傳被zip物件裡面最短的長度
  • in -> 跟R/SQL一樣,用來檢查元素是否存在於物件中

  • min, max -> 跟R一樣,用來回傳物件中的最小值或最大值

  • from library import function -> 從library套件中引用function這個函數

    • python from random import shuffle # 從random套件中引用shuffle函數
  • input -> 產生文字輸入方塊

CH36-1 Import的補充


# 方法1. import [module_name]
import random
print(random.randint(0, 5)) # 使用時要呼叫module_name.method

# 方法1-1. import [module_name] as mn (改名的方法)
import random as rd
print(rd.randint(0, 5)) # 使用時要呼叫rd.randin

# 方法2. from [module_name] import [method1, method2...]
from random import randint
print(randint(0, 5)) # 使用時直接呼叫method

CH37 List Comparison

  • 用法與結構: new_list = [expression for_loop conditions]
  • used for creating new lists from other iterables.
  • consist of brackets containing the expression, which is executed for each element along with the for loop to iterate over each element.
以單層結構示範
# 單層結構
## 方法1: 迴圈
numbers = [1, 2, 3, 4]
squares = []

for n in numbers:
  squares.append(n**2)

print(squares)  # Output: [1, 4, 9, 16]

## 方法2: 串列綜合表達(List comprehension)
numbers = [1, 2, 3, 4]
squares = [n**2 for n in numbers]

print(squares)  # Output: [1, 4, 9, 16]
多層結構示範
# 多層結構
## 方法1: 迴圈
list_a = [1, 2, 3, 4]
list_b = [2, 3, 4, 5]
common_num = []

for a in list_a:
  for b in list_b:
    if a == b:
      common_num.append(a)

print(common_num) # Output: [2, 3, 4]

## 方法2: List comprehension
list_a = [1, 2, 3, 4]
list_b = [2, 3, 4, 5]
common_num = []

common_num = [a for a in list_a for b in list_b if a == b]
print(common_num) # Output: [2, 3, 4]
回傳 tuple 示範 (以 tuple 列出兩個 list 中不同的元素)
list_a = [1, 2, 3, 4]
list_b = [2, 3, 4, 5]
diff_num = []

diff_num = [(a, b) for a in list_a for b in list_b if a != b]
print(diff_num)
# Output [(1, 2), (1, 3), (1, 4), (1, 5), (2, 3), (2, 4), (2, 5), (3, 2), (3, 4), (3, 5), (4, 2), (4, 3), (4, 5)]
兩方法的比較

1. 方法1是比較好閱讀的,雖然比較繁瑣比較多行
2. 方法2是比較難閱讀的,雖然比較簡潔只有一行
其他範例

file

result = [num ** 2 if num%2 == 0 else 'ODD' for num in range(0,11)] # 很難維護,因為這邊是ifelse先才寫for
print(result)
# Output [0, 'ODD', 4, 'ODD', 16, 'ODD', 36, 'ODD', 64, 'ODD', 100]

CH40 Methods

mylist.append() -> .append() 就是一種操作清單(list)的方法(method)

  • 很多method可以在官方的document找到

Ch41 Function

  • 要先用 def開頭,function內可以設變數
    file

  • return可把function結果存起來

# function 可以寫文件
'''
這裡是function的description
'''
def say_hello(name="default_name"): # name是variable,可給予預設值
    print("hello " + name)
say_hello()

>> hello default_name

say_hello(frank)

>> hello frank

result = say_hello("frank")
result

>> hello frank
  • PIG LATIN example
    • word starts with a vowel, add ‘ay’ to end.
    • word not starts with a voewl, put first letter at the end, then add ‘ay’
    • file

CH43 args(*args) and kwargs(**kwargs)

  • args: arguments; kwargs: keyword arguments
*args
  • 在使用function時,一定要按照function中定義的參數數量執行,若超過,會出錯

    • file
  • args 可以不用指定function內的物件數量,就可以進行運算,在function內使用*args會以tuple的形式丟入function中執行

    • file
**kwargs
  • *args一樣,只是**kwargs是以dictionary的key丟入function中,並回傳value回來
組合*args**kwargs

file

CH49 Lambda expressions map and filter

Lambda function 的一些範例

# 一個參數
print((lambda x:x + 1)(3))  # (3+1) = 4
# 兩個參數
print((lambda x, b:x ** b)(5, 3))  # (5 ** 3) = 125

# 以 function 包起來 - 一個參數
def my_lambda(n):
    return lambda b:b ** n

print(my_lambda(5)(2))  # (2 ** 5) = 32
print(my_lambda(2)(5))  # (5 ** 2) = 25

# 以 function 包起來 - 兩個參數
def my_lambda2(n):
    return lambda b, c:(b+c) ** n

print(my_lambda2(5)(2, 3))  # (2+3) ** 5 = 3125
Map function

file

Filter function

file

Lambda expression(aka anonymous function)

file

CH50 Nested statements and scope

  • 首先說明什麼是LEGB rule:python在找變數時,會從L->E->G->B這四個層級來找變數,根據找到的變數進行函數的指派、程式運作等,LEGB分別代表的意思如下:

    • L: local
    • E: enclosed function local
    • G: global(module)
    • B: built-in(python)
  • 範例

# 把不同level的name設為註解,可以觀察回吐的name是哪一層
name = 'GLOBAL NAME' # global level
def greet():
    name = 'David' # enclosed function local
    def hello():
        name = 'Local' # local
        print("Hello " + name)
    hello()

greet()

>> Hello Local
運用LEGB rule說明什麼是變數範圍(Scope)
  • global的變數,可以安全的在function中被重新指派,且不會影響到global
x = 50
def func():
    print(f'x is {x}')

    #Local Reassignment
    x = 200
    print(f'I change x from 50 to {x}')
func()

>> x is 50
>> I change x from 50 to 200
  • 若是要在local的函數中改變global的變數,則使用global的指令
x = 50
def func():
    global x
    print(f'x is {x}')

    #Local Reassignment
    x = 200
    print(f'I change x from 50 to {x}')
func()
print(x)

>> x is 50
>> I change x from 50 to 200
>> 200
  • 但是不建議使用global指令來修改全域變數,因為會有維護的困難,若要更改全域變數,建議使用下列作法
x = 50
def func(x):
    print(f'x is {x}')
    # Reassignment
    x = 'New'
    print(f'I change x from 50 to {x}')
    return x
x = func(x)

>>> x is 50
>>> I change x from 50 to New

CH59 Object Oriented Programing

  • allows programmers to create objects that have methods and attributes.

  • 用class來定義物件(object),也因此可稱呼為類別

  • class通常使用駝峰(Camel casing)來撰寫(ex: FirstClassNaming)

  • class裡面會用def來定義method

  • init method:用來創建物件實體(instance)的指令

  • 用法:init(self,argument1, argument2, …) # self一定要用,用來在class中作為連結class實體與attribute/method的關鍵詞

  • 如下範例

file

CH60 Object Oriented Programing – Attributes and classes keyword

  • attribute: is a characteristic of an object.
  • methods: is an operation we can perform with the object.
  • 以下範例說明OOP的基本概念
# 1. 創建自訂Class
class Dog:

    # Class object attribute
    species = 'mammal' # 加入一個class層別的特性

    def __init__(self,mybreed): # mybreed是argument
        self.breed = mybreed    
        # 將mybreed這個argument指派給Class(也就是Dog)內的breed特性(attribute)

# 2. 利用自訂Class指派變數sam與frank
sam = Dog(mybreed='moon')
frank = Dog(mybreed='Huskie')

# 3. 叫出sam與frank的特性
print(sam.breed)
print(frank.breed)
print(sam.species) # 可直接呼叫sam的species這個特性
print(frank.species)

>> moon
>> Huskie
>> mammal
>> mammal
  • 為求方便,在上述程式碼中,一般會將argument, attribute的名稱定為一樣

CH61 Object Oriented Programing – Class object attributes and methods.

  • what’s the difference between function and method?
  • method is a function inside of a class, work with object, perform operations/actions to object
  • what’s the difference between atributes and methods?
    • method要用(),因為他像是要執行的function,所以要()
    • attribute不用(),因為attribute已經是你執行過的東西,只是要把你執行過的東西叫出來就不用()
class Dog:

    species = 'mammal'

    def __init__(self, breed, name): 
        self.breed = breed
        self.name = name

    def bark(self, number): # number是這個method中要主動提供的參數
        print("woo! My name is {}, I bark {} time each day".format(self.name, number)) # self.name是從init繼承來的,number是這個method要主動提供的參數

# 利用自訂Class指派變數sam與frank
sam = Dog(breed='moon', name='sam_dog')
frank = Dog(breed='Huskie', name='frank_dog')

# 叫出sam與frank的特性
print(sam.breed)
print(frank.breed)

print(sam.name)
print(frank.name)

print(sam.species)
print(frank.species)

# 叫出sam與frank的method
sam.bark(3)

>> moon
>> Huskie
>> sam_dog
>> frank_dog
>> mammal
>> mammal
>> woo! My name is sam_dog, I bark 3 time each day

CH62. Object Oriented Programming – Inheritance and Polymorphism

  • Inheritance: 就是class可以被繼承而重複使用
# Class Animal
class Animal():
    def __init__(self):
        print("Animal Created")
    def who_am_i(self):
        print("I am an animal")
    def eat(self):
        print("I am eating")
myanimal = Animal()

>> Animal Created

myanimal.eat()
myanimal.who_am_i()

>> I am eating
>> I am an animal

# Class Dog inherited from Animal
class Dog(Animal): # this is a derived class which inheritance from Animal_class
    def __init__(self):
        Animal.__init__(self) # 繼承Animal.__init__ -> print("Animal Created")
        # super().__init__(self) # 或是透過 super() 的函數來繼承
        print("Dog Created")
    def who_am_i(self):
        print("I am a dog!!") # this will overwrite the older method.
mydog = Dog()

>> Animal Created
>> Dog Created

mydog.eat() # mydog裡面沒有eat的method還是可以使用,因為他繼承自Animal這個class
mydog.who_am_i()

>> I am eating
>> I am a dog!!

更多關於 super() 的用法請點我

  • Polymorphism: 不同物件可以具有相同的method名稱,且可同時被呼叫使用
# 以下範例,示範使用Animal這個base class後,給Dog與Cat繼承
# 這範例可以發現,Dog與Cat因為繼承與多型性,不需要寫入__init__(已由Animal繼承而來)

class Animal():
    def __init__(self,name):
        self.name = name
    def speak(self): # this is a abstract method because it has no function.
        raise NotImplementedError("This is an error.")

class Dog(Animal):
    def speak(self):
        return self.name + " : Dog says woof"

class Cat(Animal):
    def speak(self):
        return self.name + " : Cat says meow"

myanimal = Animal("wally")
# myanimal.speak() # will raise the error

wally = Dog("wally")
wally2 = Cat("wally2")
print(wally.speak())
print(wally2.speak())

>> wally : Dog says woof
>> wally2 : Cat says meow

CH63. Special methods

  • 這邊講class中的特別method,如__str__用於回傳字串表達,__len__用於計算,__del__可用於刪除物件,若有需要,可以去官方文件查詢更多的special methods.

file

CH68. pip install and PyPi

  • Pypi is a repository for open source third party python packages.
  • 在command line執行pip install PackageName就是去pypi抓取套件並安裝於本機

CH69. modules and packages(筆記在ipython notebook)

  • Modules and Packages

    • .py scripts就是module,可以讓你的其他程式呼叫.py用
    • packages就是一系列的module(需包含__init.py__)
  • 圖解
    file

    1. 最大的package叫做game,底下有3個次package,分別是Sound, Image, Level
    2. 最大的package、3個次package都有使用__init__.py,這樣python才會把這個資料夾結構看成python package
    3. 每個次package裡面有各自不同的module(aka py script),用來處理不同功能所用
# Create modules
## mymodule.py
def my_func():
    print("This is mymodule.py")

## program.py
from mymodule import my_func
my_func()

## run in cmd
python myprogram.py

# Create packages
## 開啟一個資料夾(mypackage),#把mymodule.py與program.py丟入
## create __init__.py(裡面不用有任何文字,只要有檔案就可以),用於將folder變成package
## 在mypackage中,建立一個main_script.py

# main_script.py
def report_main():
    print("Here is main_script")

## import from package
from mypackag import main_script
main_script.report_main()

CH70. __name__ and __main__

  • 為什麼都會在python module的最後一行放入__name__ == '__main__'的判斷

  • if __name__ == "__main__" == T,就代表我正在直接執行one.py這個檔案

  • if __name__ == "__main__" == F,代表我這段程式碼one.py是被imported

  • 以下範例示範,創造one.py與two.py

# file one.py
def func():
    print("func() in one.py")
    print("top-level in one.py")

if __name__ == "__main__":
    print("one.py is being run directly")
else:
    print("one.py is being imported into another module")

# file two.py
import one # 對應到ony.py的else
print("top-level in two.py")
one.func()

if __name__ == "__main__":
    print("two.py is being run directly")
else:
    print("two.py is being imported into another module")
  • 然後在command line中執行
$ python one.py
>>> one.py is being run directly

$ python two.py
>>> one.py is being imported into another module
>>> top-level in two.py
>>> func() in one.py
>>> top-level in one.py
>>> two.py is being run directly

CH71. Errors and exception handling

在我的另外一篇文章寫過了

CH74. Pylint overview

  • 可用pylint, unittest來測試
  • 使用pylint檢查.py檔案的程式碼是否有問題,還可給出評分,以此為例,還給出負分呢
# this is test.py file

a = 1
b = 2
print(a)
print(B)
$ pip install pylint
$ pylint test.py # 記得要切換到檔案所在的路徑下

************* Module test
D:\test.py:6:0: C0304: Final newline missing (missing-final-newline)
D:\test.py:1:0: C0111: Missing module docstring (missing-docstring)
D:\test.py:3:0: C0103: Constant name "a" doesn't conform to UPPER_CASE naming style (invalid-name)
D:\test.py:4:0: C0103: Constant name "b" doesn't conform to UPPER_CASE naming style (invalid-name)
D:\test.py:6:6: E0602: Undefined variable 'B' (undefined-variable)

-------------------------------------
Your code has been rated at -12.50/10

CH75. Running tests with unittest library

  • 建立cap.py
# create cap.py
def cap_text(text):
    return text.capitalize()
  • 建立unitest.py
import unittest
import cap

class TestCap(unittest.TestCase): # 繼承自unittest的attribute: TestCase

    def test_one_word(self):
        text = "python"
        result = cap.cap_text(text) # 繼承自cap.py的method: cap_text
        self.assertEqual(result, "Python") # check the result vs 'expected result'

    def test_multiple_words(self):
        text = "pypi python"
        result = cap.cap_text(text)
        self.assertEqual(result, "Pypi Python")

if __name__ == '__main__':
    unittest.main()
  • 看看在shell中的執行結果
$ python unitest.py

======================================================================
FAIL: test_multiple_words (__main__.TestCap)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "unitest.py", line 14, in test_multiple_words
    self.assertEqual(result, "Pypi Python")
AssertionError: 'Pypi python' != 'Pypi Python'
- Pypi python
?      ^
+ Pypi Python
?      ^
----------------------------------------------------------------------
Ran 2 tests in 0.002s

FAILED (failures=1)

可以看到shell中執行有錯誤,明確的指出了錯誤原因是test_multiple_words這個method的問題,是因為cap.py的capitalize()只能轉換第一個字,若改用title()就不會有問題了

CH81 Decorators with python overview

在開發時會碰到一個情境,是原本開發好的的class, method等需要再多增功能。通常的作法就是直接在原本的code裡面新增新的功能,但隨著程式碼越來越龐大,若某天我需要把這個功能取消/擴充時,很容易影響到現在的程式架構,造成維護的困難。

因此﹑python有個功能,叫做裝飾器(decorator),只要在function的前面加上@,就可,比較常用在web develope的工作上。

在python中,function可以被當成argument傳入另一個function中,return為物件,重複使用,這就是decorator設計的用意。

  • 範例
# decorator code
def new_decorator(func):
    def wrap_func():
        print("Code would be here, before executing the func()")
        func() # pass your function here to decorate
        print("Code here will execute after the func()")
    return wrap_func

# use decorator
@new_decorator
def func_needs_decorator2():
    print("Help me to decorate")

# execute
func_needs_decorator2

>>> Code would be here, before executing the func()
>>> Help me to decorate
>>> Code here will execute after the func()

CH83. Generators

  • allowing user to generate a sequence of values over time.
  • don’t actually return a value and then exit, instead generator functions will automatically suspend and resume the execution and state around the last point of value.
  • generator computes one value waits until next value is called.
  • range就是個generator
  • 跟傳統方式相比,就是不用產生一個大的list把所有結果存起來,而是用generator逐步的把東西產出
  • 示範使用next()iter()來逐步產出,讓記憶體使用效率更佳
    • next()是針對數值物件
    • iter()是針對字串物件
# create function that generate fibonacci sequence
def genfibon(n):
    """
    Generate a fibonnaci sequence up to n
    """
    a = 1
    b = 1
    for i in range(n):
        yield a # aka print(a)
        (a,b) = (b,a+b) # tuple assignment

# execute
for num in genfibon(10):
    print(num)

>>> 1, 1, 2, 3, 5, 8, 13, 21, 34, 55

# save fibonacci
g = genfibon(10)
g

>>> generator object genfibon at 0x000001E2ED2E8C00

# check the result
next(g)
>>> 1

next(g)
>>> 1

next(g)
>>> 2

next(g)
>>> 3

next(g)
>>> 5
  • 以下示範iter()
s = 'hello'

# Iterate over string
for letter in s:
    print(letter)

s_iter = iter(s)

next(s_iter)

>>> 'h'

next(s_iter)

>>> 'e'

next(s_iter)

>>> 'l'

CH87-90. Collection module

Counter

算出物件的重複次數,可用於數字、文字皆可

from collections import Counter

# deal with list
l = [1,1,12,3,1,1,1,2,2,2,3,3,4,5,6,6,7,78,8,8,6,5,4,4]
print(Counter(l))
print(type(Counter(l))) # Counter object

>>> Counter({1: 5, 3: 3, 2: 3, 4: 3, 6: 3, 5: 2, 8: 2, 12: 1, 7: 1, 78: 1})
>>> class 'collections.Counter'

# deal with string
sl = 'asdddssaqaazzbv'
Counter(sl)

>>> Counter({'a': 4, 's': 3, 'd': 3, 'q': 1, 'z': 2, 'b': 1, 'v': 1})

# deal with words(NLP)
words = "How do you turn this on and on and on many times".split()
Counter(words)

>>> Counter({'How': 1,
         'do': 1,
         'you': 1,
         'turn': 1,
         'this': 1,
         'on': 3,
         'and': 2,
         'many': 1,
         'times': 1})

# attribute
Counter(words).most_common

>>> <bound method Counter.most_common of Counter({'on': 3, 'and': 2, 'How': 1, 'do': 1, 'you': 1, 'turn': 1, 'this': 1, 'many': 1, 'times': 1})>
defaultdict

在dictionary裡面,必須要指定key:value配對,若沒有配對,是無法直接操作的,使用dafaultdict可以在沒有指名key:value的情況下,給予預設的key與value值

from collections import defaultdict
dict = {'k1':1}
d['k1'] >>> 1
d['k2'] >>> KeyError

d = defaultdict(object)
d['one'] >>> <object at memory_location>

d = defaultdict(lambda: 0) # 結合lambda expression
d['two'] = 2
d >>> defaultdict(<function <lambda> at memory_location>, {'two':2, 'one': 0})
OrderdDict

一般在mapping dictionary內的key:value時,並不會按照順序排序,若要作到這件事情,可使用內建的sorted

# 範例1: 未排序的dictionary
d = {'banana': 3, 'apple':4, 'pear': 1, 'orange': 2}

for k, v in d.items():
    print(k, v)

>>> banana 3
>>> apple 4
>>> pear 1
>>> orange 2

# 範例2: 排序的dictionary
ds = sorted(d.items())
for k, v in ds:
    print(k, v)

>>> apple 4
>>> banana 3
>>> orange 2
>>> pear 1

namedtuple

利用namedtuple製造變數

from collections import namedtuple

Dog = namedtuple("Dog", "age breed name") 
# 第一個argument是class name, 第二個argument是用空格分隔的attributes

sam = Dog(age = 2, breed = "moon", name = "haha")
print(sam)
print(sam.age)
print(sam.breed)
print(sam.name)

>>> Dog(age=2, breed='moon', name='haha')
>>> 2
>>> moon
>>> haha

CH91. Datetime module

介紹python的時間處理套件Datetime

import datetime
t = datetime.time(5, 25, 1) # hour, minute, second, microsecond, and tzinfo
print(t)
print(t.hour)

>>> 05:25:01
>>> 5

d = datetime.date.today()
print(d)
print(d.year)
print(d.month)
print(d.day)

>>> 2019-04-11
>>> 2019
>>> 4
>>> 11

d1 = datetime.date.today()
d2 = datetime.date(2018,12,31)
d1-d2

>>> datetime.timedelta(days=101)

CH92. Python Debugger

這章介紹python debugger的modeule(pdb),藉由此module,可產生互動式的測試環境,逐步輸入值,完成除錯

import pdb
x = [1, 3, 4]
y = 2
z = 3

pdb.set_trace() # 產生互動式環境,可輸入值測試

result = y + z
print(result)

result2 = y + x
print(result2)

CH93. Timing your code – timeit

import timeit

# 以下三種表示方式,都可將0到100的數值以'-'相連,可藉由timeit來測試效率
print("-".join(str(n) for n in range(100)))
print("-----")
print("-".join([str(n) for n in range(100)]))
print("-----")
print("-".join(map(str, range(100))))

# 觀察某段程式碼的執行時間
print(timeit.timeit('"-".join(str(n) for n in range(100))',  number = 10000))
print(timeit.timeit('"-".join([str(n) for n in range(100)])',  number = 10000))
print(timeit.timeit('"-".join(map(str, range(100)))',  number = 10000)) # 最快

CH94. Regular expression

參考連結

CH95. StringIO

把字串變成檔案物件的方法

import StringIO
string = "how do you turn this on"
f = StringIO.StringIO(string)

About the Author

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

You may also like these