 Some Builtin Types
import math
def f():
print("This is a userdefined function")
return 42
print("Some basic types in Python:")
print(type(2)) # int
print(type(2.2)) # float
print(type("2.2")) # str (string)
print(type(2 < 2.2)) # bool (boolean)
print(type(math)) # module
print(type(math.tan)) # builtin_function_or_method ("function" in Brython)
print(type(f)) # function (userdefined function)
print(type(type(42))) # type
print("#####################################################")
print("And some other types we will see later in the course...")
print(type(Exception())) # Exception
print(type(range(5))) # range
print(type([1,2,3])) # list
print(type((1,2,3))) # tuple
print(type({1,2})) # set
print(type({1:42})) # dict (dictionary or map)
print(type(2+3j)) # complex (complex number) (we may not see this type)
 Some Builtin Constants
print("Some builtin constants:")
print(True)
print(False)
print(None)
print("And some more constants in the math module:")
import math
print(math.pi)
print(math.e)
 Some Builtin Functions
print("Type conversion functions:")
print(bool(0)) # convert to boolean (True or False)
print(float(42)) # convert to a floating point number
print(int(2.8)) # convert to an integer (int)
print("And some basic math functions:")
print(abs(5)) # absolute value
print(max(2,3)) # return the max value
print(min(2,3)) # return the min value
print(pow(2,3)) # raise to the given power (pow(x,y) == x**y)
print(round(2.354, 1)) # round with the given number of digits
 Some Builtin Operators
Category  Operators 
Arithmetic  +, , *, /, //, **, %,  (unary), + (unary) 
Relational  <, <=, >=, >, ==, != 
Assignment  +=, =, *=, /=, //=, **=, %= 
Logical  and, or, not 
Note: for now at least, we are not covering the bitwise operators (<<, >>, &, , ^, ~).
 Types Affect Semantics
print(3 * 2)
print(3 * "abc")
print(3 + 2)
print("abc" + "def")
print(3 + "def")
 Integer Division
print("The / operator does 'normal' float division:")
print(" 5/3 =", ( 5/3))
print()
print("The // operator does integer division:")
print(" 5//3 =", ( 5//3))
print(" 2//3 =", ( 2//3))
print("1//3 =", (1//3))
print("4//3 =", (4//3))
 The Modulus or Remainder Operator (%)
print(" 6%3 =", ( 6%3))
print(" 5%3 =", ( 5%3))
print(" 2%3 =", ( 2%3))
print(" 0%3 =", ( 0%3))
print("4%3 =", (4%3))
print(" 3%0 =", ( 3%0))
Verify that (a%b) is equivalent to (a  (a//b)*b):
def mod(a, b):
return a  (a//b)*b
print(41%14, mod(41,14))
print(14%41, mod(14,41))
print(32%9, mod(32,9))
print(32%9, mod(32,9))
 Operator Order (Precedence and Associativity)
print("Precedence:")
print(2+3*4) # prints 14, not 20
print(5+4%3) # prints 6, not 0 (% has same precedence as *, /, and //)
print(2**3*4) # prints 32, not 4096 (** has higher precedence than *, /, //, and %)
print()
print("Associativity:")
print(543) # prints 2, not 4 ( associates lefttoright)
print(4**3**2) # prints 262144, not 4096 (** associates righttoleft)

Bitwise Operators

Approximate Values of FloatingPoint Numbers
print(0.1 + 0.1 == 0.2) # True, but...
print(0.1 + 0.1 + 0.1 == 0.3) # False!
print(0.1 + 0.1 + 0.1) # prints 0.30000000000000004 (uh oh)
print((0.1 + 0.1 + 0.1)  0.3) # prints 5.55111512313e17 (tiny, but nonzero!)
Equality Testing with math.isclose:
print("The problem....")
d1 = 0.1 + 0.1 + 0.1
d2 = 0.3
print(d1 == d2) # False (never use == with floats!)
print()
print("The solution...")
import math
print(math.isclose(d1, d2)) # True!
# math.isclose checks if the two numbers are ALMOST equal, within a small error
 ShortCircuit Evaluation
def yes():
return True
def no():
return False
def crash():
return 1/0 # crashes!
print(no() and crash()) # Works!
print(crash() and no()) # Crashes!
print (yes() and crash()) # Never runs (due to crash), but would also crash (without shortcircuiting)
Once again, using the "or" operator:
def yes():
return True
def no():
return False
def crash():
return 1/0 # crashes!
print(yes() or crash()) # Works!
print(crash() or yes()) # Crashes!
print(no() or crash()) # Never runs (due to crash), but would also crash (without shortcircuiting)
Yet another example:
def isPositive(n):
result = (n > 0)
print("isPositive(",n,") =", result)
return result
def isEven(n):
result = (n % 2 == 0)
print("isEven(",n,") =", result)
return result
print("Test 1: isEven(4) and isPositive(4))")
print(isEven(4) and isPositive(4)) # Calls both functions
print("")
print("Test 2: isEven(3) and isPositive(3)")
print(isEven(3) and isPositive(3)) # Calls only one function!
 type vs isinstance
# Both type and isinstance can be used to typecheck
# In general, (isinstance(x, T)) will be more robust than (type(x) == T)
print(type("abc") == str)
print(isinstance("abc", str))
# We'll see better reasons for this when we cover OOP + inheritance later
# in the course. For now, here is one reason: say you wanted to check
# if a value is any kind of number (int, float, complex, etc).
# You could do:
def isNumber(x):
return ((type(x) == int) or
(type(x) == float)) # are we sure this is ALL kinds of numbers?
print(isNumber(1), isNumber(1.1), isNumber(1+2j), isNumber("wow"))
# But this is cleaner, and works for all kinds of numbers, including
# complex numbers for example:
import numbers
def isNumber(x):
return isinstance(x, numbers.Number) # works for any kind of number
print(isNumber(1), isNumber(1.1), isNumber(1+2j), isNumber("wow"))