Python編碼紀要

来源:http://www.cnblogs.com/java-wgm/archive/2017/06/26/7083032.html
-Advertisement-
Play Games

Python編碼的一些見解,翻譯節選自http://book.pythontips.com/en/latest/index.html ...



1、map, filter, reduce
1) map(func, input_list)
將函數應用到輸入列表上的每個元素, 如:
input_list = [1, 2, 3, 4, 5]


def pow_elem(x):
"""
將x做乘方運算
:param x:
:return:
"""
return x * x


def multi_x_y(x, y):
return x * y


print map(pow_elem, input_list) # output:[1, 4, 9, 16, 25]

print map(multi_x_y, input_list, input_list) # output:[1, 4, 9, 16, 25]

2) filter(func_or_none, sequence)
過濾篩選出sequence中滿足函數返回True的值,組成新的sequence返回,如:
def is_odd(x):
"""
判斷x是否為奇數
:param x:
:return:
"""
return True if x % 2 > 0 else False

print filter(is_odd, input_list) # output: [1, 3, 5]

3) reduce(function, sequence)
reduce()函數接收的參數和 map()類似,一個函數 f,一個list,但行為和 map()不同,reduce()傳入的函數 f 必須接收兩個參數,reduce()對list的每個元素反覆調用函數f,並返回最終結果值。例如:reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) 等價於((((1+2)+3)+4)+5)
print reduce(lambda x, y: x * y, input_list) # output: 120

2、三元運算
下麵兩種寫法等價:
"Yes" if 2==2 else "No"
("No", "Yes")[2==2]
即:
1) condition_is_true if condition else condition_is_false
2) (if_test_is_false, if_test_is_true)[test]
1)和2)都能實現三元運算, 但是2)較為少見,且不太優雅,同時2)並不是一個短路運算,如下:
5 if True else 5/0 # output: 5
(1/0, 5)[True] # throw exception-> ZeroDivisionError: integer division or modulo by zero

3、裝飾器
1) Python中,我們可以在函數內部定義函數並調用,如:
def hi(name="patty"):
print("now you are inside the hi() function")

def greet():
return "now you are in the greet() function"

def welcome():
return "now you are in the welcome() function"

print(greet())
print(welcome())
print("now you are back in the hi() function")
輸出結果為:
now you are inside the hi() function
now you are in the greet() function
now you are in the welcome() function
now you are back in the hi() function

2) 也可以將內部函數返回,利用外部函數進行調用, 如:
def hi(name="patty"):
def greet():
return "now you are in the greet() function"

def welcome():
return "now you are in the welcome() function"

return greet if name == 'patty' else welcome


print hi() # <function greet at 0x109379a28>
print hi()() # now you are in the greet() function
上述代碼中,hi()調用返回的是一個function對象,從if/else語句中可以判斷出,返回的是greet()函數,當我們調用hi()()時,實際上是調用了內部函數greet()。

3)將函數作為參數傳遞給另一個函數, 如:
def hi():
return "hi patty!"

def doSomethingBeforeHi(func):
print("I am doing some boring work before executing hi()")
print(func())

doSomethingBeforeHi(hi)
輸出結果:
I am doing some boring work before executing hi()
hi patty!
至此, 我們已經實現了一個簡單的裝飾器, 在調用hi()函數之前, 先輸出一行,實際應用中可能是一些預處理操作。實際上,裝飾器的功能就是在你的核心邏輯執行前後,加上一些通用的功能。

4) 簡單裝飾器的實現
def a_new_decorator(a_func):

def wrapTheFunction():
print("I am doing some boring work before executing a_func()")

a_func() # call this function

print("I am doing some boring work after executing a_func()")

return wrapTheFunction

def a_function_requiring_decoration():
print("I am the function which needs some decoration to remove my foul smell")

a_function_requiring_decoration()
#outputs: "I am the function which needs some decoration to remove my foul smell"

a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration)
#now a_function_requiring_decoration is wrapped by wrapTheFunction()

a_function_requiring_decoration()
# I am doing some boring work before executing a_func()
# I am the function which needs some decoration to remove my foul smell
# I am doing some boring work after executing a_func()

5) 註解形式
@a_new_decorator
def b_function_requiring_decoration():
print("I am the another function which needs some decoration to remove my foul smell")

b_function_requiring_decoration()
# I am doing some boring work before executing a_func()
# I am the another function which needs some decoration to remove my foul smell
# I am doing some boring work after executing a_func()
此處@a_new_decorator就等價於a_new_decorator(b_function_requiring_decoration)

