如果第一個學習的不是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

沒有留言:
張貼留言