Crash Course In Python 3

Python is a popular general-purpose programming language. For a while now, I wanted to pick up the language, however learning for the sake of learning is hard for me, until it was required of me to do my work. I spent a week learning python in order to do some embedded development work. I made myself a cheat sheet for future refresher/reference.

Setup:

  • Anaconda 
  • Python 3.6
  • PyCharm IDE

Python Basics

import math
import random
import json


# single line comment
''' multi line comment '''


def python_variable():
    # call the name of the current function
    print(python_variable.__name__)

    int_variable = 1
    float_variable = 2.345
    string_variable = "Hello there young one"

    # single line def and initialization
    a, b, c = 1, 4.33, "Hi There"

    # variables can be feed by deleting them
    del a

    # variables can be redefined into different types
    a = 0x2
    a = "HI"

    # complex number
    a = 3.14j

    some_string = "Another test string"
    some_string_a = string_variable[0]  # A
    some_string_b = some_string[2:5]  # Character from 2 to 5 index


def python_arrays():
    print(python_arrays.__name__)

    # CLASS: List can store mix types
    some_list = ["Hi my name is", "Masum", "age", 23, "height", 172.2, "CM"]
    print(type(some_list), "\n Print the whole list: ", some_list,
          "\n Or just a element of the the list", some_list[1])

    # Generate list
    some_list = [x for x in range(0, 100, 5)]

    # same as
    some_list_2 = []
    for x in range(0, 100, 5):
        some_list_2.append(x)


def python_tuples():
    print(python_tuples.__name__)
    # Similar to list but size cannot extend
    tuple_list = (123, "2345fg", 234.44)


def python_dictionaries():
    print(python_dictionaries.__name__)
    # Python dictionary is is similar to a hash table
    dict_key_pair = {0}
    dict_key_pair["Key_1"] = "002223444"
    dict_key_pair["Key_2"] = 8.334

    # Or it can be defined like this
    some_dict = {"Name": "Masum", "Age": 23.2, "Height CM": 172.2}


def data_conversion():
    print(data_conversion.__name__)

    ''' Convert to Int '''
    float_variable_conv = 23.5
    int_variable_conv = int(float_variable_conv)  # 23 gets saved

    ''' Convert to Float'''
    some_int_a = 44
    float_string_conv = float(some_int_a)

    ''' Convert to Complex Number '''
    list_a = [234, 55.3]
    complex_number = complex(33, 21)


def python_operators():
    add_op = 3 + 4
    sub_op = 4 - 2
    multi_op = 4 * 5
    div_op = 67 / 5
    mod_op = 10 % 3
    exponent_op = 3**3  # 3^3 = 27
    floor_div = 9//2 # 9 // 2 = 4

    # Equal ==
    # Not Equal  !=
    # More Than >
    # Less Than <
    # More Than Equal to >=
    # Less Than Equal to <=

    ''' Bitwise Operator '''
    # Bitwise AND: &
    # Bitwise OR: |
    # Bitwise XOR: ^
    # Bitwise invert: ~
    # Bitwise shift right: >>
    # Bitwise shit left: <<

    ''' Logical Operator '''
    # Logical AND: AND, and
    # Logical OR: OR, or
    # Logical NOT: NOT, not

    ''' Python Membership Operators'''
    # E.g var_x in var_y evaluates to True if var_x value is a member of var_y
    # E.g var_x not in var_y evaluates to True if var_x value is not a member of var_y


def python_if_statement():
    print(python_if_statement.__name__)
    var_y = 5
    var_x = [1, 4, 55, 6]
    if var_x[0] == 1:
        print("First index is: ", var_x[0])

    if var_y in var_x:
        print("Contains ", var_y)

    elif var_x[0] == 1:
        print("First index is: ", var_x[0])

    else:
        print("Nope")


def python_switch_statement():
    print(python_switch_statement.__name__)


def python_loops():
    print(python_loops.__name__)

    some_list = [x for x in range(5, 25, 5)]
    some_dict = {"Key_1": 10, "Key_2": 12.5}

    # for loop example
    print("Simple for loop using range")
    for x in range(10):
        print(x)

    print("Simple loop using range with step size")
    for x in range(5, 20, 2):
        print(x)

    print("Loops list using an iterator")
    for x in some_list:
        print(x)

    print("Loops Dictionary ")
    for key, value in some_dict.items():
        print("Key: ", key)
        print("Values ", value)

    print("While Loop")
    while x < 10:
        x += 1
        print(x)


