CMU 15-112: Fundamentals of Programming and Computer Science
Class Notes: Data and Expressions


  1. Some Builtin Types
  2. Some Builtin Constants
  3. Some Builtin Functions
  4. Some Builtin Operators
  5. Types Affect Semantics
  6. Integer Division
  7. The Modulus or Remainder operator (%)
  8. Operator Order (Precedence and Associativity)
  9. Approximate Values of Floating-Point Numbers
  10. Short-Circuit Evaluation

  1. Some Builtin Types
    import math def f(): print("This is a user-defined 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 (user-defined 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)

  2. 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)

  3. 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

  4. Some Builtin Operators
    CategoryOperators
    Arithmetic+, -, *, /, //, **, %, - (unary), + (unary)
    Relational <, <=, >=, >, ==, !=
    Assignment+=, -=, *=, /=, //=, **=, %=, <<=, >>=
    Logicaland, or, not
    Note: for now at least, we are not covering the bitwise operators (<<, >>, &, |, ^, ~, &=, |=, ^=).

  5. Types Affect Semantics
    print(3 * 2) print(3 * "abc") print(3 + 2) print("abc" + "def") print(3 + "def")

  6. 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))

  7. 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))

  8. 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(5-4-3) # prints -2, not 4 (- associates left-to-right) print(4**3**2) # prints 262144, not 4096 (** associates right-to-left)

  9. Approximate Values of Floating-Point 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.55111512313e-17 (tiny, but non-zero!)

    Equality Testing with almostEqual:
    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...") epsilon = 10**-10 print(abs(d2 - d1) < epsilon) # True! print() print("Once again, using a useful helper function, almostEqual:") def almostEqual(d1, d2): epsilon = 10**-10 return (abs(d2 - d1) < epsilon) d1 = 0.1 + 0.1 + 0.1 d2 = 0.3 print(d1 == d2) # still False, of course print(almostEqual(d1, d2)) # True, and now packaged in a handy reusable function!

  10. Short-Circuit 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 short-circuiting)

    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 short-circuiting)

    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!