在使用Python多年以后,我偶然发现了一些我们过去不知道的功能和特性。一些可以说是非常有用,但却没有充分利用。考虑到这一点,我编辑了一些的你应该了解的Pyghon功能特色。 带任意数量参数的函数你可能已经知道了Python允许你定义可选参数。但还有一个方法,可以定义函数任意数量的参数。 首先,看下面是一个只定义可选参数的例子 01 | def function(arg1="",arg2=""): |
02 | print "arg1: {0}".format(arg1) |
03 | print "arg2: {0}".format(arg2) |
05 | function("Hello", "World") |
现在,让我们看看怎么定义一个可以接受任意参数的函数。我们利用元组来实现。 03 | print "Number of arguments: {0}".format(numargs) |
04 | for i, x in enumerate(args): |
05 | print "Argument {0} is: {1}".format(i,x) |
14 | foo("hello","World","Again") |
使用Glob()查找文件
大多Python函数有着长且具有描述性的名字。但是命名为glob()的函数你可能不知道它是干什么的除非你从别处已经熟悉它了。 它像是一个更强大版本的listdir()函数。它可以让你通过使用模式匹配来搜索文件。 4 | files = glob.glob('*.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"): |
如果你想得到每个文件的绝对路径,你可以在返回值上调用realpath()函数: 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"): |
07 | realpath = os.path.realpath(filename) |
调试下面的例子使用inspect模块。该模块用于调试目的时是非常有用的,它的功能远比这里描述的要多。 这篇文章不会覆盖这个模块的每个细节,但会展示给你一些用例。 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) |
生成唯一ID在有些情况下你需要生成一个唯一的字符串。我看到很多人使用md5()函数来达到此目的,但它确实不是以此为目的。 其实有一个名为uuid()的Python函数是用于这个目的的。 你可能会注意到,即使字符串是唯一的,但它们后边的几个字符看起来很相似。这是因为生成的字符串与电脑的MAC地址是相联系的。 为了减少重复的情况,你可以使用这两个函数。 04 | print hmac.new(key, data, hashlib.sha256).hexdigest() |
07 | m.update("The quick brown fox jumps over the lazy dog") |
序列化
你曾经需要将一个复杂的变量存储在数据库或文本文件中吧?你不需要想一个奇特的方法将数组或对象格转化为式化字符串,因为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) |
12 | target = open('serial.txt','r') |
13 | myObj = pickle.load(target) |
这是一个原生的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)) |
这样更紧凑,而且最重要的是这样与JavaScript和许多其他语言兼容。然而对于复杂的对象,其中的一些信息可能丢失。
压缩字符当谈起压缩时我们通常想到文件,比如ZIP结构。在Python中可以压缩长字符,不涉及任何档案文件。 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)) |
注册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) |
打眼看来很简单。只需要将代码添加到脚本的最底层,它将在脚本结束前运行。但如果脚本中有一个致命错误或者脚本被用户终止,它可能就不运行了。 当你使用atexit.register()时,你的代码都将执行,不论脚本因为什么原因停止运行。 结论你是否意识到那些不是广为人知Python特性很有用?请在评论处与我们分享。谢谢你的阅读!
|