在使用Python多年之後,我偶然發現了一些咱們過去不知道的功能和特性。一些能夠說是很是有用,但卻沒有充分利用。考慮到這一點,我編輯了一些的你應該瞭解的Pyghon功能特點。html
帶任意數量參數的函數
你可能已經知道了Python容許你定義可選參數。但還有一個方法,能夠定義函數任意數量的參數。python
首先,看下面是一個只定義可選參數的例子數據庫
01 |
def function(arg1 = " ",arg2=" "): |
02 |
print "arg1: {0}" . format (arg1) |
03 |
print "arg2: {0}" . format (arg2) |
05 |
function( "Hello" , "World" ) |
如今,讓咱們看看怎麼定義一個能夠接受任意參數的函數。咱們利用元組來實現。json
01 |
def foo( * args): # just use "*" to collect all remaining arguments into a tuple |
03 |
print "Number of arguments: {0}" . format (numargs) |
04 |
for i, x in enumerate (args): |
05 |
print "Argument {0} is: {1}" . format (i,x) |
08 |
# Number of arguments: 0 |
11 |
# Number of arguments: 1 |
12 |
# Argument 0 is: hello |
14 |
foo( "hello" , "World" , "Again" ) |
15 |
# Number of arguments: 3 |
16 |
# Argument 0 is: hello |
17 |
# Argument 1 is: World |
18 |
# Argument 2 is: Again |
使用Glob()查找文件
大多Python函數有着長且具備描述性的名字。可是命名爲glob()的函數你可能不知道它是幹什麼的除非你從別處已經熟悉它了。
它像是一個更強大版本的listdir()函數。它可讓你經過使用模式匹配來搜索文件。api
4 |
files = glob.glob( '*.py' ) |
8 |
# ['arg.py', 'g.py', 'shut.py', 'test.py'] |
你能夠像下面這樣查找多個文件類型:數組
01 |
import itertools as it, glob |
03 |
def multiple_file_types( * patterns): |
04 |
return it.chain.from_iterable(glob.glob(pattern) for pattern in patterns) |
06 |
for filename in multiple_file_types( "*.txt" , "*.py" ): # add as many filetype arguements |
若是你想獲得每一個文件的絕對路徑,你能夠在返回值上調用realpath()函數:app
01 |
import itertools as it, glob, os |
03 |
def multiple_file_types( * patterns): |
04 |
return it.chain.from_iterable(glob.glob(pattern) for pattern in patterns) |
06 |
for filename in multiple_file_types( "*.txt" , "*.py" ): # add as many filetype arguements |
07 |
realpath = os.path.realpath(filename) |
12 |
# C:\xxx\pyfunc\test.txt |
13 |
# C:\xxx\pyfunc\arg.py |
15 |
# C:\xxx\pyfunc\shut.py |
16 |
# C:\xxx\pyfunc\test.py |
調試
下面的例子使用inspect模塊。該模塊用於調試目的時是很是有用的,它的功能遠比這裏描述的要多。函數
這篇文章不會覆蓋這個模塊的每一個細節,但會展現給你一些用例。ui
01 |
import logging, inspect |
03 |
logging.basicConfig(level = logging.INFO, |
04 |
format = '%(asctime)s %(levelname)-8s %(filename)s:%(lineno)-4d: %(message)s' , |
05 |
datefmt = '%m-%d %H:%M' , |
07 |
logging.debug( 'A debug message' ) |
08 |
logging.info( 'Some information' ) |
09 |
logging.warning( 'A shot across the bow' ) |
12 |
frame,filename,line_number,function_name,lines,index = \ |
13 |
inspect.getouterframes(inspect.currentframe())[ 1 ] |
14 |
print (frame,filename,line_number,function_name,lines,index) |
18 |
# Should print the following (with current date/time of course) |
19 |
#10-19 19:57 INFO test.py:9 : Some information |
20 |
#10-19 19:57 WARNING test.py:10 : A shot across the bow |
21 |
#(, 'C:/xxx/pyfunc/magic.py', 16, '', ['test()\n'], 0) |
生成惟一ID
在有些狀況下你須要生成一個惟一的字符串。我看到不少人使用md5()函數來達到此目的,但它確實不是以此爲目的。
其實有一個名爲uuid()的Python函數是用於這個目的的。spa
5 |
# output => various attempts |
6 |
# 9e177ec0-65b6-11e3-b2d0-e4d53dfcf61b |
7 |
# be57b880-65b6-11e3-a04d-e4d53dfcf61b |
8 |
# c3b2b90f-65b6-11e3-8c86-e4d53dfcf61b |
你可能會注意到,即便字符串是惟一的,但它們後邊的幾個字符看起來很類似。這是由於生成的字符串與電腦的MAC地址是相聯繫的。
爲了減小重複的狀況,你可使用這兩個函數。
04 |
print hmac.new(key, data, hashlib.sha256).hexdigest() |
07 |
m.update( "The quick brown fox jumps over the lazy dog" ) |
10 |
# c6e693d0b35805080632bc2469e1154a8d1072a86557778c27a01329630f8917 |
11 |
# 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 |
序列化
你曾經須要將一個複雜的變量存儲在數據庫或文本文件中吧?你不須要想一個奇特的方法將數組或對象格轉化爲式化字符串,由於Python已經提供了此功能。
03 |
variable = [ 'hello' , 42 , [ 1 , 'two' ], 'apple' ] |
06 |
file = open ( 'serial.txt' , 'w' ) |
07 |
serialized_obj = pickle.dumps(variable) |
08 |
file .write(serialized_obj) |
11 |
# unserialize to produce original content |
12 |
target = open ( 'serial.txt' , 'r' ) |
13 |
myObj = pickle.load(target) |
30 |
# ['hello', 42, [1, 'two'], 'apple'] |
這是一個原生的Python序列化方法。然而近幾年來JSON變得流行起來,Python添加了對它的支持。如今你可使用JSON來編解碼。
03 |
variable = [ 'hello' , 42 , [ 1 , 'two' ], 'apple' ] |
04 |
print "Original {0} - {1}" . format (variable, type (variable)) |
07 |
encode = json.dumps(variable) |
08 |
print "Encoded {0} - {1}" . format (encode, type (encode)) |
11 |
decoded = json.loads(encode) |
12 |
print "Decoded {0} - {1}" . format (decoded, type (decoded)) |
16 |
# Original ['hello', 42, [1, 'two'], 'apple'] - <type 'list'="" style="word-wrap: break-word;"> |
17 |
# Encoded ["hello", 42, [1, "two"], "apple"] - <type 'str'="" style="word-wrap: break-word;"> |
18 |
# Decoded [u'hello', 42, [1, u'two'], u'apple'] - <type 'list'="" style="word-wrap: break-word;"> |
這樣更緊湊,並且最重要的是這樣與JavaScript和許多其餘語言兼容。然而對於複雜的對象,其中的一些信息可能丟失。
壓縮字符
當談起壓縮時咱們一般想到文件,好比ZIP結構。在Python中能夠壓縮長字符,不涉及任何檔案文件。
03 |
string = """ Lorem ipsum dolor sit amet, consectetur |
04 |
adipiscing elit. Nunc ut elit id mi ultricies |
05 |
adipiscing. Nulla facilisi. Praesent pulvinar, |
06 |
sapien vel feugiat vestibulum, nulla dui pretium orci, |
07 |
non ultricies elit lacus quis ante. Lorem ipsum dolor |
08 |
sit amet, consectetur adipiscing elit. Aliquam |
09 |
pretium ullamcorper urna quis iaculis. Etiam ac massa |
10 |
sed turpis tempor luctus. Curabitur sed nibh eu elit |
11 |
mollis congue. Praesent ipsum diam, consectetur vitae |
12 |
ornare a, aliquam a nunc. In id magna pellentesque |
13 |
tellus posuere adipiscing. Sed non mi metus, at lacinia |
14 |
augue. Sed magna nisi, ornare in mollis in, mollis |
15 |
sed nunc. Etiam at justo in leo congue mollis. |
16 |
Nullam in neque eget metus hendrerit scelerisque |
17 |
eu non enim. Ut malesuada lacus eu nulla bibendum |
18 |
id euismod urna sodales. """ |
20 |
print "Original Size: {0}" . format ( len (string)) |
22 |
compressed = zlib.compress(string) |
23 |
print "Compressed Size: {0}" . format ( len (compressed)) |
25 |
decompressed = zlib.decompress(compressed) |
26 |
print "Decompressed Size: {0}" . format ( len (decompressed)) |
31 |
# Compressed Size: 423 |
32 |
# Decompressed Size: 1022 |
註冊Shutdown函數
有可模塊叫atexit,它可讓你在腳本運行完後立馬執行一些代碼。
假如你想在腳本執行結束時測量一些基準數據,好比運行了多長時間:
05 |
def microtime(get_as_float = False ) : |
09 |
return '%f %d' % math.modf(time.time()) |
10 |
start_time = microtime( False ) |
11 |
atexit.register(start_time) |
15 |
print "Execution took: {0} seconds" . format (start_time) |
17 |
atexit.register(shutdown) |
19 |
# Execution took: 0.297000 1387135607 seconds |
20 |
# Error in atexit._run_exitfuncs: |
21 |
# Traceback (most recent call last): |
22 |
# File "C:\Python27\lib\atexit.py", line 24, in _run_exitfuncs |
23 |
# func(*targs, **kargs) |
24 |
# TypeError: 'str' object is not callable |
25 |
# Error in sys.exitfunc: |
26 |
# Traceback (most recent call last): |
27 |
# File "C:\Python27\lib\atexit.py", line 24, in _run_exitfuncs |
28 |
# func(*targs, **kargs) |
29 |
# TypeError: 'str' object is not callable |
打眼看來很簡單。只須要將代碼添加到腳本的最底層,它將在腳本結束前運行。但若是腳本中有一個致命錯誤或者腳本被用戶終止,它可能就不運行了。
當你使用atexit.register()時,你的代碼都將執行,不論腳本由於什麼緣由中止運行