Functions | UCB CS61A – 23 Spring

发布于 14 天前  48 次阅读


Functions

Experessions

Types of expressions

An expression describes a computation and evaluates to a value.

Call Expressions in Python

All expressions can use function call notation.

Anatomy of a Call Expression

add(2,3)
add => Operator
2,3 => Operands

Operators and operands are also expressions. So they evaluate to values.

Evalutaion procedure for call expressions

  1. Evaluate the operator and then the operands subexpressions
  2. Apply the function that is the value of the operator subexpression to the arguments that are the values of the operand subexpressions

Evaluating Nested Expressions

mul(add(2,mul(4,6)), add(3,5))

Names, Assignment, and User-Defined Functions

Primitive expressions:

  • 2 : Number or Numeral
  • add : Name
  • 'hello': String

Call expressions:

max(2,3)

  • max : Operator
  • 2,3 : Operands

An operand can also be a call expression

Question 1

What is the value of the final expression in the following sequence of expressions?

f = min
f = max
g, h = min, max
max = g
max(f(2, g(h(1, 5), 3)), 4)

Answer: 3

Environment Diagrams

Environment diagrams visualize the interpreter's process

Assignment Statements

Execution rule for assignment statements:

  1. Evaluate all expressions to the right of = form left to right
  2. Bind all names to the left of = to the resulting values in the current frame

Defining Functions

Assignment is a simple means of abstraction: binds names to values

Function definition is a more powerful means of abstraction: binds names to expressions

def <name>(<formal parameters>):
    return <return expression>

Execution procedure for def statements:

  1. Create a function with signature ()
  2. Set the body of that function to be everything indented after the first line
  3. Bind to that function in the current frame

Calling User-Defined Functions

Procedure for calling a user-defined function:

  1. Add a local frame, forming a new environment
  2. Bind the formal parameters to the arguments
  3. Execute the body of the function in the new environment

Looking Up Names In Environments

Every expression is evaluated in the context of an environment

So far, the current environment is either:

  • The global frame alone, or
  • A local frame, followed by the global frame

Most important

An environment is a sequence of frames.

A name evaluates to the value bound to that name in the first frame in the sequence where that name is found.

E.g., to look up some name in the body of the square function:

  • Look for that name in the local frame.
  • If not found, look for it in the global frame.(Built-in names like "max" are in the global frame too, but we don't draw them in environment diagrams.)

Homework

from operator import add, sub

def a_plus_abs_b(a, b):
    """Return a+abs(b), but without calling abs.

    >>> a_plus_abs_b(2, 3)
    5
    >>> a_plus_abs_b(2, -3)
    5
    >>> a_plus_abs_b(-1, 4)
    3
    >>> a_plus_abs_b(-1, -4)
    3
    """
    if b < 0:
        f = sub
    else:
        f = add
    return f(a, b)

def a_plus_abs_b_syntax_check():
    """Check that you didn't change the return statement of a_plus_abs_b.

    >>> # You aren't expected to understand the code of this test.
    >>> import inspect, re
    >>> re.findall(r'^\s*(return .*)', inspect.getsource(a_plus_abs_b), re.M)
    ['return f(a, b)']
    """
    # You don't need to edit this function. It's just here to check your work.

def two_of_three(i, j, k):
    """Return m*m + n*n, where m and n are the two smallest members of the
    positive numbers i, j, and k.

    >>> two_of_three(1, 2, 3)
    5
    >>> two_of_three(5, 3, 1)
    10
    >>> two_of_three(10, 2, 8)
    68
    >>> two_of_three(5, 5, 5)
    50
    """
    return min(i, j, k)**2 + max(min(j, k), min(i,k), min(i,j))**2

def two_of_three_syntax_check():
    """Check that your two_of_three code consists of nothing but a return statement.

    >>> # You aren't expected to understand the code of this test.
    >>> import inspect, ast
    >>> [type(x).__name__ for x in ast.parse(inspect.getsource(two_of_three)).body[0].body]
    ['Expr', 'Return']
    """
    # You don't need to edit this function. It's just here to check your work.

def largest_factor(n):
    """Return the largest factor of n that is smaller than n.

    >>> largest_factor(15) # factors are 1, 3, 5
    5
    >>> largest_factor(80) # factors are 1, 2, 4, 5, 8, 10, 16, 20, 40
    40
    >>> largest_factor(13) # factor is 1 since 13 is prime
    1
    """
    "*** YOUR CODE HERE ***"
    num = 1
    for i in range(n):
        if not(i == 0):
            if n % i == 0:
                num = max(num, i)
    return num

def hailstone(n):
    """Print the hailstone sequence starting at n and return its
    length.

    >>> a = hailstone(10)
    10
    5
    16
    8
    4
    2
    1
    >>> a
    7
    >>> b = hailstone(1)
    1
    >>> b
    1
    """
    "*** YOUR CODE HERE ***"
    t = 1
    while (n != 1):
        if n % 2 == 0:
            t+=1
            print(n)
            n=int(n/2)
        else:
            t+=1
            print(n)
            n = n*3+1
    print(1)
    return t