如果第一個學習的不是Python語言, 常常依照其他語言的語法來寫Python, 這裡紀錄常被遺忘但卻重要的寫法, 節錄自書本Python神乎其技
assert
後面搭配Bool運算, 來檢查該運算式是否符合條件, 若無則觸發exception
1. assert為內部檢查輔助除錯工具
2. 幫助找bug, 不可使用在業務邏輯上, 不可作為處理執行期間的錯誤的機制
3. 直譯器加以設定後會關閉assert, 要小心bug產生
後面搭配Bool運算, 來檢查該運算式是否符合條件, 若無則觸發exception
1. assert為內部檢查輔助除錯工具
2. 幫助找bug, 不可使用在業務邏輯上, 不可作為處理執行期間的錯誤的機制
3. 直譯器加以設定後會關閉assert, 要小心bug產生
def apply_discount(product, discount): price = int(product['price'] & (1.0 - discount)) assert 0 <= price <= product['price'] return price
在串列.字典.集合每一行末端都加入逗點
1.可以在版本管理中看出修改哪一行
names = ['a', 'b', 'c',]
底線.雙底線
1._var : 命名慣例, 提醒其他協作者此變數要注意不要給scope外的使用, 但直譯器不會去管
2.__var : private
3.__var__ : 系統保留特殊用法
4._ : 暫時無使用變數, 或尚未命名變數
5.var_ : 區隔系統保留字與自己的變數 EX: class_
字串格式化
如果格式由使用者提供使用樣板字串, python3.6+使用字串差值, 不然用.format
# python3.6以前 _name = 'charles' 'Hello, {name}'.formate(name=_name) # python3.6+ f'Hello, {name}' # 格式由使用者提供使用template from string import Template t = Template('Hello', $name!) t.substitute(name=_name) >>'Hello, charles'
函式
1.在pythoon裡所有東西都是物件, 包含函式, 可指派給變數, 放在資料結構當中, 作為傳入函式的參數與回傳
2.包在函式內部的子函式可以記住父函數的參數值, 直接拿來使用稱, 稱之為閉包, lexical closure
3.Decorator
裝飾器能讓你在被裝飾的函式之前與之後執行裝飾器的程式, 延伸函式的呼叫行為, 將共用的功能獨立出來, 不用修改函式
, 加上去即可使用 ,不限制一個數量, 內建裝飾器如@property, @staticmethod各有不同功能:
使用場合:
- 紀錄log
- 管控權限與身份認證
- 在呼叫API時很適合搭配使用
- 在沒明確定義參數數量時使用 *args : 回傳tuple, **kwargs : 回傳Dictionary
import functools def upercase(func): functools.wraps(func) def wrapper(*args, **kwargs): print args print kwargs return func().upper() return wrapper @uppercase def hi('boy',name='Charles'): return 'Hello' >>> hi() ('boy') {name : 'Charles'} 'HELLO'*,** 也可用來將參數拆箱
tuple = (1, 2, 3) list = [1, 2, 3] def print_vector(x, y, x): print (x, y, x) >>> print_vector(*tuple) 1,2,3 >>> print_vector(*list) 1,2,3
Class
__repr__來說明物件, 建議每個物件都要有__repr__, 用來明確表明物件的用途
# python 3.6 class Car: def __init__(delf, color, mileage): self.color = color self.mileage = mileage def __repr__(self): return (f{self.__class__.__name__} ('f'{self.color!r}, {self.mileage!r})') def __str__(self): return f'a {self.color car}' >>> my_car = Car('yellow',100) >>> repr(my_car) 'Car('yellow',100)' >>> str(my_car) 'a yellow car'
staticmethod,classmethod說明
for python2.7
class calc:
@staticmethod
def add(x,y):
answer = x + y
print(answer)
#call staticmethod add directly
#without declaring instance and accessing class variables
calc.add(5,7)
Or, Use
instance method
if you need to call other instance methods or use anything inside classclass calc:
def add(self,x,y):
print(self._add(x,y)) #call another instance method _add
def _add(self,x,y):
return x+y
#declare instance
c = calc()
#call instance method add
c.add(5,7)
Additionally, Use
classmethod
if you need to use class variables but without declaring instanceclass calc:
some_val = 1
@classmethod
def add_plus_one(cls,x,y):
answer = x + y + cls.some_val #access class variable
print(answer)
#call classmethod add_plus_one dircetly
#without declaring instance but accessing class variables
calc.add_plus_one(5,7)
自訂Exception
也可以定義好階層一次捕捉特定例外
class BaseValidationError(ValueError) pass class NameTooShortError(BaseValidationError) pass class NameTooLongError(BaseValidationError) pass def validate(name): if len(name) < 10: raise NameTooShortError(name) if len(name) >= 20: raise NameTooLongError(name) try: validate(name) catch BaseValidationError as err: handle_error(err)使用抽象於父類別避免錯誤
from abc import ABCMeta, abstractmethod class Base(metaclass=ABCMeta): @abstractmethod def foo(self): pass @abstractmethod def bar(self): pass class Concrete(Base): def foo(self): pass >>> c = Concrete() TyepError: "無法實體化帶有抽象方法bar的抽象類別Concrete"namedtuple代替tuple,dict或只當成存資料的class
不可變更資料集, 並且比一般透過必須透過index的資料集多了命名, 又比class使用更少的記憶體
from collections import namedtuple Car = namedtuple('Car',{ 'color', 'age', ]} >>> my_car = Car(color='red', age=10) >>> my_car.color 'red' >>> my_car._asdict() OrderedDict([('color','red'),('age',10)]) >>> json.dumps(my_car._asdict()) '{"color":"red","age":10}' # 新增欄位 >>> ElectricCar = namedtuple('ElectricCar', Car._fields + ('charge',) >>> ElectricCar('red', 12, 100) # 產生新的namedtuple >>> my_car._replace(color='blue') >>> my_car._make(['yellow',999]) Car(color='yellow', age=999)資料結構
- collections.nametuple 最建議使用
- collections.OrderedDict 記住key的插入順序
- collections.defaultDict 找不到key會回傳預設值
- collections.ChainMap 把多個字典組合起來逐一搜尋
- types.MappingProxyType 製作唯讀字典
- set 唯一的集合
- frozenset 不可變更的set
- collections.Count
from collections import Counter counter = Counter() dict_a = {'aa':1, 'bb':2} dict_b = {'aa':1, 'cc':2} counter.update(dict_a) counter.update(dict_b) >>counter Counter({'aa':2, 'bb':2, 'cc':2}) >>len(counter) 3 >>sum(counter) 6
- 不要用list來做collections.deque的事情(LIFO)
- queue.PriorityQueue比list再sort好, 有新值插入不用重新排序
from queue import PriorityQueue q = PriorityQueue() q.put((2, 'b')) q.put((1, 'a')) q.put((3, 'c')) while not q.empty() next_item = q.get() print(next_item) >> (1, 'a') (2, 'b') (3, 'c')
迴圈
- 串列生成式
>>> [x * x for x in range(10) if x % 2 == 0] [0, 4, 16, 36, 64] >>> {x * x for x in range(-9, 10)} set({64,1,36,0,49,9,16,81,25,4}) >>> {x:x * x for x in range(5)} {0:0, 1:1, 2:4, 3:9, 4:16}
- 若須使用特殊迭代功能, 可以自訂迭代器, 依照需求用不同方式撰寫
字典技巧
- 排序字典
>>> sorted(dict_a.items(), key=lambda x: x[1], reverse=True) [('d',4),('c',3),('b',2),('a',1)]
- 字典合併-override重複依照左到右
# in Python 3.5+ >>> x = {'a': 1, 'b': 2} >>> y = {'b': 3, 'c': 4} >>> z = {**x, **y} >>> z {'c': 4, 'a': 1, 'b': 3} # In Python 2.x >>> z = dict(x, **y) >>> z {'a': 1, 'c': 4, 'b': 3}
- 用字典當switch/case
operator_dict ={ 'add': lambda: operator.add(x , y), 'sub': lambda: operator.sub(x , y), 'mul': lambda: operator.mul(x , y), 'div': lambda: operator.div(x , y), 'mod': lambda: operator.mod(x , y), } def dispatch_dict(operator, x, y): return operator_dict.get(operator, lambda: None)()
- print dictionary, pprint可印出集合
>>> import json >>> json.dumps(dict, indent=4, sort_keys=True) { "a":11, "b":22 } >>> import pprint >>> pprint.pprint(dict) {"a":11, "b":22, "c": set([1, 2, 3])}
Ref:
Dan Bader著,江志良譯 , Python神乎其技 , 旗標
dbader.org, Dan Bader
沒有留言:
張貼留言