Pythonsmall, clean, fun, powerful! |
Let's to https://mybinder.org/v2/gh/binder-examples/r/HEAD?filepath=index.ipynb [using Chrome] and create a new Python3 notebook:
New notebook:
Yeay! Now we can play :)
You can simply watch, and/or take notes, and/or follow along...
What follows is very compact/terse (it's the 'essence' of ALL programming!) - if anything isn't clear, do ask later, or find out by yourself!
We can regard ANY programming language this way (as being made up of these 4 levels):
EVERY programming language lets us use vars, ie. variables.
Each var has a NAME, VALUE of a certain TYPE.
"Programming" consists of using as many vars as we need, and PUTTING (WRITING) values into them, and GETTING (READING) the values (we put) in them.
Variables vary :) We can OVERWRITE (no undo!) a var's values very many times..
Here are the TYPES of values we can store, in a Python var:
#int, float a = 5 pi = 3.1415 #boolean sunnyToday = True #string schoolName = "USC"
Note: the = does NOT mean equality!! It really means <------, in other words, we STORE (ASSIGN/WRITE/SET/PUT/...) right-hand-side [RHS] (ALWAYS a VALUE), into the left-hand-side [LHS] (ALWAYS a VAR):
var <-----receives----- value
The above types are 'atomic' types. There are also, aggregate (collection) types: list, tuple, dictionary.
There is one more type: a 'class'!! Here is where, we can create our OWN type (eg. color, playlist, Driver's License, datatable...) using existing types. This is a very powerful mechanism.
You can read more here.
Operators are symbols (like in math) we use, to do assignments, calculations and comparisons on the values in vars.
Calculation operators: + - * / // % **
Assignment operators: = += -= *= /= //= %= **=
Comparison operators: == != < <= > >=
Logical ('combination') operators: and or not
We can use print() to examine a var's value:
a = 2**10 print(a)
You can look up more here.
In a=2**10, the RHS 2**10 is an expression which TURNS INTO a value. The entire line a=2**10 is called a statement.
We need a way to BRANCH ("do this", or, "do that") code execution, and a way to LOOP ("repeat this") code execution.
LOOPING AND BRANCHING form the HEART of all programming!!!
Python's branching statements: if..., if...else..., if...elif...else... [three variations]
Python's looping statements: while, for
LOOPS AND BRANCHES CAN BE ENDLESSLY 'NESTED' (telescoped) INSIDE EACH OTHER!!! This should be one of your BIGGEST takeaways!
Loops and branches are also, statements.
In Python, we NEED to indent the 'insides' of a while or for or if - in other words, the 'body' of if/while/for needs to be offset (indented); in other languages we use { } rather than indentation.
A function is a packaging (abstracting) mechanism - we can pack up a bunch of code, give it a NAME, then USE that name over and over...
We can collect (gather, group...) a bunch of RELATED functions, call it a 'module'. Python's magic lies in the following fact: simple core language, EXTENSIVE/POWERFUL modules!!
Eg. the 'math' module has math functions. We can use dir() to examine what is inside a module...
import math
print(dir(math))
def hyp(x,y):
return math.sqrt(x*x+y*y)
print(hyp(3,4))
Note: we can also group together data (vars) and related code (functions), and package them into 'CLASSES' (which can then go in modules). A class is a new TYPE - we can then create vars (OBJECTS) for such types, and use the functions to manipulate (read/write) values in vars. Or we can define 'static' functions and call them without needing to make an object first.
We write/define/create a function/class/module just once, and call/execute/run/invoke them multiple times! Here is how we call the 5 [1+2+2] different variations of a function:
You now know a LOT about Python - vars (value, type), operators (expression, statement), flow control (branching, looping), abstraction (functions, modules). With these you can do/learn a ton of things!!
We can reuse functions - once we write one, we can 'call' use them inside another function's definition!
import math
def hyp(x,y):
return math.sqrt(x*x+y*y)
def hypAvg(x0,y0, x1,y1):
h1 = hyp(x0,y0)
h2 = hyp(x1,y1)
av = 0.5*(h1+h2)
return av
# use/call our new function
print(hypAvg(3,4, 6,8)) # av of 5, 10, ie. expect 7.5
Do the following in the 'mybinder' Jupyter IDE or conda shell or Colab:
import math
import numpy as np
for angle in np.arange(1,360,0.1):
ang = angle*math.pi/180
radius = 10
x = radius*math.cos(ang)
y = radius*math.sin(ang)
print(x,",",y)
# try this too: import random, then do
# x = radius*math.cos(ang) + 2*random.random()
# y = radius*math.sin(ang) + 2*random.random()
# save the x,y to a text file, add column names (eg x,y),
# rename to be a .csv file, then upload it to
# https://statscharts.com/scatter/scatterchart?status=edit
# to visualize it :)
For this, we are going to use the conda shell.
Create a dir, eg. MIDIWriter. Inside it, create a midi_writer folder, and place these two files (the two files are/form the midi_writer module):
Next, create a blank run.py file, place/paste the following in it, save:
import midi_writer
print(dir(midi_writer)) # peek inside the module :)
# the usage example code below is at
# https://github.com/FlipperPA/midi-writer/tree/main/examples
from midi_writer import MIDIFile, Notes
_ = Notes() # The Notes class maps notes to their MIDI equivalents
degrees = [_.C4, _.D4, _.E4, _.F4, _.G4, _.A4, _.B4, _.C5]
track = 0
channel = 0
time = 0 # In beats
duration = 1 # In beats
tempo = 60 # In BPM
velocity = 100 # 0-127, as per the MIDI standard - often used for VOLUME
MyMIDI = MIDIFile(1) # One track
MyMIDI.add_tempo(track, time, tempo)
for i, pitch in enumerate(degrees):
MyMIDI.add_note(track, channel, pitch, time + i, duration, velocity)
with open("major-scale.mid", "wb") as output_file:
MyMIDI.write_file(output_file)
print("The MIDI file has been written successfully.")
Run the run.py file, like so:
Look in the folder - ta da - a MIDI file!!!
To practice more, you can start playing with the tons of Python scripts, modules... that are out there. HAVE FUN!