262 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			262 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| ---
 | |
| title: Handy Python Tips
 | |
| date: 2021-05-29
 | |
| tags:
 | |
| - tech
 | |
| ---
 | |
| 
 | |
| Python is a flexible programming language that is well-known for its simplicity and numerous features that make programming in it a lot faster. This article presents just a few that might speed up your productivity a little bit.
 | |
| 
 | |
| <!-- more -->
 | |
| 
 | |
| ## 1. Tuple expansion
 | |
| 
 | |
| ```python
 | |
| a, b = tuple([1, 2])
 | |
| s1, s2 = input(), int(input())
 | |
| ```
 | |
| 
 | |
| Tuple expansion is one of Python's most powerful features, allowing you to assign multiple values or expand multiple values of a tuple in a single line.
 | |
| 
 | |
| ```python
 | |
| >>> print(a, b)
 | |
| 1 2
 | |
| >>> print(s1, s2)
 | |
| baguette
 | |
| pomme
 | |
| Traceback (most recent call last):
 | |
|   File "<stdin>", line 1, in <module>
 | |
| ValueError: invalid literal for int() with base 10: 'pomme'
 | |
| ```
 | |
| 
 | |
| The code above effectively assigns a tuple `(a, b)` to another tuple `(1, 2)`, and is equivalent to the code below:
 | |
| 
 | |
| ```python
 | |
| a = 1
 | |
| b = 2
 | |
| s1 = input()
 | |
| s2 = int(input())
 | |
| ```
 | |
| 
 | |
| This can let you return multiple values from a function.
 | |
| 
 | |
| ```python
 | |
| def init():
 | |
|     return (5, 6)
 | |
| 
 | |
| a, b = init()
 | |
| print(a, b)
 | |
| ```
 | |
| 
 | |
| Output:
 | |
| 
 | |
| ```
 | |
| 5 6
 | |
| ```
 | |
| 
 | |
| Tuple expansion is also used in for loops to iterate over tuples or even dictionaries.
 | |
| 
 | |
| ```python
 | |
| array = [
 | |
|     (1, 2),
 | |
|     (3, 4),
 | |
|     (5, 6)
 | |
| ]
 | |
| 
 | |
| items = {
 | |
|     7: 8,
 | |
|     9: 10,
 | |
|     11: 12
 | |
| }
 | |
| 
 | |
| for i, j in array:
 | |
|     print(i, j)
 | |
| 
 | |
| for k, v in items.items():
 | |
|     print(k, v)
 | |
| ```
 | |
| 
 | |
| Output:
 | |
| 
 | |
| ```
 | |
| 1 2
 | |
| 3 4
 | |
| 5 6
 | |
| 7 8
 | |
| 9 10
 | |
| 11 12
 | |
| ```
 | |
| 
 | |
| ## 2. Nicer iteration with zip() and enumerate()
 | |
| 
 | |
| Python's for loop is commonly known in other programming languages as a for-each loop. This is great if you just want each item in an iterable, but sometimes you want the index too! Instead of having to resort to `range(len(array))`, instead you can use `enumerate()` and tuple expansion to easily get both the index of the element and the element itself:
 | |
| 
 | |
| ```python
 | |
| array = ["a", "b", "c", "d", "e"]
 | |
| for i, c in enumerate(array):
 | |
| 	print(i, c)
 | |
| ```
 | |
| 
 | |
| Output:
 | |
| 
 | |
| ```
 | |
| 0 a
 | |
| 1 b
 | |
| 2 c
 | |
| 3 d
 | |
| 4 e
 | |
| ```
 | |
| 
 | |
| In a similar vein, if you have two arrays you want to process at the same time, you don't need to use `range(len(array))` when you have `zip()`, which will bundle the different iterators into one big one as big as the smallest iterable.
 | |
| 
 | |
| ```python
 | |
| ints = [1, 2, 3, 4]
 | |
| strs = ("pomme", "poutine", "pinterest", "pear")
 | |
| floats = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]
 | |
| for i, s, f in zip(ints, strs, floats):
 | |
|     print(i, s, f)
 | |
| ```
 | |
| 
 | |
| Output:
 | |
| 
 | |
| ```
 | |
| 1 pomme 1.0
 | |
| 2 poutine 2.0
 | |
| 3 pinterest 3.0
 | |
| 4 pear 4.0
 | |
| ```
 | |
| 
 | |
| ## 3. Iterable unpacking
 | |
| 
 | |
