from collections import defaultdict from functools import reduce TrieNode = lambda: defaultdict(TrieNode)
classTrie: def__init__(self): self.trie = TrieNode() definsert(self, word): reduce(dict.__getitem__, word, self.trie)['end'] = True defsearch(self, word): return reduce(lambda d,k: d[k] if k in d else TrieNode(), word, self.trie).get('end', False) defstartsWith(self, word): returnbool(reduce(lambda d,k: d[k] if k in d else TrieNode(), word, self.trie).keys())
classTrieNode(object): def__init__(self): """ Initialize your data structure here. """ self.data = {} self.is_word = False classTrie(object): def__init__(self): self.root = TrieNode() definsert(self, word): """ Inserts a word into the trie. :type word: str :rtype: void """ node = self.root for letter in word: child = node.data.get(letter) ifnot child: node.data[letter] = TrieNode() node = node.data[letter] node.is_word = True defsearch(self, word): """ Returns if the word is in the trie. :type word: str :rtype: bool """ node = self.root for letter in word: node = node.data.get(letter) ifnot node: returnFalse return node.is_word defstarts_with(self, prefix): """ Returns if there is any word in the trie that starts with the given prefix. :type prefix: str :rtype: bool """ node = self.root for letter in prefix: node = node.data.get(letter) ifnot node: returnFalse returnTrue defget_start(self, prefix): """ Returns words started with prefix :param prefix: :return: words (list) """ def_get_key(pre, pre_node): words_list = [] if pre_node.is_word: words_list.append(pre) for x in pre_node.data.keys(): words_list.extend(_get_key(pre + str(x), pre_node.data.get(x))) return words_list words = [] ifnot self.starts_with(prefix): return words if self.search(prefix): words.append(prefix) return words node = self.root for letter in prefix: node = node.data.get(letter) return _get_key(prefix, node)
""" base 2 (binary) """ # decimal to binary (base 2) bin_dec = bin(dec) # str: '0b101' # binary to decimal dec = int(bin_dec, 2) # int: 5
""" base 8 (octal) """ # decimal to octal (base 8) oct_dec = oct(dec) # str: '05' # octal to decimal dec = int(oct_dec, 8) # int: 5
""" base 16 (hexadecimal) """ # decimal to hexadecimal (base 16) hex_dec = hex(dec) # str: '0x5' # hexadecimal to decimal dec = int(hex_dec, 16) # int: 5
Bit-wise Op
&: binary AND. Op copies a bit to the result if it exists in both operands.
|: binary OR. It copies a bit to the result if it exists in either operand.
^: binary XOR. It copies a bit if it is set in one operand but not both.
~: binary Ones Complement. It is unary and has the effect of ‘flipping’ bits.
<<: binary left shift.
>>: binary right shift.
Array index
1 2
~i # -i-1 arr[~i] # is equal to arr[-i-1]
\r application
\r puts the location of the cursor at the beginning of the current row.
\b backtracks one bit of the cursor.
Count down
1 2 3 4 5 6 7 8 9
import time
count_down = 10# count down total time ( seconds ) for i inrange(count_down, 0, -1): msg = u"\r System will exit in " + str(i) + "secs" print(msg, end="") time.sleep(1) end_msg = "end" + " "*(len(msg)-len("end")) # cover all the console output with whitespace print(u"\r"+end_msg)
Progress bar
1 2 3 4 5 6 7 8 9
import time
count_down = 10 interval = 1 for i inrange(0, int(count_down/interval)+1): print("\r"+"▇"*i+" "+str(i*10)+"%", end="") time.sleep(interval) print("\n Finished")
Loading
1 2 3 4 5 6 7 8 9 10 11
import time
count_down = 10 interval = 0.25 for i inrange(0, int(count_down/interval)): ch_list = ["\\", "|", "/", "-"] index = i % 4 msg = "\r Program is running " + ch_list[index] print(msg, end="") time.sleep(interval) print(u"\r Finished" + " "*len(msg))
deftime_metric(func): # print the call time and call counts count = 0 defwrapper(*args, **kwargs): nonlocal count start_time = time.time() data = func(*args, **kwargs) time_delta = time.time() - start_time count += 1 print("Call {} times. It costs {} secs".format(count, time_delta)) return data return wrapper
@time_metric deff(): time.sleep(0.5)
Deep copy and shallow copy
= operator only creates a new variable that shares the reference of the original object.
Deep copy is a process in which the copy process occurs recursively. It first construct a new collection object and then recursively populating it with copies of the child objects found in the original. Any changes made to a copy of object do not reflect in the original object.
1 2 3 4 5 6 7
import copy
l = [1,2,[3,4],5] l_deep = copy.deepcopy(l) # deep copy l[2][0] = 6 print(l) # [1,2,[6,4],5] print(l_deep) # [1,2,[3,4],5]
Shallow copy constructs a new collection object and then populating it with references to the children objects found in the original. The copying process does not recurse and therefore won’t create copies of the child objects themselves.
Avoids GIL(Global Interpreter Lock) limitations for cPython
Children processes are interruptible
A must with cPython for CPU-bound processing
Cons:
IPC a little more complicated with more overhead
Larger memory footprint
threading
Pros:
Lightweight -> low memory footprint
Shared memory -> makes access to state from another context easier
Allows you to easily make responsive UIs
cPython C extension modules that properly release the GIL will run in parallel
Great option for I/O-bound applications
Cons:
CPython -> subject to the GIL
Not interruptible/killable
Random
1 2 3 4 5 6 7 8 9 10 11 12 13
# approach 1 import numpy as np np.random.choice(items, p)
# approach 2 defrandom_select(items, p): x = random.uniform(0,1) cum_p = .0 for item, prob inzip(items, p): cum_p += prob if x < cum_p: break return item
Pathlib
The python std library Pathlib module can be used to manipulate windows paths on a Unix machine(or vice versa). It can also be used to manipulate paths without accessing the os module.
# open a file >>> with q.open() as f: f.readline()
>>> p.name # filename >>> p.stem # filename without suffix >>> p.suffix # file suffix >>> p.parent # the dirname
# create directory >>> p=Path(r'./a/b/c') >>> p.mkdir(exist_ok=True) # create if the parent directory exists ## iteratively create the directory >>> p.mkdir(exist_ok=True, parents=True)
# file details >>> p.stat() # detail information >>> p.stat().st_size # file size >>> p.stat().st_ctime # create time >>> p.stat().st_mtime # modified time
itertools
itertools.count()
Iteration over infinite numbers
1 2 3 4 5 6
$ import itertools $ results = [] $ for x in itertools.count(start=0): $ if <condition>: $ break $ results.append(<element>)
itertools.permutations()
itertools.permutations(iterable, r=None)
Return successive $r$ length permutations of elements in the iterable. If None, then $r$ defaults to the length of the iterable and alll possible full-length permutations.
1 2
# permutations('ABCD', 2) --> AB AC AD BA BC BD CA CB CD DA DB DC # permutations(range(3)) --> 012 021 102 120 201 210
itertools.zip_longest()
1 2
# Similar to zip but return the longest length of inputs with filling default values, whereas zip returns the shortest length itertools.zip_longest(*iterables, fillvalue=None)
defprint_format_table(): """ prints table of formatted text format options """ for style inrange(8): for fg inrange(30, 38): s1 = '' for bg inrange(40, 48): format = ';'.join([str(style), str(fg), str(bg)]) s1 += '\x1b[%sm %s \x1b[0m' % (format, format) print(s1) print('\n')
Python’s default arguments are evaluated once when the function is defined, not each time the function is called (like it is in say, Ruby). This means that if you use a mutable default argument and mutate it, you will and have mutated that object for all future calls to the function as well.
Important warning: The default value is evaluated only once. This makes a difference when the default is a mutable object such as a list, dictionary, or instances of most classes.
The list iteration is done index by index. When removing 1 from l1 or l4, the contents of lists are [2,3,4]. The remaining elements are shifted down, i.e. 2 is at index 0, 3 at index 1. Since the next iteration is going to loo at index 1 (element 3), the 2 is skipped entirely.
Run
stderr directly outputs to the screen, whilst the stdout is usually saved in the buffer util full. python -u can directly print out the stdout without buffers.