6) 獲取name
對於4)中的a_function_requiring_decoration, 我們列印print(a_function_requiring_decoration.__name__) 得到的結果是wrapTheFunction,而實際上我們希望得到的是a_func所對應的a_function_requiring_decoration函數名,Python為我們提供了wraps用來解決這個問題。
from functools import wraps
def a_new_decorator(a_func):
@wraps(a_func)
def wrapTheFunction():
print("I am doing some boring work before executing a_func()")

a_func()

print("I am doing some boring work after executing a_func()")

return wrapTheFunction

7) 裝飾器的一些應用場景
用戶認證
def requires_auth(f):
@wraps(f)
def decorated(*args, **kwargs):
auth = {"username": "patty", "password": "123456"}
if not check_auth(auth['username'], auth['password']):
authenticate()
return f(*args, **kwargs)

def check_auth(username, password):
print "Starting check auth..."
return True if (username == 'patty' and password == '123456') else False


def authenticate():
print "Already authenticate"
return decorated

@requires_auth
def welcome():
return "Welcome patty!"

print welcome()

日誌記錄
def logit(func):
@wraps(func)
def with_logging(*args, **kwargs):
print(func.__name__ + " was called")
return func(*args, **kwargs)
return with_logging

@logit
def addition_func(x):
"""Do some math."""
return x + x


result = addition_func(4)
將會列印:addition_func was called

8)帶參數的裝飾器
from functools import wraps

def logit(logfile='out.log'):
def logging_decorator(func):
@wraps(func)
def wrapped_function(*args, **kwargs):
log_string = func.__name__ + " was called"
print(log_string)
# Open the logfile and append
with open(logfile, 'a') as opened_file:
# Now we log to the specified logfile
opened_file.write(log_string + '\n')
return wrapped_function
return logging_decorator

@logit()
def myfunc1():
pass

myfunc1()
# Output: myfunc1 was called
# A file called out.log now exists, with the above string

@logit(logfile='func2.log')
def myfunc2():
pass

myfunc2()

9) 用類作為裝飾器
import os
class Logit(object):
def __init__(self, log_file):
self.log_file = log_file

def __call__(self, func):
with open(self.log_file, 'a') as fout:
log_msg = func.__name__ + " was called"
fout.write(log_msg)
fout.write(os.linesep)
# Now, send a notification
self.notify()

def notify(self):
# logit only logs, no more
pass

class EmailLogit(Logit):
'''
A logit implementation for sending emails to admins
when the function is called.
'''
def __init__(self, log_file, email='[email protected]'):
self.email = email
super(EmailLogit, self).__init__(log_file)

def notify(self):
# Send an email to self.email
# Will not be implemented here
with open(self.log_file, 'a') as f:
f.write("Do Something....")
f.write(os.linesep)
f.write("Email has send to " + self.email)
f.write(os.linesep)


@Logit("log1.txt")
def myfunc3():
pass

@EmailLogit("log2.txt")
def myfunc4():
pass
用類作為裝飾器,我們的代碼看上去更簡潔, 而且還可以通過繼承的方式,實現功能的個性化和復用。

4、可變類型
Python中的可變類型包括列表和字典,這些對象中的元素是可改變的,如
>>> foo = ['hi']
>>> foo += ['patty']
>>> foo
['hi', 'patty']
>>> foo[0]='hello'
>>> foo
['hello', 'patty']

>>> fdict = {"name":"patty"}
>>> fdict.update({"age":"23"})
>>> fdict
{'age': '23', 'name': 'patty'}
>>> fdict.update({"age":"25"})
>>> fdict
{'age': '25', 'name': 'patty'}

在方法中,若傳入的參數採用可變類型並賦預設值,要註意會出現以下情況:
>>> def add_to(num, target=[]):
... target.append(num)
... return target
...
>>> add_to(1)
[1]
>>> add_to(2)
[1, 2]
>>> add_to(3)
[1, 2, 3]
這是因為, 預設參數在方法被定義時進行計算,而不是每次調用時再計算一次。因此, 為了避免出現上述情況, 當我們期待每次方法被調用時,以一個新的空列表進行計算的時候,可採取如下寫法:
>>> def add_to(num, target=None):
... if target is None:
... target = []
... target.append(num)
... return target
...
>>> add_to(1)
[1]
>>> add_to(2)
[2]

