你須要知道的、有用的 Python 功能和特色

在使用Python多年之後,我偶然發現了一些咱們過去不知道的功能和特性。一些能夠說是很是有用,但卻沒有充分利用。考慮到這一點,我編輯了一些的你應該瞭解的Pyghon功能特點。html

帶任意數量參數的函數

你可能已經知道了Python容許你定義可選參數。但還有一個方法,能夠定義函數任意數量的參數。python

首先,看下面是一個只定義可選參數的例子數據庫

01 def function(arg1="",arg2=""):
02     print "arg1: {0}".format(arg1)
03     print "arg2: {0}".format(arg2)
04   
05 function("Hello""World")
06 # prints args1: Hello
07 # prints args2: World
08   
09 function()
10 # prints args1:
11 # prints args2:

 

如今,讓咱們看看怎麼定義一個能夠接受任意參數的函數。咱們利用元組來實現。json

01 def foo(*args): # just use "*" to collect all remaining 
arguments into a tuple
02     numargs = len(args)
03     print "Number of arguments: {0}".format(numargs)
04     for i, x in enumerate(args):
05         print "Argument {0} is: {1}".format(i,x)
06   
07 foo()
08 # Number of arguments: 0
09   
10 foo("hello")
11 # Number of arguments: 1
12 # Argument 0 is: hello
13   
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

1 import glob
2   
3 # get all py files
4 files = glob.glob('*.py')
5 print files
6   
7 # Output
8 # ['arg.py', 'g.py', 'shut.py', 'test.py']

 

你能夠像下面這樣查找多個文件類型:數組

01 import itertools as it, glob
02   
03 def multiple_file_types(*patterns):
04     return it.chain.from_iterable(glob.glob(pattern) for pattern in patterns)
05   
06 for filename in multiple_file_types("*.txt""*.py"): # add as many filetype arguements
07     print filename
08   
09 # output
10 #=========#
11 # test.txt
12 # arg.py
13 # g.py
14 # shut.py
15 # test.py

 

若是你想獲得每一個文件的絕對路徑,你能夠在返回值上調用realpath()函數:app

01 import itertools as it, glob, os
02   
03 def multiple_file_types(*patterns):
04     return it.chain.from_iterable(glob.glob(pattern) for pattern in patterns)
05   
06 for filename in multiple_file_types("*.txt""*.py"): # add as many filetype arguements
07     realpath = os.path.realpath(filename)
08     print realpath
09   
10 # output
11 #=========#
12 # C:\xxx\pyfunc\test.txt
13 # C:\xxx\pyfunc\arg.py
14 # C:\xxx\pyfunc\g.py
15 # C:\xxx\pyfunc\shut.py
16 # C:\xxx\pyfunc\test.py
 

調試

下面的例子使用inspect模塊。該模塊用於調試目的時是很是有用的,它的功能遠比這裏描述的要多。函數

這篇文章不會覆蓋這個模塊的每一個細節,但會展現給你一些用例。ui

01 import logging, inspect
02   
03 logging.basicConfig(level=logging.INFO,
04     format='%(asctime)s %(levelname)-8s %(filename)s:%(lineno)-4d: %(message)s',
05     datefmt='%m-%d %H:%M',
06     )
07 logging.debug('A debug message')
08 logging.info('Some information')
09 logging.warning('A shot across the bow')
10   
11 def test():
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)
15   
16 test()
17   
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

1 import uuid
2 result = uuid.uuid1()
3 print result
4   
5 # output => various attempts
6 # 9e177ec0-65b6-11e3-b2d0-e4d53dfcf61b
7 # be57b880-65b6-11e3-a04d-e4d53dfcf61b
8 # c3b2b90f-65b6-11e3-8c86-e4d53dfcf61b

 

你可能會注意到,即便字符串是惟一的,但它們後邊的幾個字符看起來很類似。這是由於生成的字符串與電腦的MAC地址是相聯繫的。

爲了減小重複的狀況,你可使用這兩個函數。

01 import hmac,hashlib
02 key='1'
03 data='a'
04 print hmac.new(key, data, hashlib.sha256).hexdigest()
05   
06 = hashlib.sha1()
07 m.update("The quick brown fox jumps over the lazy dog")
08 print m.hexdigest()
09   
10 # c6e693d0b35805080632bc2469e1154a8d1072a86557778c27a01329630f8917
11 # 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12
 

序列化

你曾經須要將一個複雜的變量存儲在數據庫或文本文件中吧?你不須要想一個奇特的方法將數組或對象格轉化爲式化字符串,由於Python已經提供了此功能。

01 import pickle
02   
03 variable = ['hello'42, [1,'two'],'apple']
04   
05 # serialize content
06 file = open('serial.txt','w')
07 serialized_obj = pickle.dumps(variable)
08 file.write(serialized_obj)
09 file.close()
10   
11 # unserialize to produce original content
12 target = open('serial.txt','r')
13 myObj = pickle.load(target)
14   
15 print serialized_obj
16 print myObj
17   
18 #output
19 # (lp0
20 # S'hello'
21 # p1
22 # aI42
23 # a(lp2
24 # I1
25 # aS'two'
26 # p3
27 # aaS'apple'
28 # p4
29 # a.
30 # ['hello', 42, [1, 'two'], 'apple']

 

這是一個原生的Python序列化方法。然而近幾年來JSON變得流行起來,Python添加了對它的支持。如今你可使用JSON來編解碼。

01 import json
02   
03 variable = ['hello'42, [1,'two'],'apple']
04 print "Original {0} - {1}".format(variable,type(variable))
05   
06 # encoding
07 encode = json.dumps(variable)
08 print "Encoded {0} - {1}".format(encode,type(encode))
09   
10 #deccoding
11 decoded = json.loads(encode)
12 print "Decoded {0} - {1}".format(decoded,type(decoded))
13   
14 # output
15   
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中能夠壓縮長字符,不涉及任何檔案文件。

01 import zlib
02   
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. """
19   
20 print "Original Size: {0}".format(len(string))
21   
22 compressed = zlib.compress(string)
23 print "Compressed Size: {0}".format(len(compressed))
24   
25 decompressed = zlib.decompress(compressed)
26 print "Decompressed Size: {0}".format(len(decompressed))
27   
28 # output
29   
30 # Original Size: 1022
31 # Compressed Size: 423
32 # Decompressed Size: 1022

 

 

註冊Shutdown函數

有可模塊叫atexit,它可讓你在腳本運行完後立馬執行一些代碼。

假如你想在腳本執行結束時測量一些基準數據,好比運行了多長時間:

01 import atexit
02 import time
03 import math
04   
05 def microtime(get_as_float = False) :
06     if get_as_float:
07         return time.time()
08     else:
09         return '%f %d' % math.modf(time.time())
10 start_time = microtime(False)
11 atexit.register(start_time)
12   
13 def shutdown():
14     global start_time
15     print "Execution took: {0} seconds".format(start_time)
16   
17 atexit.register(shutdown)
18   
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()時,你的代碼都將執行,不論腳本由於什麼緣由中止運行

相關文章
相關標籤/搜索