# Learn Python Programming Masterclass

<https://www.udemy.com/course/python-the-complete-python-developer-course>

Progress: 400/(580/100)

## Documentation

* <https://docs.python.org/3.11>

## IntelliJ python shortkeys:

* CMD+\ comment block
* CMD+shift+R run code
* ALT+CMD+L reformat code

## Section 2: Install and Setup

Q: Is it better to use vanilla python or a distribution like anaconda? We need to use a package to interface with hardware which is a Python extension to a C library (harvesters). It also requires specific Python versions.
A: TBD 

* Using Combination of vanilla python and IntelliJ IDE from Jetbrains. Community edition

* Virtual environements for dependency management so you don't screw up your python main installation. `virtualenv` `venv`.

* Venv could be suffixed with python version e.g venv-python39 or venv\python39

* Manage virtual envs from -> File -> Project structure -> Platform settings -> SDKs

* Conda is an alternative for virtualenv

* IntelliJ supports markdown and PlantUML/Mermaid diagrams and HTML preview

* IdeaVim emulation for vim users -> make it comfy

Could also install PyCharm. Pycharm is same applicable as python plugin for IntelliJ IDEA

## Section 3: Stepping into the World of Python

Code format according to PEP 8?

Python 2 EOL since 2019, focus on 3

**16. Printing in Python**

A function has a specific amount of arguments, but can have variable list of arguments. The print function is made to have variable list of arguments. The `print` function by defaults adds spaces in the output for multi-argument prints and a newline.

In Python all functions **return** a value.

Q: What about `pprint.pprint` for debugging?
A: TBD

Exercise: Print text conditionally using ternary operator:

```python
IsFull = True

print("My hovercraft is", "full" if IsFull else "not full", "of eels")
```


**17. Strings in Python**

Q: Multiple string types `''` and `""` and `r""` ?

In Python 3 all strings are unicode formatted. In Python 2 strings need to be prefixed with `u""`.  See also
https://docs.python.org/2/howto/unicode.html#unicode-literals-in-python-source-code

# Section 5 Lists and Typles

## Lists

A sequence is an ordered collection of items, the word ordered is important. Something that can be looped over with for is iterable. The accurate definition of an iterable is that an object contains either the `__iter__` or `__getitem__` method. All sequence types can be iterated over, strings, lists etc are iterable types. Not all iterables are sequences.

Lists are mutable, strings are immutable

## Immutable objects

Python immutable types, things which can not be changed:

* int
* float
* bool (subclass of int)
* str (string)
* tuple
* frozenset
* bytes

`id` gets the id of an object is guaranteed to be unique and constant for the object lifetime. the Cpython implementation does return the object memory address

# Mutable objects

* list
* dict
* set
* bytearray

# Operations on Mutable Sequences

<https://docs.python.org/3/library/stdtypes.html#mutable-sequence-types>

E.g append method. A method is bound to an object a function is not. A function is e.g `min` or `max`. Dot notation e.g list `s` append object `x` is written as `s.append(x)`. Dot notation is used in a lot of object oriented programming.

# Iterate over a list

Using `for` with [`sequence.index(item)`](https://docs.python.org/3/library/stdtypes.html#common-sequence-operations) is not good for performance. We must use [`enumerate`](https://docs.python.org/3/library/functions.html#enumerate) to get the index and the item. 

Python list comprehension:

`letters = [letter for letter in 'human']` 


# Section 6 Functions an introduction

## Docstrings

Docstrings are the documentation for functions. They are an attribute of the function. And can be accessed using `.__doc__` or builtin `help`. 

```
"""

"""
```

## Typehints and annotations

* <https://docs.python.org/3/library/typing.html>
* <https://peps.python.org/pep-3107/>

Example:

```python
def myfunction(x: int = 0) -> bool:
	return False
```

## Virtual Environment 

To activate execute `activate`(.bat) on windows or source `activate` on *nix.

## Testing and debugging

* **Testing** is the process of finding out if there are bugs in your code
* **Debugging** is the process of working out what the bugs are, and fixing them

# Section 7 Dictionaries and Sets

## setdefault

```python
if item_name in shopping_list:
	# Item is already in the list, so we need to buy more
	shopping_list[item_name] += item_quantity
else:
	shopping_list[item_name] = item_quantity

# code reduction by use the list setdefault function
shopping_list[item_name] = shopping_list.setdefault(item_name, 0) + item_quantity
```

## check if list is empty or not

```python
l1 = ["Hire", "the", "top", "1%", "freelancers"]

l2 = []

if l2:
    print("list is not empty")
else:
    print("list is empty")

#Output: "list is empty"
```

## Introduction to sets

A set is an unordered collection with no duplicate entries. Python has builtin set.

<https://docs.python.org/3.11/library/stdtypes.html#set>

**Set operations**

Set union -> removes duplicates 

```python
set1.union(set2) # or
set1 | set2
```

Set intersection -> get common items

```python
set1.intersection(set2) # or
set1 & set2
```

Set difference -> substracts common items

```python
set1 - set2 # or:
set1.difference(set2)
```

Symmetric difference -> reverse of intersection, removes common items

```python
set1 ^ set2 # or:
set1.symmetric_difference(set2)
```

Subsets and supersets

Use operators `<, <=, > and >=`

# Misc tips and tricks

## Convert datetime string to object

```python
from datetime import datetime

datetime_str = '09/19/22 13:55:26'

datetime_object = datetime.strptime(datetime_str, '%m/%d/%y %H:%M:%S')

print(type(datetime_object))
print(datetime_object)  # printed in default format
```

## Pretty print JSON string

Set the indent of `json.dumps`:

```python
import json

json_data = '[{"ID":10,"Name":"Pankaj","Role":"CEO"},' \
            '{"ID":20,"Name":"David Lee","Role":"Editor"}]'

json_object = json.loads(json_data)

json_formatted_str = json.dumps(json_object, indent=2)

print(json_formatted_str)
```

## Class equivalence

You need to be careful with inheritance:

```python
>>> class Foo:
    def __eq__(self, other):
        if isinstance(other, self.__class__):
            return self.__dict__ == other.__dict__
        else:
            return False

>>> class Bar(Foo):pass

>>> b = Bar()
>>> f = Foo()
>>> f == b
True
>>> b == f
False
```

Check types more strictly, like this:

```python
def __eq__(self, other):
    if type(other) is type(self):
        return self.__dict__ == other.__dict__
    return False
```

Besides that, your approach will work fine, that's what special methods are there for.

See <https://stackoverflow.com/questions/390250/elegant-ways-to-support-equivalence-equality-in-python-classes>

# Chapter 8 read-writing files in Python

Python 3 string type is native UTF-8. When the open builtin function is called an explict encoding can be given which is more portable between operating systems.

## Intellij file encoding

View -> Appareance -> Status bar widgets -> File encoding

Then the status bar get this file information:

![](i/Screenshot%202023-03-24%20at%2011.32.02.png)

## File encoding in python

https://docs.python.org/3/howto/unicode.html
https://docs.python.org/3/library/codecs.html?highlight=codecs%20file%20encoding#standard-encodings

# Data serialization

E.g JSON, CSV data formats