def python_number():
    some_list = [x for x in range(-22, 10, 4)]
    ''' Maths Functions '''
    absolute_value = abs(some_list[0])
    print(absolute_value)   # prints 22

    float_abs = math.fabs(-22.33)
    print(float_abs)    # 22.33

    smallest_int = math.ceil(66.78)
    print(smallest_int)     # prints 66

    # exponential
    expo_value = math.exp(2)    # e^2
    print(expo_value)

    # log(x) base 2
    # log10(x) base 10
    # max(var1, var2, ...) returns largest
    # min(var1, var2, ...) returns smallet
    # modf this is pretty cool
    modf_var = math.modf(10.4)
    print(modf_var)     # returns a tuple (0.40000000000000036, 10.0)

    round_number = round(23.4444433324, 3)
    print(round_number)

    print(math.sqrt(144))


def python_random_number():
    random_number_from_a_list = random.choice([x for x in range(10, 100, 2)])
    print("Random Number From A List", random_number_from_a_list)

    random_number_from_range = random.randrange(0, 20, 3)
    print("Random Number From A Range: ", random_number_from_range)

    print("Random Float From 0 to 1 ", random.random())

    print("Random Seed ", random.seed())

    shuffle_list = [x for x in range(0, 10, 1)]
    random.shuffle(shuffle_list)
    print("Shuffle List: ", shuffle_list)


def python_io():
    str_name = input("Enter your name ")
    user_age = int(input("Enter Age"))
    print(str_name, user_age)

    some_dict = {"Name": str_name, "Age": user_age}
    print(some_dict)

    file = open('test_file_a.json', 'w')
    file_string = json.dumps(some_dict, indent=4)
    file.write(file_string)

    with open('test_file_b.json', 'w') as file_obj:
        json.dump(some_dict, file_obj, indent=4)

Python OOP

# Subclass / Parent Class / Base Class
class Employee:
    num_of_emps = 0
    raise_amount = 1.04  # raise 4 % per year

    # Default Ctor
    def __init__(self, first_name, last_name, salary):
        self.first_name = first_name
        self.last_name = last_name
        self.salary = salary
        self.email = first_name + '.' + last_name + '@gmail.com'

        Employee.num_of_emps += 1

    # Default Dtor
    def __del__(self):
        print("Object Deleted")

    # Example Instance Method / Function
    def get_full_name(self):
        return '{} {}'.format(self.first_name, self.last_name)

    # Example of Instance Method / Function
    def apply_raise(self):
        self.salary = int(self.salary * Employee.raise_amount)

    # Example of Class Method / Function - similar to C++ static functions
    @classmethod
    def set_raise_amt(cls, amount):
        cls.raise_amount = amount

    # Python Ctor overloaded using @classmethod, the return statement calls the class ctor
    # Since cls is the class it is the same as calling Employee()
    @classmethod
    def ctor_from_string(cls, cls_str):
        first_name, last_name, salary = cls_str.split('-')
        return cls(first_name, last_name, salary)

    # Python static functions do not use / alter class attribute however the functionality is
    # loosely related to the class
    @staticmethod
    def is_workday(day):
        if day.weekday() == 5 or day.weekday == 6:  # Monday = 0 ... Sunday = 6
            return False
        return True


# Class/ Child Class / Super Class
class Developer(Employee):
    raise_amount = 1.05  # 5% per year

    def __init__(self, first_name, last_name, salary, lang):
        super(Developer, self).__init__(first_name, last_name, salary)
        self.prog_lang = lang

    def learn_new_lang(self, new_lang):
        self.prog_lang.append(new_lang)

    @classmethod
    def get_raise_amount(cls):
        return cls.raise_amount


new_dev_a = Developer("Alex", "Smith", 35000, "Javascript")

