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!