Python Tips # 1
Tags: python
Published: 2019-08-19 20:07:31

These tips are entirely based on the Python official tutorial guide.


- **Using `else` in `for` statements:**  

You can use the `else` clause at the end of a `for` loop if you want to trigger an action as soon as the loop finishes. It will not be triggered by `break`:

  ```python
  for num in range(2, 10):
    for x in range(2, n):
      if n % x == 0:
        print(n, 'equals', x, '*', n//x)
    		break
      else:
        # loop fell through without finding a factor
        print(n, 'is a prime number')
  ```


  [Source](https://docs.python.org/3/tutorial/controlflow.html#if-statements)


- **Using simple copy vs shallow copy vs deep copy:** 


  - Simple copy or `=` will only create a reference of the object:

  ```python
  old_list = [[1, 1, 1], [2, 2, 2], [3, 3, 3]]
  new_list = old_list
  new_list[2][2] = 9
  
  print('old_list:', old_list)
  print('id of old_list:', id(old_list))
  
  print('new_list:', new_list)
  print('id of new_list:', id(new_list))
  ```

  ```
  Old List: [[1, 1, 1], [2, 2, 2], [3, 3, 9]]
  ID of Old List: 140673303268168
  
  New List: [[1, 1, 1], [2, 2, 2], [3, 3, 9]]
  ID of New List: 140673303268168
  ```


  - Shallow copy or `object[:]`will create a new object but will reference the nested objects:

    ```python
    import copy
    
    old_list = [[1, 1, 1], [2, 2, 2], [3, 3, 3]]
    new_list = old_list[:] # or copy.copy(old_list)
    old_list[1][1] = 'AA'
    
    print('old_list:', old_list)
    print('id of old_list:', id(old_list))
    
    print('new_list:', new_list)
    print('id of new_list:', id(new_list))
    ```

    ```
    old_list: [[1, 1, 1], [2, 'AA', 2], [3, 3, 3]]
    id of old_list: 140673303268168
    
    new_list: [[1, 1, 1], [2, 'AA', 2], [3, 3, 3]]
    id of new_list: 140673303268169
    ```

    
  - Finally, a deep copy will create a new object and will create new objects for the content as well: 

    ```python
    import copy
    
    old_list = [[1, 1, 1], [2, 2, 2], [3, 3, 3]]
    new_list = copy.deepcopy(old_list)
    old_list[1][1] = 'AA'
    
    print('old_list:', old_list)
    print('id of old_list:', id(old_list))
    
    print('new_list:', new_list)
    print('id of new_list:', id(new_list))
    ```

    ```
    old_list: [[1, 1, 1], [2, 'AA', 2], [3, 3, 3]]
    id of old_list: 140673303268168
    
    new_list: [[1, 1, 1], [2, 2, 2], [3, 3, 3]]
    id of new_list: 140673303268169
    ```

    [Source](https://www.programiz.com/python-programming/shallow-deep-copy)


- **Default values in functions are evaluated only once:**

```python
def f(a, L=[]):
    L.append(a)
    return L

print(f(1))
print(f(2))
print(f(3))
```

```
[1]
[1, 2]
[1, 2, 3]
```

If you don’t want the default to be shared between subsequent calls, you can write the function like this instead:

```python
def f(a, L=None):
    if L is None:
        L = []
    L.append(a)
    return L
```

[Source](https://docs.python.org/3/tutorial/controlflow.html#if-statements)


- **Use `deque` to implement double-ended queues:**


  "Deques are a generalization of stacks and queues (the name is pronounced “deck” and is short for “double-ended queue”). Deques support thread-safe, memory efficient appends and pops from either side of the deque with approximately the same O(1) performance in either direction".

  ```python
  from collections import deque
  d = deque('ghi')
  d.append('j')
  d.appendleft('f')
  j = d.pop()
  f = d.popleft()
  for elem in d:
    print(elem.upper())
   
  ```

   [Source](https://docs.python.org/3/tutorial/datastructures.html#using-lists-as-queues)