print(new_dev_a.prog_lang)
print(new_dev_a.salary

Python kwargs, args

# min_value(33,44,3,2,66,75,2,-77,0.43)
# will return -77
def min_value(*args):
    result = args[0]
    for item in args:
        if item < result:
            result = item
    return result


# Accepts dictionary like input and returns a dictionary
def some_kwarg_func(**kwargs):
    print(kwargs)
    return kwargs

 

Sandbox – Matplotlib, PySerial, Thread, JSON, IO

main.py

import serial_logger
import time
import sys

is_running = True


def main():
    global is_running
    serial_logger.com_port = input("Enter the RTD board com port e.g COM11 ")
    serial_logger.start_rtd_thread()
    while is_running:
        input_str = input(" Enter STOP to Stop Logging ")
        if input_str != "STOP":
            time.sleep(1)
        else:
            is_running = False
            serial_logger.is_logging = False
            serial_logger.join_rtd_thread()
            sys.exit()


# Press the green button in the gutter to run the script.
if __name__ == '__main__':
    main()

serial_logger.py

import serial
import threading
import json
import csv


is_logging = True
com_port = ""


def read_rtd_serial():
    global is_logging

    # Connect to correct com port - currently hard coded
    rtd_serial_in = serial.Serial(com_port, 921600, timeout=0.5)
    rtd_serial_in.flushInput()

    # CSV File Header
    field_name = ["ADC ChA1",
                  "ADC ChA2",
                  "ADC ChA3",
                  "ADC ChA4",
                  "ADC ChA5",
                  "ADC ChA6",
                  "ADC ChA7",
                  "ADC ChA8",
                  "ADC ChB1",
                  "ADC ChB2",
                  "ADC ChB3",
                  "ADC ChB4",
                  "ADC ChB5",
                  "ADC ChB6",
                  "ADC ChB7",
                  "ADC ChB8",
                  "ADC ChC1",
                  "ADC ChC2",
                  "ADC ChC3",
                  "ADC ChC4",
                  "ADC ChC5",
                  "ADC ChC6",
                  "ADC ChC7",
                  "ADC ChC8",
                  "UI Logger Period",
                  "UI Logger Enabled",
                  "UI Test ID",
                  "UI Mock Chip ID",
                  "UI Test Run Time",
                  "UI CChiller Power",
                  "UI CPump Power",
                  "UI Fluidic Temperature",
                  "UI Chiller Auto Mode",
                  "UI Heater One",
                  "UI Heater Two",
                  "UI Heater Three",
                  "UI Heater Four"
                  ]

    # Creates a new file is file does not already exist, then adds the correct header.
    f = open("rtd_logger.csv", "w", newline='', encoding="utf-8")
    tmp = csv.DictWriter(f, fieldnames=field_name)
    tmp.writeheader()
    f.close()

    # Logging Thread : saves board settings and RTD count in a CSV file
    while is_logging:
        serial_byte = rtd_serial_in.readline()
        json_string = serial_byte.decode("utf-8")
        if json_string != '':
            # print("Running")
            no_newline = json_string.rstrip('\n')
            log_string = no_newline.replace("}{", ", ")
            compose_dict = json.loads(log_string)
            with open("rtd_logger.csv", "a", newline='') as f:
                data_log = csv.DictWriter(f, fieldnames=field_name)
                data_log.writerow(compose_dict)
                # print(compose_dict)

    # when leaving the thread close serial connection
    rtd_serial_in.close()


serial_rtd = threading.Thread(target=read_rtd_serial)


# function to start the RTD thread
def start_rtd_thread():
    global serial_rtd
    serial_rtd.start()


def join_rtd_thread():
    serial_rtd.join()

sandbox_matlibplot.py

from matplotlib import animation
import matplotlib.pyplot as plt
from stm32_serial import adc_dictionary
import threading
import collections

counter = 0

cy_data = collections.deque([[0], [0], [0], [0], [0], [0], [0], [0], [0], [0], [0], [0], [0], [0], [0], [0], [0], [0], [0], [0], [0], [0], [0], [0]])
cx_data = collections.deque([[0], [0], [0], [0], [0], [0], [0], [0], [0], [0], [0], [0], [0], [0], [0], [0], [0], [0], [0], [0], [0], [0], [0], [0]])

fig, ax = plt.subplots()
ax.set_xlim(0, 200)
#plt.show()


def adc_animate():
    i = 0
    global counter
    plt.cla()

    for key, value in adc_dictionary.items():
        cx_data[i].append(int(counter))
        cy_data[i].append(int(value))

        ax.plot(cx_data[i], cy_data[i], label=key)
        counter += 1
        if counter > 1000:
            cx_data[i].pop(0)
            cy_data[i].pop(0)

        i += 1

    plt.draw()
    plt.pause(0.001)



def plot_init():
    plt.ion()
    plt.show()
    ax.legend()


def start_plot_thread():
    plot_init()
    plot_animate = threading.Thread(target=adc_animate)
    plot_animate.start()


#ani = animation.FuncAnimation(fig, adc_animate, frames=10, interval=100)

''' 
for _ in range(10):
    for key, value in adc_dictionary.items():
        plt.plot(counter, int(value), label=key)
    counter += 1

plt.show()

'''