This notebook was put together by [Jake Vanderplas](http://www.vanderplas.com) for UW's [Astro 599](http://www.astro.washington.edu/users/vanderplas/Astr599_2014/) course. Source and licensing info is on [GitHub](https://github.com/jakevdp/2014_fall_ASTR599/).


In [122]:
%run talktools.py


Basic Training

Much of this material thanks to http://www.pythonbootcamp.info/

Outline

  • ### Python is easy! Hello world revisited
  • ### Calculator / basic math
  • ### Strings
  • ### Variables
  • ### Basic control statements (indentation!)

Hello World!

We saw before how easy a hello world script is to create in Python:


In [123]:
print("Hello World!")


Hello World!

Some other languages...

http://www.roesler-ac.de/wolfram/hello.htm

Python

file: hello.py

print "Hello World!"


[~]> python hello.py

Java

file: hello.java

class HelloWorld {
  static public void main( String args[] ) {
    System.out.println( "Hello World!" );
  }
}


[~]> javac hello.java
[~]> java HelloWorld
Hello World!

C++

file: hello.cpp

#include <iostream>
int main()
{
  std::cout << "Hello World!" << std::endl;
}


[~]> g++ -o hello hello.cpp
[~]> ./hello
Hello World!

Fortran

file: hello.f

    PROGRAM HELLO
    WRITE (*,100)
    STOP
100 FORMAT (' Hello World! ' /)
    END


[~]> g77 -o hello hello.f
[~]> ./hello
Hello World!

Two Points

  • Python provides interaction in both development and execution
  • Executing interactively is basically the same thing as executing a script, line-by-line

Types and Operations: Python as a Calculator

We'll talk about a few types here:

  • int: integer
  • float: floating point (decimal)
  • long: long integer
  • complex: complex number (decimal, not integer)

We'll also introduce the basic arithmetic operations

  • + : addition
  • -: subtraction
  • /: division
  • *: multiplication
  • %: modulus (remainder)
  • **: exponentiation

As we go through this, note carefully how these operations interact with various types


In [124]:
print(2 + 2)


4

In [125]:
2 + 2


Out[125]:
4

In [126]:
print(2.1 + 2)


4.1

Careful: floats are limited by their 16-bit representation (same as in other languages)


In [127]:
print(4.0999999999999995)


4.1

In [128]:
2.1 + 2 == 4.0999999999999995


Out[128]:
True

In [129]:
4 * 2


Out[129]:
8

In [130]:
4 / 2


Out[130]:
2.0

In [131]:
5 / 2  # Note this is different in Python 2.x!!


Out[131]:
2.5

In [132]:
5 // 2


Out[132]:
2

Integer operations result in integers in Python 2.x, but floats in Python 3.x.


In [133]:
5 % 2  # modulus (remainder after division)


Out[133]:
1

In [134]:
5 ** 2


Out[134]:
25

In [135]:
# or you can use the pow() function
pow(5, 2)


Out[135]:
25

Indentation Matters!


In [136]:
print(2 + 2)
   3 + 3


  File "<ipython-input-136-25c65360fa6d>", line 2
    3 + 3
    ^
IndentationError: unexpected indent

Use # for comments

  • Everything after the # will be ignored

In [137]:
print(1 + 1)  # easy arithmetic


2

Complex types


In [138]:
complex(1,2)


Out[138]:
(1+2j)

In [139]:
1+2j


Out[139]:
(1+2j)

In [140]:
1 + 2j - 2j


Out[140]:
(1+0j)

In [141]:
(3.0*10.0 - 25.0)/5.0


Out[141]:
1.0

In [142]:
print(3.085e18 * 1e6)  # this is a Megaparsec in units of cm!


3.085e+24

Assigning variables


In [143]:
t = 1.0  # declare a variable t (time)
accel = 9.8  # acceleration in units of m/s^2

# distance travelled in time t seconds is 1/2 a*t**2
dist = 0.5*accel*t*t
print(dist) # this is the distance in meters


4.9

In [144]:
dist1 = accel*(t**2)/2
print(dist1)


4.9

In [145]:
dist2 = 0.5*accel*pow(t,2)
print(dist2)


4.9

A nice trick that other languages can't do:


In [146]:
x, y = 4, 50
print(x)
print(y)


4
50

In [147]:
x, y = y, x  # easy swap!
print(x)
print(y)


50
4

Each operator has an operate-and-assign version


In [148]:
x = 4
x += 8  # same as x = x + 8
print(x)


12

In [149]:
x *= 0.2  # x is upgraded to a float!
print(x)


2.4000000000000004

In [150]:
x %= 1
print(x)


0.40000000000000036

Bitwise Operators

You might also come across bitwise operators:

  • &: bitwise and
  • |: bitwise or
  • ^: bitwise xor
  • <<: bit-shift left
  • >>: bit-shift right

All these make more sense if you think about binary representations:


In [151]:
bin(14)  # print binary representation


Out[151]:
'0b1110'

In [152]:
bin(13)


Out[152]:
'0b1101'

In [153]:
14 & 13


Out[153]:
12

In [154]:
bin(14 & 13)


Out[154]:
'0b1100'

In [155]:
14 | 13


Out[155]:
15

In [156]:
bin(14 | 13)


Out[156]:
'0b1111'

Comparison operators

  • ==, !=: equal, not equal
  • <, <=: less than, less than or equal
  • >, >=: greater than, greater than or equal

In [157]:
2 < 4


Out[157]:
True

In [158]:
3 >= 3


Out[158]:
True

In [159]:
5 == 4


Out[159]:
False

In [160]:
5 != 4


Out[160]:
True

In [161]:
5 < 2 + 4j


---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-161-22831f5cf00f> in <module>()
----> 1 5 < 2 + 4j

TypeError: unorderable types: int() < complex()

Comparisons can also be strung together and behave as expected:


In [162]:
x = 4
y = 6
print(2 < x <= 4)
print(2 < y <= 4)


True
False

In [163]:
# This allows strange/confusion expressions
# don't do things like this!
8 > x <= 5


Out[163]:
True

Warning about Floating Point Equality

Precision issues can lead to seemingly strange results (again, this is the same in any modern programming language)


In [164]:
0.1 + 0.2 == 0.3


Out[164]:
False

In [165]:
# this is a string formatting command (we'll cover this later)
# it says to print 20 places after the decimal
print("{0:.20f}".format(0.1 + 0.2))
print("{0:.20f}".format(0.3))


0.30000000000000004441
0.29999999999999998890

Moral of the story: in any language you use, be careful using equality comparisons on floating point!

Boolean variables and logical operations

Python has two built-in boolean values, True and False which we've seen above.

There are also built-in logical operations to test these

  • A or B : True if either A or B or both are True
  • A and B : True only if both A and B are True
  • not A: True only if A is False

In [166]:
x = 4
(x > 2) and (x < 10)


Out[166]:
True

In [167]:
(x <= 4) or not (x > 10)


Out[167]:
True

Built-in types can be coerced to booleans.


In [168]:
0 == False


Out[168]:
True

In [169]:
not False


Out[169]:
True

In [170]:
not 0


Out[170]:
True

In [171]:
not -1


Out[171]:
False

zero is evaluated to False, every other number to True


In [172]:
print(None)  # None is a special object


None

In [173]:
print(None == True)
print(None == False)
print(None == None)
print(bool(None))


False
False
True
False

Special comparators: is and is not


In [174]:
x = 1
y = 1
x is y


Out[174]:
True

In [175]:
x = 1111
y = 1111
print(x is y)


False

Takeaway: "is" and "is not" refer to the memory being used by the object. If x and y point to the same location in memory, then x is y will be True.

Probably their most common use is in comparisons to None. All variables equal to None are guaranteed to point to the same memory location (i.e. it acts as a Singleton).


In [176]:
x = None
print(x is None)


True

You don't need to fully understand this, but just be aware that the is and is not operators should generally not be used unless you do!

More on Variables & Types


In [177]:
print(type(1))


<class 'int'>

In [178]:
x = 2
print(type(x))


<class 'int'>

In [179]:
type(2) == type(1)


Out[179]:
True

In [180]:
print(type(True))


<class 'bool'>

In [181]:
print(type(None))


<class 'NoneType'>

In [182]:
print(type(type(1)))


<class 'type'>

In [183]:
print(type(pow))


<class 'builtin_function_or_method'>

we can test whether something is a certain type with isinstance()


In [184]:
print(isinstance(1, int))
print(isinstance("spam", str))
print(isinstance(1.212, int))


True
True
False

builtin-types: int, bool, str, float, complex, long....

Strings


In [185]:
x = "spam" ; type(x)


Out[185]:
str

In [186]:
print("hello!\n...my sire.")


hello!
...my sire.

In [187]:
"hello!\n...my sire."


Out[187]:
'hello!\n...my sire.'

In [188]:
"wah?!" == 'wah?!'


Out[188]:
True

In [189]:
print("'wah?!' said the student")


'wah?!' said the student

In [190]:
print("\"wah?!\" said the student")


"wah?!" said the student

backslashes (\) start special (escape) characters:

 \n   = newline  (\r = return)
 \t   = tab
 \a   = bell

string literals are defined with double quotes or quotes. the outermost quote type cannot be used inside the string (unless it's escaped with a backslash)


In [191]:
# raw strings (marked with r) don't escape characters
print(r'This is a raw string...newlines \r\n are ignored.')


This is a raw string...newlines \r\n are ignored.

In [192]:
# Triple quotes are real useful for multiple line strings
y = """For score and seven minutes ago,
    you folks all learned some basic mathy stuff with Python
    and boy were you blown away!"""
print(y)


For score and seven minutes ago,
    you folks all learned some basic mathy stuff with Python
    and boy were you blown away!
  • prepending r makes that string "raw"
  • triple quotes allow you to compose long strings
  • prepending u makes that string "unicode"

http://docs.python.org/reference/lexical_analysis.html#string-literals

Arithmetic with Strings


In [193]:
s = "spam" ; e = "eggs"
print(s + e)


spameggs

In [194]:
print(s + " and " + e)


spam and eggs

In [195]:
print("green " + e + " and\n " + s)


green eggs and
 spam

In [196]:
print(s*3 + e)


spamspamspameggs

In [197]:
print("*" * 50)


**************************************************

In [198]:
print("spam" == "good"); print("spam" == "spam")


False
True

In [199]:
"spam" < "zoo"


Out[199]:
True

In [200]:
"s" < "spam"


Out[200]:
True
  • you can concatenate strings with + sign
  • you can do multiple concatenations with the * sign
  • strings can be compared

But you can't add strings and integers:


In [201]:
print('I want' + 3 + ' eggs and no ' + s)


---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-201-fbc395a7f2be> in <module>()
----> 1 print('I want' + 3 + ' eggs and no ' + s)

TypeError: Can't convert 'int' object to str implicitly

In [202]:
print('I want ' + str(3) + ' eggs and no ' + s)


I want 3 eggs and no spam

In [203]:
pi = 3.14159
print('I want ' + str(pi) + ' eggs and no ' + s)


I want 3.14159 eggs and no spam

In [204]:
print(str(True) + ":" + ' I want ' + str(pi) + ' eggs and no ' + s)


True: I want 3.14159 eggs and no spam

you must concatenate only strings, coercing ("casting") other variable types to str

Getting input from the user


In [205]:
# Note that raw_input does not work in IPython notebook version < 1.0
# You can always do this from a file or from the command line, though
faren = input("enter a temperature (in Fahrenheit): ")
print(faren)


enter a temperature (in Fahrenheit): 280
280

(Note that in Python 2.x you should use raw_input rather than input

Remember that the input comes as a string:


In [206]:
cent = (faren - 32) / 1.8


---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-206-692d7634602b> in <module>()
----> 1 cent = (faren - 32) / 1.8

TypeError: unsupported operand type(s) for -: 'str' and 'int'

In [207]:
cent = (float(faren) - 32) / 1.8
print(cent)


137.77777777777777

In [208]:
# Or in one line:
faren = float(input("enter a temperature (in Fahrenheit): "))
(faren - 32) / 1.8


enter a temperature (in Fahrenheit): 232
Out[208]:
111.11111111111111

Strings as arrays

We can think of strings as arrays (although, unlike in C you never really need to deal with directly addressing character locations in memory)


In [209]:
s = 'spam'
len(s)


Out[209]:
4

In [210]:
len("eggs\n")


Out[210]:
5

In [211]:
len("")


Out[211]:
0

Indexing in Python is zero-based


In [212]:
print(s[0])
print(s[-1])


s
m

In [213]:
s[0:1]


Out[213]:
's'

In [214]:
s[1:4]


Out[214]:
'pam'

In [215]:
s[-2:]


Out[215]:
'am'

In [216]:
s[0:100]  # if the slice goes past the end, no complaints!


Out[216]:
'spam'

In [217]:
s[0:4:2]


Out[217]:
'sa'

In [218]:
s[::2]


Out[218]:
'sa'

In [219]:
s[::-1]


Out[219]:
'maps'
  • len() gives us the length of an array
  • strings are zero indexed
  • can also count backwards

Flow control: conditionals and loops


In [220]:
x = 1
if x > 0:
    print("yo")
else:
    print("dude")


yo

One liners


In [221]:
"yo" if x > 0 else "dude"


Out[221]:
'yo'

In [222]:
x = 1
y = 0
while y < 10:
    print("yo" if x > 0 else "dude")
    x *= -1
    y += 1


yo
dude
yo
dude
yo
dude
yo
dude
yo
dude

In [223]:
# Could also do this with a break statement
x = 1
y = 0
while True:
    print("yo" if x > 0 else "dude")
    x *= -1
    y += 1
    if y >= 10:
        break


yo
dude
yo
dude
yo
dude
yo
dude
yo
dude

case statements can be constructed with just a bunch of if, elif,...else


In [224]:
if x < 1:
    print("t")
elif x > 100:
    print("yo")
elif x == 42:
    print("bingo")
else:
    print("dude")


dude

Note: ordering matters. The first block of True in an if/elif gets executed then everything else does not.

Blocks cannot be empty!


In [225]:
x = "fried goldfish"
if x == "spam for dinner":
    print("I will destroy the universe")
else:
    # I'm fine with that. I'll do nothing


  File "<ipython-input-225-51470879c358>", line 5
    # I'm fine with that. I'll do nothing
                                         ^
SyntaxError: unexpected EOF while parsing

In [226]:
x = "fried goldfish"
if x == "spam for dinner":
    print("I will destroy the universe")
else:
    # I'm fine with that. I'll do nothing
    pass

pass is a "do nothing"/NOP statement

Example: putting it all together


In [227]:
%%file number_game.py
# The above "magic" command saves the contents
# of the current cell to file.  We'll see more of these later

x = 0
max_tries = 10
count = 0

while True:
    x_new = int(input("Enter a new number: "))
    if x_new > x:
        print(" -> it's bigger than the last!")
    elif x_new < x:
        print(" -> it's smaller than the last!")
    else:
        print(" -> no change!  I'll exit now")
        break
        
    x = x_new
        
    count += 1
    if count > max_tries:
        print("too many tries...")
        break


Overwriting number_game.py

In [229]:
%run number_game.py
# this magic command runs the given file


Enter a new number: 200
 -> it's bigger than the last!
Enter a new number: 200
 -> no change!  I'll exit now

Breakout #1: getting your code on

Create a program (a .py file) which repeatedly asks the user for a word. The program should append all the words together. When the user types a "!", "?", or a ".", the program should print the resulting sentence and exit.

For example, a session might look like this:

[~]$ python breakout01.py
Enter a word (. ! or ? to end): My
Enter a word (. ! or ? to end): name
Enter a word (. ! or ? to end): is
Enter a word (. ! or ? to end): Walter
Enter a word (. ! or ? to end): White
Enter a word (. ! or ? to end): !

My name is Walter White!

Breakout #2: Fizz Buzz (a classic)

Write a program that prints the numbers from 1 to 100. But for multiples of three print “Fizz” instead of the number and for the multiples of five print “Buzz”. For numbers which are multiples of both three and five print “FizzBuzz”.

If you finish quickly... see how few characters you can write this program in (this is known as "code golf": going for the fewest key strokes).