5、淺拷貝和深拷貝
Python中,對象的賦值,拷貝(深/淺拷貝)之間是有差異的,如果使用的時候不註意,就可能產生意外的結果。
1) Python中預設是淺拷貝方式
>>> foo = ['hi']
>>> bar = foo
>>> id(foo)
4458211232
>>> id(bar)
4458211232
>>> bar.append("patty")
>>> bar
['hi', 'patty']
>>> foo
['hi', 'patty']
註意:id(foo)==id(bar),說明foo和bar引用的是同一個對象, 當通過bar引用對list進行append操作時, 由於指向的是同一塊記憶體空間,foo的輸出與bar是一致的。

2) 深拷貝
>>> foo
['hi', {'age': 20, 'name': 'patty'}]
>>> import copy
>>> slow = copy.deepcopy(foo)
>>> slow
['hi', {'age': 20, 'name': 'patty'}]
>>> slow[0]='hello'
>>> slow
['hello', {'age': 20, 'name': 'patty'}]
>>> foo
['hi', {'age': 20, 'name': 'patty'}]
註意: 由於slow是對foo的深拷貝,實際上是在記憶體中新開了一片空間,將foo對象所引用的內容複製到新的記憶體空間中,因此當對slow對像所引用的內容進行update操作後,更改只體現在slow對象的引用上,而foo對象所引用的內容並沒有發生改變。

6、集合Collection
1) defaultdict
對於普通的dict,若是獲取不存在的key,會引發KeyError錯誤,如下:
some_dict = {}
some_dict['colours']['favourite'] = "yellow"
# Raises KeyError: 'colours'
但是通過defaultdict,我們可以避免這種情況的發生, 如下:
import collections
import json
tree = lambda: collections.defaultdict(tree)
some_dict = tree()
some_dict['colours']['favourite'] = "yellow"
print json.dumps(some_dict)
# Works fine, output: {"colours": {"favourite": "yellow"}}

2) OrderedDict
OrderedDict能夠按照我們定義字典時的key順序列印輸出字典,改變value的值不會改變key的順序, 但是,對key進行刪除,重新插入後,key會重新排序到dict的尾部。
from collections import OrderedDict

colours = OrderedDict([("Red", 198), ("Green", 170), ("Blue", 160)])
for key, value in colours.items():
print(key, value)

3)Counter
利用Counter,可以統計特定項的出現次數,如:
from collections import Counter

colours = (
('Yasoob', 'Yellow'),
('Ali', 'Blue'),
('Arham', 'Green'),
('Ali', 'Black'),
('Yasoob', 'Red'),
('Ahmed', 'Silver'),
)

favs = Counter(name for name, colour in colours)
print(favs)
# Counter({'Yasoob': 2, 'Ali': 2, 'Arham': 1, 'Ahmed': 1})

4)deque
deque是一個雙端隊列,可在頭尾分別進行插入,刪除操作, 如下:
from collections import deque
queue_d = deque()
queue_d.append(1)
queue_d.append(2)
print queue_d # deque([1, 2])
queue_d.appendleft(3)
print queue_d # deque([3, 1, 2])

queue_d.pop()
print queue_d # deque([3, 1])
queue_d.popleft()
print queue_d # deque([1])

deque可以設置隊列的最大長度,當元素數目超過最大長度時,會從當前帶插入方向的反方向刪除相應數目的元素,如下:
queue_c = deque(maxlen=5, iterable=[2, 4, 6])
queue_c.extend([7, 8])
print queue_c # deque([2, 4, 6, 7, 8], maxlen=5)
queue_c.extend([10, 12])
print(queue_c) # deque([6, 7, 8, 10, 12], maxlen=5)
queue_c.extendleft([18])
print(queue_c) # deque([18, 6, 7, 8, 10], maxlen=5)

5)nametuple
tuple是不可變的列表,不可以對tuple中的元素重新賦值,我們只能通過index去訪問tuple中的元素。nametuple可看做不可變的字典,可通過name去訪問tuple中的元素。如:
from collections import namedtuple

Animal = namedtuple('Animal', 'name age type')
perry = Animal(name="perry", age=31, type="cat")

print(perry)
# Output: Animal(name='perry', age=31, type='cat')

print(perry.name)
# Output: 'perry'

print(perry[0])
# Output: 'perry'

print(perry._asdict())
# Output: OrderedDict([('name', 'perry'), ('age', 31), ('type', 'cat')])

