@Pythonetc 2018年10月

图片

这是来自@pythonetc feed的第五种Python技巧和编程。

先前的选择:



分隔符-


每个不错的命令行实用程序都应接受以下形式的参数:选项(例如-h--help ),带有参数的选项( --log-level 2 )或位置参数( cp file1 file2 )。

选项与位置参数的不同之处在于,开头有一个或两个破折号。 当位置参数以破折号开头时,会出现问题:如果要删除名为-rf的文件,则rm -rf命令将无济于事。

一种简单的解决方法是使用两个破折号作为分隔符。 后面的参数-不被视为选项:

$ echo test > -rf $ cat -rf cat: invalid option -- 'r' Try 'cat --help' for more information. $ cat -- -rf test $ rm -- -rf $ cat -- -rf cat: -rf: No such file or directory 

开箱即用的argparse模块支持两个破折号。

排序稳定性


Python中的标准排序功能强大, 排序后的函数不会更改相等对象的顺序:

 In : a = [2, -1, 0, 1, -2] In : sorted(a, key=lambda x: x**2) Out: [0, -1, 1, 2, -2] 

最小最大函数也与排序一致 max的工作方式类似于sorted(a,reverse = True)[0] ,而min的工作方式类似于sorted( a)[0] 。 这意味着两个函数都返回最左边的答案:

 In : max([2, -2], key=lambda x: x**2) Out: 2 In : max([-2, 2], key=lambda x: x**2) Out: -2 In : min([2, -2], key=lambda x: x**2) Out: 2 In : min([-2, 2], key=lambda x: x**2) Out: -2 

缓存默认参数


在新手python专家中,最常见的错误也许是将可变对象指定为默认函数的参数。 在函数调用之间分隔此对象会导致最奇怪的结果:

 def append_length(lst=[]): lst.append(len(lst)) return lst print(append_length([1, 2])) # [1, 2, 2] print(append_length()) # [0] print(append_length()) # [0, 1] 

但是,如果使用对象创建共享缓存,则这种共享甚至将非常有用:

 def fact(x, cache={0: 1}): if x not in cache: cache[x] = x * fact(x - 1) return cache[x] print(fact(5)) 

在此示例中,我们将计算出的阶乘值放入默认参数值内。 这些值甚至可以提取:

 >>> fact.__defaults__ ({0: 1, 1: 1, 2: 2, 3: 6, 4: 24, 5: 120},) 

使用FS


您可以使用os.path模块处理文件系统路径。 该模块包含许多函数,这些函数将字符串视为文件路径,并对它们执行各种有用的操作,例如串联:

 >>> import os.path >>> os.path.join('/usr', 'local') '/usr/local' >>> os.path.dirname('/var/log') '/var' 

从3.4版开始,Python包含pathlib模块,该模块提供了一种面向对象的方法:

 >>> from pathlib import Path >>> Path('/usr') / Path('local') PosixPath('/usr/local') >>> Path('/usr') / 'local' PosixPath('/usr/local') >>> Path('/var/log').parent PosixPath('/var') >>> Path('/var/log').parent.name 'var' 

被叫对象


在Python中,不仅可以通过创建函数(使用语法deflambda )来创建可调用对象。 如果对象具有__call__方法,则该对象可被调用:

 class Truncater: def __init__(self, length): self._length = length def __call__(self, s): return s[0:self._length] print(Truncater(4)('abcdabcd')) # abcd 

由于装饰器本质上是一个高阶函数,因此它也可以由被调用对象而不是函数来表示:

 class cached: def __init__(self, func): self._func = func self._cache = {} def __call__(self, arg): if arg not in self._cache: self._cache[arg] = self._func(arg) return self._cache[arg] @cached def sqr(x): return x * x 

Source: https://habr.com/ru/post/zh-CN429186/


All Articles