Just to keep the computational model straight, we are using:
print
not needed to see the last un-captured value in a cellJupyter notebook -> IPython -> Python
----------------- ------------------ ------------------
This is what you Checks for special Does the real work
see syntax, then sends
it on
Note: The very new JupyterLab takes this one step further, by providing an nice environment for notebooks, which themselves are an environment for IPython... It's really nice and beautiful, though.
Computing can be broken down to two things:
# This is a variable
variable = 3
# This is a function
def function(x):
return pow(x, 2)
function(variable)
Don't worry about the details of the Python syntax quite yet, just focus on the two concepts: data and procedures. And, yes, x**2
is nicer than pow(x,2)
.
The great thing about programming in an interpreted language like Python is that you can try everything yourself, in real time. Play around with the above variables and answer these questions:
def
? Why or why not?pow
? Why or why not?pow
?pow
? (Hint: Try del
or restarting your kernel (top menu)).#
and are ignored by PythonNote: Builtins can't be undefined due to the way the Python lookup system works.
# Does not take anything or return anything
def funct():
"This is the function documentation"
print("Called f", 1 * 1, "time")
Operators, Keywords, Builtins, Numbers, Strings, Comments
We can go one step further from variables and functions: objects and classes.
Why are objects so important in Python? Because unlike many other languages, everything in Python is an object! This is very powerful.
Note: Syntax such as keywords are not objects. (though builtins are)
number = 1.5
string = "hello world"
complex_number = 2 + 3j
Try running some of the methods and look at the members of the objects defined above.
IPython + Jupyter keyboard hints:
.
We can use type
to see the class of an object:
type(number)
There are certain conventions for the names of objects and classes:
Case | Convention | Example |
---|---|---|
Objects and methods | start with lower case letter | like_this |
Classes | Start with upper case letter | LikeThis |
Globals | all uppercase | LIKE_THIS |
Hidden | start with underscore | _like_this |
In one class only | start with two underscores (rarely used) | __like_this |
Special python names | start and end with two underscores | __like_this__ |
Exceptions for some Python built-in types, which are all lowercase. And True
, False
, None
, and Ellipsis
, which are objects but are capitalized.
The following are a mostly comprehensive list of built-in Python types
py_int = 101
py_float = 3.7
py_complex = 1j
py_str = "Unicode string: Python 3 is 😀"
py_bytes = b"Binary string"
py_bool = True
py_none = None
These types are all also constructible by calling the name of the type, such as int(1)
. A few interesting notes:
int("1")
b
. We'll see this again someday."
or '
. Three quotes can be used to include new lines.None
is the only none type. How lonely.These are composed, but are also very important
py_tuple = (1, 2, 3)
py_list = [1, 2, 3]
py_dict = {"Python 3": "😍", "Python 2": "😖"}
py_set = {"no", "duplicates", "in", "here"}
Accessing values is done with brackets:
print(py_tuple[0])
print(py_dict["Python 3"])
Mutable | Immutable |
---|---|
Can be changed | Can only be replaced |
Can be a key or in a set | Can't be a key or in a set |
list , dict , set |
tuple , str , int , etc. |
[]
to get items from it)There are other types in the standard library, but we'll restrict ourselves to talking about these for now.
If you could put a mutable item in as a key or set item, you could then change it later and have two identical key items or set items!
Can you guess what the final value of a
is? What about b
?
a = [1, 2, 3, 4]
b = a
b[2] = "😡"
b = [3, 2, 1, 3]
b[2] = None
print(a, b)
Key points to understanding this example:
There are a limited number of expressions allowed on the left (but they can be chained):
a =
a[x] =
a.x =
One of the most important things in computation is indexing, and Python is really good at it. You've already seen integers being used to index lists (strings work the same way too), but let's peek at another way to index lists and tuples: slicing.
a = "abcdefg"
print(a)
print(a[0:7:1]) # start : stop (not included) : step
print(a[0:7]) # step not needed
print(a[1:]) # you can leave out values
print(a[:-1]) # like indexing, - means from end
print(a[::2])
Python's operators are pretty standard. Here are the ones that tend to be a little odd:
x**y
: Raise x
to a power y
x == y
: See if x
is equal to y
x is y
: See if x
is the same object (in the same spot in memory) as y
, can't be overriden~x
: Invert x
(might be different than unary -
)+x
: Python does have a unary +
operator, too. Not sure why you'd want it.x += y
: Add y to x, in place only if mutablex / y
: True mathematical division (Py3 default, Py2 option)x // y
: Truncating divisionx @ y
: Matrix product of x and y (Python 3.5+, only in libraries)x and y
: Boolean operator, short-circuits and can't be overriden (or
and not
too)x & y
: Bitwise and - this one can be overriden, but has odd precedencex | y
: Bitwise orWe've already seen functions. What other control statements are out there for use to use?
x = True
if x:
print("x was true")
else:
print("x was not true")
The for each loop works on any iterable:
a = "abcdefg"
for item in a:
print(item, sep=", ")
You can also use for item in range(N)
to count over a range of values, or while CONDITION:
.
You can use for
(and if
) inside []
, ()
, or {}
to build the data structures mentioned above inplace.
bad_way_to_make_a_set_of_tens = {x for x in range(100) if x % 10 == 0}
bad_way_to_make_a_set_of_tens
There are other useful things in Python we will cover later, but the with
statement is too good to wait. With lets you take code like this:
f = open(filename)
txt = f.read()
f.close() # Don't forget me!
and write instead:
with open(filename) as f:
txt = f.read()
# File automatically closed here!
With simply runs code at the start and at the end of a block. It also promises the code at the end runs, even if there's an error! (More about errors later)
You may have noticed that each new concept in programming restricts rather than enables. If we went further into topics like functional program, this would continue to be the case. This is odd but true: we could write any program with a very small set of constructs. However, the most important feature of programming is organization (also called design).
Compare this hypothetical pseudo-code:
i = 0
label start
compute(i)
i = i + 1
if i < 10: goto start
Verses real code:
for i in range(10):
compute(i)
Now imagine a complex program with 1,000 of goto
statements; you would have to work through every line of code to understand it. But if you restrict yourself to common structures, like loops, objects, functions, etc., you no longer have to look at the whole program, but just parts you recognize.
You should:
Objects are very good for the second two points (and so-so for the first).
Also notice the running theme above?