Red: What You'd Actually Put in Python File: Common Differences Between Python and MATLAB, Ways To Approach Python
Red: What You'd Actually Put in Python File: Common Differences Between Python and MATLAB, Ways To Approach Python
Introduction
Here are some notes that I’ve been taking over the past few weeks as I learn Python
using learnpython.org. I recommend going through this site as well, as they give example
problems for each of the sections listed below. My background in programming lies in C and
MATLAB, and unlike these functional programs, Python is object oriented, which will be hard to
grasp as first. In functional programming like C and MATLAB, every single variable you use must
be defined beforehand, but in Python, variables can be created on the spot without prior
definition (mainly in loops), as long as it corresponds to some sort of data (string, values) which
follows the object’s declaration. You’ll see what I mean as you go through these notes. You
could still define all variables beforehand, as you would in MATLAB, but that’s not the best use
of Python. To access all of Python’s built in functions, visit https://docs.python.org/3/library/.
Arithmetic Operators
%: modulo operator, returns the remainder after division, 11%3 returns 2
** 2: The same as squared
** 3: The same as cubed
Can multiply strings: “hello”*10 gives 10 iterations of hello
Can join lists with addition operator (but can’t mix values with strings)
Can multiply lists, list*3= listlistlist
String Formatting
Print(“hello %s!” % name)
%s can step in for strings and lists
Print(“%s is %d years old” % (name, age))
%d is for integers
%f is for floating point
%.number of digitsf: floating point with specific number of placeholders
%x/%x: Hex representation (integer lowercase/uppercase)
String Operations
Len(string) gives # of characters inside string
.index(“o”) gives place of character, in this case the letter o
String[3:7] gives characters between 3rd and 7th place
String[3:7:2] gives every other character between 3rd and 7th place
String[::-1] returns the string but backwards
.upper converts all characters of string to uppercase
.lower converts all characters of string to lowercase
.startswith(“object”) returns true if string starts with that object, false if not
.endswith(“object”) same as above
.split(somecharacter) creates a list with multiple entries, split at the character chosen
“**”.join(somelistofstrings) will print string1**string2**string2
Conditions
If, and, or is used (if blah and blah then blah)
Is True or is False used
Elif… else # always end line containing condition with colon
== #equate things for Boolean condition
< or > or <= or >= #greater or less than for Boolean condition
In checks if specified object lies within iterable object container
is does not match values of variables, it checks instances, therefore different than ==
Not operator inverses following Boolean phrase
Loops
Don’t need to put an end on for loops (unlike MATLAB)
Range(3,6) returns a new list of 3,4,5
Xrange(3,6) returns an iterator of 3,4,5
While loop is normal (same as C and MATLAB)
!= is not equal to
Count+=1 is the same as count=count+1
Break used to exit for or while loop
Continue used to skip current block and return to for or while loop
Else can be used as a loop(Unlike C/MATLAB), if break inside for loop, else part is
skipped, else part continued even with continue statement
Can access certain points in a list using iterations, such as:
For i in mylist:
If mylist[i]==2:
Print(“This element is equal to 2”)
Functions
Called using def myfunction(args) (myfunction can be any name)
Use return under def to return a value, string, to the caller
To call the function, after defining, just put myfunction(args) in same script
Can return strings like print statements “%s is a good fit for functions” % benefit
def function(args):
return or print or whatever
myobjectx=MyClass()
To obtain the variable within Myclass (variable is just the name of your variable, can be
anything)
myobjectx.variable
To access the function within a class (remember, function is just the name of whatever
function you created)
Myobjectx.function()
But what if I want to import a Python file into another, but I don’t want to execute the
variables/functions/classes inside this file until I run the entire program?
Use the __main__ declaration, this ensures that variables, functions, classes etc. are
only run when you hit “Run Module”, not when importing.
Ex.
If __name__==__main__
Function 1
Variable1
Class1
Function2
#none of these objects above will be run while importing this file into another
Dictionaries
Accessed using keys instead of indexes
Phonebook={}
Phonebook[“John”]=9385466788 would print out as {‘John’:9385466788}
Could also look like salaries[name]=salary
Can also be initialized like
Phonebook{ “John”: 9385466788}
Can be iterated over, but does not keep the order of the values stored in it, to iterate in
pairs:
For name, numbers in phonebook.items():
Print(“Phone number of %s is %f” % (name,number))
Can use custom import names, useful if you have two modules with similar names
If visual_mode:
Import draw_visual as draw
Else:
Import draw_textual as draw
To tell the Python interpreter where to look for modules, there are two options,
PYTHONPATH and sys.path.append (same as file path in MATLAB)
E.g. PYTHONPATH=/foo python game.py or sys.path.append(“/foo”)
The dir function can be called to see all functions within a module
Dir(urllib)
The help function can be used to see what that function inside the specific module does,
in this case, what the urlopen function does within the urllib function
E.g. help(urllib.urlopen)
Packages are namespaces that contain modules and more packages, like a directory but
With a twist. Each package in Python must have __init__.py: inside, so the directory
recognizes it as a package, and therefore can be called properly. Packages, modules, classes,
functions are a sort of “hierarchy” within Python to increase efficiency.
If we create a package called “foo”, and create a module inside “foo” named “bar”, we
can call it to the mainspace in one of two ways. “foo” must also contain __init__.py: within it so
Python directory recognizes it as a module.
1. Import foo.bar
2. From foo import bar
__init__.py can be used along with __all__ to choose which modules to export, while keeping
other modules internal like such:
__init__.py:
__all__=[“bar”]
Numpy Arrays
Easier to handle, more efficient than lists, gives you more arithmetic capabilities (useful
for data sets)
Automatically indexes with values 0 to end number, can change index “ticker” by such
Brics.index=[“BR”, “RU”, “IN”, “CH”, “SA”] #remember, without specifying index and
append will automatically go to first entry
Indexing: A single bracket will output a Panda Series, double bracket will output Panda
DataFrame. Think of Series as just a single row of data, (1 X N Array)
List Comprehensions
Can be used to pick out certain values/strings in one line
Ex.
numbers = [34.6, -203.4, 44.9, 68.3, -12.2, 44.6, 12.7]
newlist = [round(number) for number in numbers if number > 0 ]
print(newlist)
EX. 2
sentence = "the quick brown fox jumps over the lazy dog"
words = sentence.split()
word_lengths = [len(word) for word in words if word != "the"]
print(words)
print(word_lengths)
Like C and MATLAB, functions can have a specified number of inputs, which can help
with debugging and understanding of your code.
if options.get("number") == "first":
return first
def catch_this():
the_list = (1, 2, 3, 4, 5)
for i in range(20):
try:
do_stuff_with_number(the_list[i])
except IndexError: # Raised when accessing a non-existing index of a list
do_stuff_with_number(0)
catch_this()
Sets
Sets are just lists with no duplicate entries
Print(set(“my name is Eric and Eric is my name”.split()))
This will print {‘my’ , ‘is’, ‘name’, ‘Eric’}, note how there is no order
To see if there is a string/value that is common between two sets, use .intersection
a = set(["Jake", "John", "Eric"])
b = set(["John", "Jill"])
print(a.intersection(b))
print(b.intersection(a))
This will print out {‘John’} {‘John’}
To see everything BUT the common entries between two sets, use .symetric_difference
This function compares two sets simultaneously, so will give two of the same outputs
a = set(["Jake", "John", "Eric"])
b = set(["John", "Jill"])
print(a.symmetric_difference(b))
print(b.symmetric_difference(a))
This prints out {‘Jake, ‘Jill’, ‘Eric’} twice
.difference will compare one set to another, and returns everything BUT the common
value/string and without repeating entries.
print(a.difference(b))
print(b.difference(a))
This prints out {‘Jake, ‘Eric} {‘Jill’}
.union combines two sets into one, and common entries between sets are only
listed/encapsulated once
a = set(["Jake", "John", "Eric"])
b = set(["John", "Jill"])
print(a.union(b))
This prints out {‘John’, ‘Jake’, ‘Jill’, ‘Eric’}
Serialization
This is where it gets complicated, so there’s no need to learn this if you don’t deal with
networks or servers. But if you’re interested, Python can be used to encode and decode JSON.
JSON stands for JavaScript Object Notation, and basically what this section does is show that
Python can read and manipulate JavaScript. JSON is either in a string or object datastructure,
and different functions must be used for each one.
In order to use this function first import json or simplejson if using Python 2.5
You can also just serialize data in Python, to Python. As in, instead of Python data in→ JSON
data out, you can do Python data in→ Python data out. To do this, simply import pickles (or
cpickles), and use the same .loads .dumps functions.
Partial Functions
Not really important, could just call function normally. Advantageous if you have a
function with many constants, but one variable. But basically, replaces first input with entire
function when stated like new=partial(func,var1,var2,etc), then after this new(varremaining)
will execute the original function, with varremaining used as the last variable.
def multiply(x,y):
return x * y
Code Introspection
These built in functions help determine what everything inside a class, function,
keyword is and does.
Closures
Closures can be used to prevent global variables, by using either nested functions/loops
or the nonlocal keyword. This is why spacing is so important in Python.
Ex. 1
def print_msg(number):
def printer():
"Here we are using the nonlocal keyword"
nonlocal number
number=3
print(number)
printer()
print(number)
print_msg(9)
Without nonlocal keyword, we would get “3 9”, but with it, we get “3 3”.
Ex. 2
def transmit_to_space(message):
"This is the enclosing function"
def data_transmitter():
"The nested function"
print(message)
return data_transmitter
Decorators
Just a function which takes in another function and spits a new one out. These are a bit
confusing to learn, but just think when you see @somefunction before another function (let’s
call it newfunc), newfunc replaces the original function defined above in the code. So if you
declare “somefunction(oldfunction)” earlier in the code, newfunc replaces “oldfunction”.
Decorators are basically a way to change nested functions without
@decorator
def functions(arg):
return "value"
Is equivalent to
def function(arg):
return "value"
function = decorator(function) # this passes the function to the decorator, and reassigns
it to the functions
A better example is this:
def repeater(old_function):
def new_function(*args, **kwds): # See
learnpython.org/en/Multiple%20Function%20Arguments for how *args and **kwds
works
old_function(*args, **kwds) # we run the old function
old_function(*args, **kwds) # we do it twice
return new_function # we have to return the new_function, or it wouldn't reassign it
to the value
>>> @repeater Calls the repeater function, and equates “old_function” to “multiply”
function
def multiply(num1, num2):
print(num1 * num2)
>>> multiply(2, 3) Since “multiply” function was set to “old_function”, 6 is printed twice
6
6
We could have decorators to change the output of a function, notice the spacing here
def double_out(old_function): #same as previous example, but repeater changed to
double_out
def new_function(*args, **kwds):
return 2 * old_function(*args, **kwds) # modify the return value
return new_function
Let’s say you want to multiply the output by a variable amount, the following code could
be used to achieve this utilizing decorators
def multiply(multiplier):
def multiply_generator(old_function):
def new_function(*args, **kwds):
return multiplier * old_function(*args, **kwds)
return new_function
return multiply_generator # it returns the new generator
# Usage
@multiply(3) # multiply is not a generator, but multiply(3) is
def return_num(num):
return num
How I understood this example is by looking at the top half of code and bottom half of
code as mirrored “replacements” of functions. When @multiply(3) is called, our
old_function is now set to 3. Below @multiply3 decorator is the return_num function,
so return_num is now equated to “multiplier” value (in this case 5). It’s a bit hard to
explain, so I tried color coding above to help understand.
Ex.
def type_check(correct_type):
def check(old_function):
def funccheck(arg):
if (isinstance(arg, correct_type)):
return old_function(arg)
else:
print("Bad Type")
return funccheck
return check
Ex without map
my_pets = ['alfred', 'tabitha', 'william', 'arla']
uppered_pets = []
print(uppered_pets)
Using map
# Python 3
my_pets = ['alfred', 'tabitha', 'william', 'arla']
uppered_pets = list(map(str.upper, my_pets))
print(uppered_pets)
Str.upper() does not have to be used, map() takes care of this for us. Since str.upper()
needs only one iterable, only my_pets must be called after str.upper.
If we have a function with more than one iterable, say the round() function, we must
add both iterables which follow round(). In this example, we want to round the areas of
circles to one decimal point, then two, then three, etc.
# Python 3
circle_areas = [3.56773, 5.57668, 4.00914, 56.24241, 9.01344, 32.00013]
result = list(map(round, circle_areas, range(1,7)))
print(result)
This prints: [3.6, 5.58, 4.009, 56.2424, 9.01344, 32.00013]
If you use a number of iterables which is less than or more than the desired amount,
Python will stop and return the mapping if number of iterables is too little. If the
number of iterables is too much, Python will run the mapping until it reaches the last
available iteration. Using above example, if range(1,3) is used, Python will print out [3.6,
5.57]. If range(1,300) is used, Python will print same thing [3.6, 5.58, 4.009, 56.2424,
9.01344, 32.00013]. Basically, Python will do what it can with given iterable.
Zip() creates a “tuple” from lists, containing pairs of consecutive elements in a new list.
Ex.
# Python 3
my_strings = ['a', 'b', 'c', 'd', 'e']
my_numbers = [1,2,3,4,5]
results = list(zip(my_strings, my_numbers))
print(results)
This prints: [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
The lambda function is a function that can be created on the spot with no name
associated with it.
# Python 3
my_strings = ['a', 'b', 'c', 'd', 'e']
my_numbers = [1,2,3,4,5]
results = list(map(lambda x, y: (x, y), my_strings, my_numbers))
print(results)
Filter is like the map function, but instead passes iterable objects through Boolean
conditions, and throws away all that are false. It may only be used for functions with
one argument.
Filter(func,iterable)
Ex. 1
# Python 3
scores = [66, 90, 68, 59, 76, 60, 88, 74, 81, 65]
def is_A_student(score):
return score > 75
over_75 = list(filter(is_A_student, scores))
print(over_75)
Reduce(func, iterable[,initial])
If Initial is not provided, Python uses the first element of iterable as initial, then the
second element in iterable becomes the first element in iterable.
Ex.
# Python 3
from functools import reduce
numbers = [3, 4, 6, 9, 34, 12]
def custom_sum(first, second):
return first + second
result = reduce(custom_sum, numbers)
print(result)
This prints 68
This adds the first two elements, returns the sum to reduce, then reduce adds that sum
and the third element, sends it back to reduce, etc. If I were to add an initial term, say
10, then this would print out 78.
def create_list(): # creates a list with 50 random integer entries between 1,100
a=[]
for x in range(1,50):
b=random.randint(1,100)
a.append(b)
return a
print(new_list())
def password_gen():
symbols=["!", "?", "&", ",", "."]
letters_lower=["a", "b", "c", "d", "e", "f", "g", "h", "j", "k", "l"]
string_lowers=str(letters_lower)
letters_upper=string_lowers.upper()
letters_upper=list(letters_upper)
numbers=list(str(range(0,10)))
password=random.sample(total,10)
return password
output1=password_gen()
output3=''.join(output1)
print(output3)
import random
playing=True
winningnum=str(random.randint(1000,9999))
guesses=0
while playing:
guess=input("Give me your guess")
if guess=="exit":
break
cowbullcount=compare_numbers(winningnum,guess)
guesses += 1
if cowbullcount[1]==4:
print("You have won, with %s cows and %s bulls after %d tries"\
% (str(cowbullcount[1]), str(cowbullcount[0]), guesses))