| In competitive programming, often you have to print out space-separated results. This can be done by the mildly inconveniencing
 | |
| 
 | |
| ```python
 | |
| print(" ".join([1, 2, 3, 4]))
 | |
| ```
 | |
| 
 | |
| or heaven forbid, via iteration:
 | |
| 
 | |
| ```python
 | |
| for i in [1, 2, 3, 4]:
 | |
|     print(i, end=" ")
 | |
| print()
 | |
| ```
 | |
| 
 | |
| which is where iterable unpacking comes in, and you can go straight to
 | |
| 
 | |
| ```python
 | |
| print(*[1, 2, 3, 4])
 | |
| ```
 | |
| 
 | |
| The **unpacking operator** (the asterisk) basically gets rid of the container and throws all of the elements inside directly into the print function as parameters.
 | |
| 
 | |
| That means that the above line of code is equivalent to:
 | |
| 
 | |
| ```python
 | |
| print(1, 2, 3, 4)
 | |
| ```
 | |
| 
 | |
| which nicely prints out the integers separated by spaces with a newline at the end.
 | |
| 
 | |
| But wait, there's more! The unpacking operator is also commonly used in function definitions as a catch-all parameter for extra arguments, stuffing them into a list.
 | |
| 
 | |
| ```python
 | |
| def init(a, b, *args):
 | |
|     print(a, b)
 | |
|     print(args)
 | |
| 
 | |
| init(1, 2, "pomme", 4, 6.0)
 | |
| ```
 | |
| 
 | |
| Output:
 | |
| 
 | |
| ```
 | |
| 1, 2
 | |
| ['pomme', 4, 6.0]
 | |
| ```
 | |
| 
 | |
| You can also use this in normal assignment:
 | |
| 
 | |
| ```python
 | |
| a, *args, b = (1, 2, 3, 4, 5)
 | |
| print(a)
 | |
| print(args)
 | |
| print(b)
 | |
| ```
 | |
| 
 | |
| Output:
 | |
| 
 | |
| ```
 | |
| 1
 | |
| [2, 3, 4]
 | |
| 5
 | |
| ```
 | |
| 
 | |
| And it can be used as a handy way to expand a list instead of using `list()`. The comma at the end of the variable is there to indicate it is a tuple with a single element (a singleton).
 | |
| 
 | |
| ```python
 | |
| *s, = "abcde"
 | |
| print(s)
 | |
| ```
 | |
| 
 | |
| Output:
 | |
| 
 | |
| ```
 | |
| ['a', 'b', 'c', 'd', 'e']
 | |
| ```
 | |
| 
 | |
| ## 4. map()
 | |
| 
 | |
| This makes one-liners super easy in Python. `map()` takes a function in the first parameter and applies it to all values in the iterable in the second parameter.
 | |
| 
 | |
| ```python
 | |
| def readints(string):
 | |
|     print(list(map(int, string.split()))
 | |
| readInts("1 2 3 4 5")
 | |
| ```
 | |
| 
 | |
| Output:
 | |
| 
 | |
| ```
 | |
| [1, 2, 3, 4, 5]
 | |
| ```
 | |
| 
 | |
| It's most useful in assigning variables easily when you know the format the input will be in.
 | |
| 
 | |
| ```python
 | |
| a, b = (map(int, input().split()))
 | |
| ```
 | |
| 
 | |
| ## 5. List generators
 | |
| 
 | |
| You can generate a new list using inline `for`.
 | |
| 
 | |
| ```python
 | |
| array = [i for i in range(10)]
 | |
| print(array)
 | |
| ```
 | |
| 
 | |
| Output:
 | |
| 
 | |
| ```
 | |
| [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
 | |
| ```
 | |
| 
 | |
| ## 6. One-line prefix sum array
 | |
| 
 | |
| A [prefix sum array](https://en.wikipedia.org/wiki/Prefix_sum) is a common data structure used in competitive programming. Python's `itertools` module has a wide array of functionality that can make this easier. A traditional PSA requires three lines:
 | |
| 
 | |
| ```python
 | |
| psa = [0]
 | |
| for i in [1, 2, 3]:
 | |
|     psa.append(psa[-1] + i)
 | |
| ```
 | |
| 
 | |
| Excluding the import, you can shrink it down to one with `itertools`:
 | |
| 
 | |
| ```python
 | |
| import itertools
 | |
| *psa, = itertools.accumulate([1, 2, 3])
 | |
| ```
 | |
| 
 |