import sys
print(sys.version)
3.5.0 (default, Sep 23 2015, 04:41:33) [GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.57)]
# good
a = 1
spam(han[1], {egg: 2})
magic(r=real, i=img)
# bad
a = 1
spam( han[ 1 ], { egg: 2 } )
magic(r = real, i = img)
if 2 > 1: # good
print('2 > 1')
if 2 > 1: print('2 > 1') # bad
if a is not b # good
if not a is b # bad
if not somelist # good
if len(somelist) == 0 # bad
if somelist # good
if len(somelist) > 0 # bad
'''
|- bar
| |- __init__.py
| |- foo.py
| |- test1.py
'''
# in test1.py
from bar import foo # (1) good
import foo # (1) bad
from . import foo # (2) good
import foo # (2) bad
print('測試 (str): ', len('測試'))
print('測試 (unicode): ', len(u'測試'))
測試 (str): 6 測試 (unicode): 2
print('測試 (str): ', len('測試'))
print()
words = '測試'.encode('utf-8')
print(words)
print('測試 (bytes): ', len(words))
測試 (str): 2 b'\xe6\xb8\xac\xe8\xa9\xa6' 測試 (words): 6
# Python3
# Unicode 字元 -> 位元組資料
words = '測試'.encode('utf-8')
print(words)
# 位元組資料 -> Unicode 字元
words2 = words.decode('utf-8')
print(words2)
b'\xe6\xb8\xac\xe8\xa9\xa6' 測試
# Python3
# 接受 str (Unicode) 或 bytes,並總是回傳 str
def to_str(bytes_or_str):
if isinstance(bytes_or_str, bytes):
value = bytes_or_str.decode('utf-8')
else:
value = bytes_or_str
return value
# 接受 str (Unicode) 或 bytes,並總是回傳 bytes
def to_bytes(bytes_or_str):
if isinstance(bytes_or_str, str)
value = bytes_or_str.encode('utf-8')
else:
value = bytes_or_str
return value
# Python2
'123' + u'₡' # ok
'₡' + u'123' # UnicodeDecodeError
'a' == u'a' # True
'₡' == u'₡' # False, UnicodeWarning
# os.urandom - a bytes object contains random bytes
# Python2: ok
with open('/tmp/random.bin', 'w') as f:
f.write(os.urandom(10))
# Python3: TypeError: write() argument must be str, not bytes
with open('/tmp/random.bin', 'w') as f:
f.write(os.urandom(10))
# Write
with open('/tmp/random.bin', 'wb') as f:
f.write(os.urandom(10))
# Read
with open('/tmp/random.bin', 'rb') as f:
data = f.read()
from urllib.parse import parse_qs
my_values = parse_qs('red=5&blue=0&green=', keep_blank_values=True)
print(my_values)
{'red': ['5'], 'green': [''], 'blue': ['0']}
# Case 1
red = my_values.get('red') # ['5']
blue = my_values.get('blue') # ['0']
green = my_values.get('green') # ['']
yellow = my_values.get('yellow') # None
# Case 2
red = my_values.get('red', 0) # ['5']
blue = my_values.get('blue', 0) # ['0']
green = my_values.get('green', 0) # ['']
yellow = my_values.get('yellow', 0) # 0
# Case 3
red = my_values.get('red', [''])[0] # '5'
blue = my_values.get('blue', [''])[0] # '0'
green = my_values.get('green', [''])[0] # ''
yellow = my_values.get('yellow', [''])[0] # ''
# Case 4 Why?
red = my_values.get('red', [''])[0] or 0 # '5'
blue = my_values.get('blue', [''])[0] or 0 # '0'
green = my_values.get('green', [''])[0] or 0 # 0
yellow = my_values.get('yellow', [''])[0] or 0 # 0
# First part is True
a = 1 or 2 # 1
b = 2 or 1 # 2
c = -1 or 1 # -1
# First part is False
a = '' or 0 # 0
b = [] or -1 # -1
c = 0 or 2 # 2
# 最簡潔!難讀!
red = int(my_values.get('red', [''])[0] or 0) # 5
blue = int(my_values.get('blue', [''])[0] or 0) # 0
green = int(my_values.get('green', [''])[0] or 0) # 0
yellow = int(my_values.get('yellow', [''])[0] or 0) # 0
# 簡潔!好讀一點!
red = my_values.get('red', [''])[0] # '5'
red = int(red) if red else 0 # 5
blue = my_values.get('blue', [''])[0] # '0'
blue = int(blue) if red else 0 # 0
green = my_values.get('green', [''])[0] # ''
green = int(green) if red else 0 # 0
yellow = my_values.get('yellow', [''])[0] # ''
yellow = int(yellow) if red else 0 # 0
# 最不簡潔!最好讀!
red = my_values.get('red', [''])[0] # '5'
if red:
red = int(red) # 5
else:
red = 0
blue = my_values.get('blue', [''])[0] # '0'
if blue:
blue = int(blue) # 0
else:
blue = 0
# 簡潔!好讀!易修改!
def get_first_int(values, key, default=0):
found = values.get(key, [''])[0]
if found:
found = int(found)
else:
found = default
return found
red = get_first_int(my_values, 'red') # 5
blue = get_first_int(my_values, 'blue') # 0
green = get_first_int(my_values, 'green') # 0
yellow = get_first_int(my_values, 'yellow') # 0
somelist[:2] # good
somelist[0:2] # bad
somelist[2:] # good
somelist[2:len(somelist)] # bad
a = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
print('a[:4] =', a[:4])
print('a[-4:] =', a[-4:])
print('a[3:-3] =', a[3:-3])
print('a[:-1] =', a[:-1])
print('a[2:5] =', a[2:5])
print('a[-3:-1] =', a[-3:-1])
a[:4] = ['a', 'b', 'c', 'd'] a[-4:] = ['e', 'f', 'g', 'h'] a[3:-3] = ['d', 'e'] a[:-1] = ['a', 'b', 'c', 'd', 'e', 'f', 'g'] a[2:5] = ['c', 'd', 'e'] a[-3:-1] = ['f', 'g']
a = [1, 2, 3, 4, 5, 6, 7, 8]
first_three_items = a[:3] # [1, 2, 3]
first_ten_items = a[:10] # [1, 2, 3, 4, 5, 6, 7, 8]
last_three_items = a[-3:] # [6, 7, 8]
last_ten_items = a[-10:] # [1, 2, 3, 4, 5, 6, 7, 8]
# 注意 1: 直接指定超出串列邊界的索引會導致錯誤
a[10]
IndexError: list index out of range
# 注意 2: 若 start 或 end 索引設為 -0 時,等同於 0
a = [1, 2, 3, 4, 5, 6, 7, 8]
a[-0:] # [1, 2, 3, 4, 5, 6, 7, 8]
a[:-0] # []
a = [1, 2, 3]
b = a[:]
c = a
print('a_id:', id(a))
print('b_id:', id(b))
print('c_id:', id(c))
a_id: 140134057715528 b_id: 140134049210056 c_id: 140134057715528
# 串列中全是不可變 (immutable) 對象
a = [1, 2, 3]
b = a[:]
b[0] = 4
print('a:', a)
print('b:', b)
a: [1, 2, 3] b: [4, 2, 3]
# 串列中包含可變 (mutable) 對象
a = [1,2, [3, 4]]
b = a[:]
b[0] = 4 # 修改不可變對象
print('a:', a)
print('b:', b)
print()
b[2][0] = 5 # 修改可變對象
print('a:', a)
print('b:', b)
a: [1, 2, [3, 4]] b: [4, 2, [3, 4]] a: [1, 2, [5, 4]] b: [4, 2, [5, 4]]
a = [1, 2, 3, 4, 5, 6, 7, 8]
a[2:6] = ['a', 'b', 'c'] # 前 4 後 3
print(a)
[1, 2, 'a', 'b', 'c', 7, 8]
a[2:4] = ['a', 'b', 'c', 'd', 'e'] # 前 2 後 5
print(a)
[1, 2, 'a', 'b', 'c', 'd', 'e', 5, 6, 7, 8]
a = ['a', 'b', 'c', 'd', 'e', 'f']
# 當 stride 是正數,意即從串列的頭開始
a[::2] # ['a', 'c', 'e']
a[::3] # ['a', 'd']
# 當 stride 是負數,意即從串列的尾開始
a[::-1] # ['f', 'e', 'd', 'c', 'b', 'a']
a[::-2] # ['f', 'd', 'b']
# 當 stride 與 start 或 end 同時使用,容易使人困惑 (stride 為負數時尤勝)
a[2::2] # ['c', 'e']
a[:-2:2] # ['a', 'c']
a[2:-2:2] # ['c']
a[-2::-2] # ['e', 'c', 'a']
a[:2:-2] # ['f', 'd']
a[-2:2:-2] # ['e']
a[4:1:-2] # ['e', 'c']
a = [1, 2, 3, 4, 5, 6]
# 使用 map
squares = list(map(lambda x: x**2, a))
print(squares)
[1, 4, 9, 16, 25, 36]
# 使用串列概括式 (list comprehension)
squares = [x**2 for x in a]
print(squares)
[1, 4, 9, 16, 25, 36]
a = [1, 2, 3, 4, 5, 6]
# 使用 map
squares = list(map(lambda x: x**2, filter(lambda x: x%2 == 0, a)))
print(squares)
[4, 16, 36]
# 使用串列概括式 (list comprehension)
squares = [x**2 for x in a if x%2 == 0]
print(squares)
[4, 16, 36]
# Python3
child_rank = {'Amy': 1, 'Mary': 2, 'Tom': 3}
# dict
rank = {rank: name for name, rank in child_rank.items()}
print(rank)
# set
child_name_length_set = {len(name) for name in rank.values()}
print(child_name_length_set)
{1: 'Amy', 2: 'Mary', 3: 'Tom'} {3, 4}
# 想將二維矩陣變成一維陣列
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [item for row in matrix for item in row]
print('flat =', flat)
# 想要計算二維矩陣內每個值的平方
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
squares = [[item**2 for item in row] for row in matrix]
print('squares =', squares)
# 想要過濾出大於 4 的偶數值
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
b = [x for x in a if x > 4 if x%2 == 0]
c = [x for x in a if x > 4 and x%2 == 0]
print('b =', b)
print('c =', c)
flat = [1, 2, 3, 4, 5, 6, 7, 8, 9] squares = [[1, 4, 9], [16, 25, 36], [49, 64, 81]] b = [6, 8, 10] c = [6, 8, 10]
my_lists = [
[[1, 2], [3, 4]],
[[5, 6], [7, 8]],
]
flat = [item for sub_list1 in my_lists for sub_list2 in sub_list1 for item in sub_list2]
print(flat)
[1, 2, 3, 4, 5, 6, 7, 8]
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
filtered = [[x for x in row if x%3 == 0] for row in matrix if sum(row) > 10]
print(filtered)
[[6], [9]]
# 若該檔案極端龐大,可能會在 value 實際產生完畢之前就把記憶體塞爆
value = [len(line) for line in open('/tmp/my_file.txt')]
print(value)
[100, 57, 15, 1, 22, 3]
# 串列概括式: 檔案過大,記憶體可能爆掉
value = [len(line) for line in open('/tmp/my_file.txt')]
print(value)
print()
# 產生器運算式: 可利用 next 內建函式來一次次讀取輸出值,不用擔心記憶體爆掉
value = (len(line) for line in open('/tmp/my_file.txt'))
print(value)
print(next(value))
print(next(value))
[100, 57, 15, 1, 22, 3] <generator object <genexpr> at 0x101b81480> 100 57
# 利用剛剛的 value 來當作 roots 的輸入
roots = ((x, x**2) for x in value)
print(next(roots))
(15, 225)
# 產生 1~10 的串列
a = [i+1 for i in range(10)]
print(a)
# 產生五組介於 1~10 之間的亂數
import random
for i in range(5):
print(random.randint(1, 10))
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] [4,3,3,1,7]
a = ['red', 'blue', 'green', 'yellow']
for i, color in enumerate(a):
print(i, color)
0 red 1 blue 2 green 3 yellow
# By range
for i in range(len(a)):
print(i+1, a[i])
print()
# By enumerate
for i, color in enumerate(a, 1):
print(i, color)
1 red 2 blue 3 green 4 yellow 1 red 2 blue 3 green 4 yellow
names = ['Cecilia', 'Lise', 'Marie']
letters = [len(n) for n in names]
longest_name = None
max_letters = 0
# By range: 有視覺雜訊,相同索引使用了兩次
for i in range(len(names)):
count = letters[i]
if count > max_letters:
max_letters = count
longest_name = names[i]
print(longest_name)
# By enumerate: 稍微改善,但不夠理想
for i, name in enumerate(names):
count = letters[i]
if count > max_letters:
max_letters = count
longest_name = name
print(longest_name)
Cecilia Cecilia
names = ['Cecilia', 'Lise', 'Marie']
letters = [len(n) for n in names]
longest_name = None
max_letters = 0
for name, count in zip(names, letters):
if count > max_letters:
max_letters = count
longest_name = name
print(longest_name)
Cecilia
a = [1, 2, 3, 4, 5]
b = ['a', 'b', 'c']
for number, letter in zip(a, b):
print(number, letter)
1 a 2 b 3 c
from itertools import zip_longest
a = [1, 2, 3, 4, 5]
b = ['a', 'b', 'c']
for number, letter in zip_longest(a, b):
print(number, letter)
1 a 2 b 3 c 4 None 5 None
# Case 1
for i in range(3):
print('loop', i)
else:
print('Else block!')
loop 0 loop 1 loop 2 Else block!
# Case 2
for i in range(3):
print('loop', i)
if i == 1:
break
else:
print('Else block!')
loop 0 loop 1
# Case 3
for x in []:
print('Never run')
else:
print('Else block!')
Else block!
# Case 4
while False
print('Never run')
else:
print('Else block!')
Else block!
a = 4
b = 9
for i in range(2, min(a, b)+1):
print('Testing', i)
if a%i == 0 and b%i == 0:
print('Not coprime')
break
else:
print('Coprime')
Testing 2 Testing 3 Testing 4 Coprime
# Case 1
def coprime(a, b):
is_coprime = True
for i in range(2, min(a, b)+1):
if a%i == 0 and b%i == 0:
is_coprime = False
break
return is_coprime
# Case 2
def coprime(a, b):
for i in range(2, min(a, b)+1):
if a%i == 0 and b%i == 0:
return False
return True
f = open('/tmp/random_data.txt') # 這邊可能會有 IOError
try:
data = f.read() # 這邊可能會有 UnicodeDecodeError
finally:
f.close()
def load_json_key(data, key):
try:
result_dict = json.loads(data)
except ValueError as e:
print(e)
return None
else:
return result_dict[key] # 這邊可能會有 KeyError