📜 ⬆️ ⬇️

Selection @pythonetc, October 2018

image

This is the fifth collection of tips on Python and programming from my author’s @pythonetc channel.

Previous selections:
')


Separator --


Each decent command-line utility should take arguments in the form of options (for example, -h or --help ), options with parameters ( --log-level 2 ), or positional parameters ( cp file1 file2 ).

Options differ from positional parameters by having one or two dashes at the beginning. When positional arguments begin with a dash, problems arise: if you want to delete a file named -rf , the rm -rf command will not help you with this.

A simple way to get out of the situation is to use two dashes as a delimiter. Arguments after are not considered options:

$ 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 

Two dashes are supported by the argparse module out of the box.

Sorting stability


Standard sorting in Python is robust, the sorted function does not change the order of equal objects:

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

The min and max functions are also consistent with sorted. max works as sorted (a, reverse = True) [0] , and min - sorted (a) [0] . This means that both functions return the leftmost possible answer:

 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 

Default cache argument


Perhaps the most common mistake among novice Pythonists is specifying a variable object as the default argument of the function. The separation of this object between function calls may lead to the strangest results:

 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] 

However, such sharing will even be useful if you use the object to create a shared cache:

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

In this example, we put the calculated factorial values ​​inside the default argument value. Such values ​​can even be extracted:

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

Work with FS


You can work with file system paths using the os.path module. The module contains many functions that perceive strings as file paths and perform various useful operations on them, such as concatenation:

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

Starting with version 3.4, Python includes the pathlib module, offering an object-oriented approach:

 >>> 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' 

Called Objects


In Python, you can create a callee not only by creating functions (using def syntax or lambda syntaxes). An object becomes invoked if it has a __call__ method:

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

Since the decorator is essentially a higher order function, it can also be expressed by the called object, and not by the function:

 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/429186/


All Articles