如果第一個學習的不是Python語言, 常常依照其他語言的語法來寫Python, 這裡紀錄常見語法的Python寫法, 本篇參考網路上的文章, 一些作者整理了Effective Python中相當多值得學習的地方, 完整連結於文章最下方
多個list一起使用
for a1, a2 in zip(arr1, arr2):
print(a1, a2)
注意:zip 會在最短的 list 結束,想要執行到最長的 list,可以用
itertools
的zip_longest
Generator
概括式遇到大型資料時,可能會因為創立一個過於龐大的 list,造成程式當掉,例如我要計算文字檔每一行的字數
lengths = [len(x) for x in open('/PATH/INFO.txt')]
print(lengths)
# > [32, 19, 1, 12, 26]
如果檔案 size 非常大,或是他是一個不會停止的 input,你應該改用 generator 來產生迭代器,按需要產出內容
lengths = (len(x) for x in open('/PATH/INFO.txt'))
print(it)
# > <generator object <genexpr> at 0x0000017BF5C939E8>
然後搭配 next
來一次次觸發 iterator
print(next(lengths))
print(next(lengths))
# > 32
# > 19
Python 3.7 開始會內建 Data Classes,之後 Python 3.6 也能透過 pip 安裝。
Data Class 支援預設值 和 更多樣化的型別定義,例如
from dataclasses import dataclass, field
from typing import Any, List
@dataclass
class Node:
x: int
y: int
radius: float = 0.0
name: str = 'none'
child: Any = None
test: List[int] = field(default_factory=list)
這段 code 應該很好理解,名稱後用 :
宣告型態,型態在 typing 套件中更多支援(例如這邊的 Any),在型態後面用 =
賦予預設值。
暫時忽略最後一行的那個 field,這段 code 可以像是正常使用 class 一樣,用順序或是 keywords 輸入數值
print(Node(2, 4))
# Node(x=2, y=4, radius=0.0, name='none', child=None, test=[])
print(Node(2, 4, name='end', radius=1.5))
# Node(x=2, y=4, radius=1.5, name='end', child=None, test=[])
print(Node(4, 6, 5.3, 'hi', test=[1, 2, 3]))
# Node(x=4, y=6, radius=5.3, name='hi', child=None, test=[1, 2, 3])
取代 == Bool
if valid(): print 'valid' if not valid(): print 'invalid'
if not users: print 'No users available'
tuple
list to tuple
def get_error_details(): return (2, 'details') (errnum, errstr) = get_error_details()
my_list = ['Alice', 12, 'Python'] (name, age, skill) = my_list
(x, y) = (y, x)
邏輯很短的if 表示法
def foo(logging): level = (1 if logging else 0)
enumerate
不用額外宣告index 然後 index = index + 1
names = ['Alice', 'Bob', 'Cindy'] for index, element in enumerate(names): print '%d %s' % (index, element)
使用[:]計算陣列
不用len(account)再去計算
def get_check_number(account): return account[-4:]
文字過長用括號不用 \
sql = ( "SELECT name, product, price " "FROM production.product " "WHERE description = 'TEST' " "AND days < 10 " "ORDER BY name DESC" )
取代 if 中還需要temp變數紀錄是否滿足
for n in range(2, 10): for x in range(2, n): if n % x == 0: print n, 'equals', x, '*', n/x break else: print n, 'is a prime number'
string合併
name_list = ['Alice', 'Bob', 'Cindy'] name_formatted = ', '.join(name_list)
判斷name是否在dict當中,若沒有回傳Bob
name = some_dict.get('name', 'Bob')
getter,setter
class Egg(object): def __init__(self, price): self._price = price @property def price(self): return self._price * RATE @price.setter def price(self, value): self._price = value
取代手動關閉, try catch必須手動關閉, 使用with才是好的寫法
with open('tmp.txt', 'w') as f: f.write('TEST')
f = open('tmp.txt', 'w') try: f.write('TEST') finally: f.close()
第一種方式最簡短, 也不會像map,filter難理解
imgs = [f.upper() for f in glob.iglob('*.gif') if os.stat(f).st_size > 2000]
imgs = [] for f in glob.iglob('*.gif'): if os.stat(f).st_size > 2000: imgs.append(f.upper())
imgs = map(lambda x: x.upper(), filter(lambda f: os.stat(f).st_size > 2000, glob.iglob('*.gif'))
使用內建函數all(條件必須全都符合), any (條件只要一個符合), sum取代自己寫
要記得不要去蓋掉他
def is_valid(file_names): return all('py' in name for name in file_names)
def is_dangerous(sql): actions = ('update', 'delete', 'replace') return any(sql.startswith(action) for action in actions)
prices = [100, 300, 50, 600] total = sum(prices)
defaultdict 若key不存在會回傳[] , 不會有exception
import collections the_dict = collections.defaultdict(list) for author, book in books: the_dict[author].append(book)
code style
Type | Example |
---|---|
Module | module_name.py |
Package | package_name |
Class | class ClassName(object): |
Exception | class ExceptionName(Exception): |
Function | def function_name(): |
Method | def method_name(self): |
Constant | GLOBAL_CONSTANT_NAME = 1 |
Variable | var_name = 1 |
import 順序
{{ Python 內建的 modules }} \n {{ 第三方 modules }} \n {{ 本地 modules }}
不要使用隱性import
from animals.dogs import base
import base
Ref:
沒有留言:
張貼留言