7、Object introspection
1) dir: 列舉該對象的所有方法
2)type: 返回對象的類型
3)id: 返回對象的id

8、生成器
1)list
>>> squared = [x**2 for x in range(10)]
>>> squared
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
2) dict
{v: k for k, v in some_dict.items()}
3) set
>>> squared = {x**2 for x in range(10)}
>>> squared
set([0, 1, 4, 81, 64, 9, 16, 49, 25, 36])

9、異常處理
try:
print('I am sure no exception is going to occur!')
except Exception:
print('exception')
else:
# any code that should only run if no exception occurs in the try,
# but for which exceptions should NOT be caught
print('This would only run if no exception occurs. And an error here '
'would NOT be caught.')
finally:
print('This would be printed in every case.')

# Output: I am sure no exception is going to occur!
# This would only run if no exception occurs.
# This would be printed in every case.
else中的語句會在finally之前執行。

10、內置方法
a_list = [[1, 2], [3, 4], [5, 6]]
print(list(itertools.chain.from_iterable(a_list)))
# Output: [1, 2, 3, 4, 5, 6]

# or
print(list(itertools.chain(*a_list)))
# Output: [1, 2, 3, 4, 5, 6]


class A(object):
def __init__(self, a, b, c, d, e, f):
self.__dict__.update({k: v for k, v in locals().items() if k != 'self'})

11、for-else語句
for語句的正常結束方式有兩種:一是在滿足特定條件的情況下break跳出迴圈,二是所有條件迴圈結束。 for-else中的else語句只有在所有條件都經過判斷然後正常結束for迴圈的情況下,才被執行,如下:
for x in range(1, 10, 2):
if x % 2 == 0:
print "found even of %d"%x
break
else:
print "not foud even"
# output: not foud even

12、相容Python 2+和Python 3+
1) 利用 __future__模塊在Python 2+的環境中引用Python 3+的模塊
2)相容的模塊導入方式
try:
import urllib.request as urllib_request # for Python 3
except ImportError:
import urllib2 as urllib_request # for Python 2

 

Reference: http://book.pythontips.com/en/latest/index.html

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1 html_doc = "" 2 sp = BeautifulSoup(html_doc,"html.parser") 3 print(sp.p['class']) 4 #['body','strikeout'] 5 print(sp.p['id']) 6 #zhangsan 7 8 html_d... ...
  • 課程中詳細演示了一個應用從單塊架構到垂直應用架構再到分散式服務架構的演進過程。講解瞭如何在前後端分離的架構下設計RESTful API。最終的系統對外提供REST風格的http服務,內部各個垂直應用通過dubbo共用無狀態的Java服務。整個系統在Web層和服務層都可以無縫的橫向擴展。 ...
  • 抓取內容: 從最好大學網上抓取中國前10的大學排名、大學名稱、總分,並數據格式左對齊。 http://www.zuihaodaxue.cn/zuihaodaxuepaiming2017.html 首先,看下網站的Robots協議,沒有找到相關協議,可以抓取。 http://www.zuihaodax ...
  • var a,f:array[1..10000000] of longint; b,i,j,n,s,x,y:longint;begin read(b,n); for i:=1 to n do a[i]:=0; for i:=1 to n do begin readln(x,y); a[x]:=1-a[ ...
  • 什麼是進程(process)? 程式並不能單獨運行,只有將程式裝載到記憶體中,系統為它分配資源才能運行,而這種執行的程式就稱之為進程。程式和進程的區別就在於,程式是指令的集合,它是進程運行的靜態描述文本;進程是程式的一次執行活動,屬於動態概念。 什麼是線程(thread)? 線程是操作系統能夠進行運算... ...
  • 想知道怎麼用python處理尾碼為".sqlite"的文件,這裡有你想要的答案。 ...
  • /* 標識對象模式 這個模式主要功能就是創建sql語句中的wehre條件字元串的,下麵直接看代碼和註釋: */ namespace woo\mapper; //欄位對象 class Field { protected $name = null; //欄位名稱 protected $operator ... ...
  • 快速排序(簡稱快排)因為其效率較高(平均O(nlogn))經常在筆試題中對其考查。 對於快排的第一步是選取一個“基數”,將會用這個“基數”與其它數進行比較交換。而這個“基數”的選擇將影響到快排的效率如何,但如果為了選擇基數而選擇基數則會本末倒置。例如為了找到最佳基數,則需要在整個待排序列中找到中位數 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...