《Composing Programs》(SICP python版) chap1 笔记(2)

news2024/11/17 15:50:19

《Composing Programs》(SICP python版) chap1 笔记(2)

文章目录

  • 《Composing Programs》(SICP python版) chap1 笔记(2)
  • Chapter 1: Building Abstractions with Functions
    • 1.3 Defining New Functions
      • 1.3.1 Environments
        • Function Signatures(看语境翻译为函数原型比较好)
      • 1.3.2 Calling User-Defined Funcitons
        • Name Evaluation
      • 1.3.3 Example: Calling a User-Defined Function
      • 例1(我把1.3.2的搬过来了)
      • 例2
      • 1.3.4 Local Names
      • 1.3.5 Choosing Names
      • 1.3.6 Funcitons as Abstractions
        • Aspects of a functional abstraction
      • 1.3.7 Operations
    • 1.4 Designing Functions
      • 1.4.1 Documentation
        • Comment 注释
      • 1.4.2 Default Argument Values
    • 1.5 Control
      • 1.5.1 Statements
      • 1.5.2 Compound Statements
      • 1.5.3 Defining Functions II: Local Assignment
      • 1.5.4 Conditional Statements
      • 1.5.5 Iteration
      • 1.5.6 Testing
        • Assertions
        • Doctests
  • basic knowledge and skills
    • 连接阿里云服务器
    • 给阿里云服务器配置图形界面
      • 第一次配置(之前配置过了,现在来review一下)
      • 之后日常使用
      • VNC Viewer 无法复制粘贴
    • Infix notation 中缀表达式
    • python语法糖之多重赋值
  • 致敬一下python tutor的作者 Or2
  • 总结
  • 总结
  • 相关资源

呃 下面很多笔记是直接照搬的textbook,其实很多地方是想积累英文表达,
但这样子就缺乏了自己概括的过程,从下一篇笔记开始把积累英文表达和概括给分开来…

不要嫌配置环境麻烦, 这次代码用阿里云服务器来跑,再熟悉一下各种操作

Chapter 1: Building Abstractions with Functions

下面会介绍很多代码风格,感觉给出的python 官方的一些链接也要自己去看看

1.3 Defining New Functions

  • 这里是怎么介绍abstraction 的呢

    • Binding names to values provides a limited means of abstraction
    • function definitions, a much more powerful abstraction technique by which a name can be bound to compound operation, which can be referred to as a unit.
  • How to define a function

    • Function consists of a def statement that idicates a <name> and a comma-separated list of named <formal parameters>, then a return statement, called the function body, that specifies the <return expression> of the function, which is an expression to be evaluated whenever the function is applied:

      def <name> (<formal parameters>):
      	return <return expression>
      
    • The second line must be indented(most programmers use four spaces to indent). The return expression is not evaluated right away; it is stored as part of the newly defined function and evaluated only when the function is eventually applied.

1.3.1 Environments

用pythontutor来讲真的太棒

  • 引入,提出问题

    Our subset of Python is now complex enough that the meaning of programs is non-obvious. What if a formal parameter has the same name as a built-in function? Can two functions share names without confusion?

  • An environment in which an expression is evaluated consists of a sequence of frames, depicted as boxes.

  • Each frame contains bindings, each of which associates a name with its corresponding value. There is a single global frame. Assignment and import statements add entries to the first frame of the current environment.

So far, our environment consists only of the global frame.

image-20230118162950730

此处引入对pythontutor的介绍

This environment diagram shows the bindings of the current environment, along with the values to which names are bound. The environment diagrams in this text are interactive: you can step through the lines of the small program on the left to see the state of the environment evolve on the right. You can also click on the “Edit code in Online Python Tutor” link to load the example into the Online Python Tutor, a tool created by Philip Guo for generating these environment diagrams. You are encouraged to create examples yourself and study the resulting environment diagrams.


  • Functions appear in environment diagrams as well, An import statement(语句) binds a name to a built-in function. A def statement binds a name to a user-defined function created by the definition.
    在这里插入图片描述

    The resulting environment after importing mul and defining square appears above.


  • Each function is a line that starts with func, followed by the function name and formal parameters(形式参数). Built-in functions such as mul do not have formal parameter names, and so ... is always used instead.

  • The name of a function is repeated twice, once in the frame and again as part of the function itself. The name appearing in the function is called the intrinsic name. The name in a frame is a bound name. There is a difference between the two: different names may refer to the same function, but that function itself has only one intrinsic name.

    The name bound to a function in a frame is the one used during evaluation. The intrinsic name of a function does not play a role in evaluation. Step through the example below using the Forward button to see that once the name max is bound to the value 3, it can no longer be used as a function.

    在这里插入图片描述

    The error message TypeError: 'int' object is not callable is reporting that the name max (currently bound to the number 3) is an integer and not a function. Therefore, it cannot be used as the operator in a call expression.

    我再来试试

    在这里插入图片描述

Function Signatures(看语境翻译为函数原型比较好)

  • Functions differ in the number of arguments that they are allowed to take. To track these requirements, we draw each function in a way that shows the function name and its formal parameters. The user-defined function square takes only x; providing more or fewer arguments will result in an error. A description of the formal parameters of a function is called the function’s signature.
  • The function max can take an arbitrary number of arguments. It is rendered as max(...). Regardless of the number of arguments taken, all built-in functions will be rendered as <name>(...), because these primitive functions were never explicitly defined.

1.3.2 Calling User-Defined Funcitons

  • 调用函数的过程:

    To evaluate a call expression whose operator names a user-defined function, the Python interpreter follows a computational process. As with any call expression, the interpreter evaluates the operator and operand expressions, and then applies the named function to the resulting arguments.

  • Applying a user-defined function introduces a second local frame, which is only accessible to that function. To apply a user-defined function to some arguments:↳

    1. Bind the arguments to the names of the function’s formal parameters in a new local frame.
    2. Execute the body of the function in the environment that starts with this frame.

Name Evaluation

The order of frames in an environment affects the value returned by looking up a name in an expression. We stated previously that a name is evaluated to the value associated with that name in the current environment.

We can now be more precise:

  • A name evaluates to the value bound to that name in the earlist frame of the current environment in which that name is found.

1.3.3 Example: Calling a User-Defined Function

例1(我把1.3.2的搬过来了)

from operator import mul
def square(x):
    return mul(x, x)
square(-2)
  • After executing the first import statement, only the name mul is bound in the global frame

    在这里插入图片描述

  • First, the definition statement for the function square is executed. Notice that the entire def statement is processed in a single step. The body of a function is not executed until the function is called (not when it is defined).

    在这里插入图片描述

  • Next, the square function is called with the argument -2, and so a new frame is created with the formal parameter x bound to the value -2.
    在这里插入图片描述

  • Then, the name x is looked up in the current environment, which consists of the two frames shown. In both occurrences, x evaluates to -2, and so the square function returns 4.

    在这里插入图片描述

    The “Return value” in the square() frame is not a name binding; instead it indicates the value returned by the function call that created the frame.

Even in this simple example, two different environments are used. The top-level expression square(-2) is evaluated in the global environment, while the return expression mul(x, x) is evaluated in the environment created for by calling square. Both x and mul are bound in this environment, but in different frames.

例2

Let us again consider our two simple function definitions and illustrate the process that evaluates a call expression for a user-defined function.

在这里插入图片描述

from operator import add, mul
def square(x):
    return mul(x, x)

def sum_squares(x, y):
    return add(square(x), square(y))

result = sum_squares(5, 12)
  • Python first evaluates the name sum_squares, which is bound to a user-defined function in the global frame. The primitive numeric expressions 5 and 12 evaluate to the numbers they represent.

  • Next, Python applies sum_squares, which introduces a local frame that binds x to 5 and y to 12.

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ly3XRV3t-1674181433885)(null)]

  • The body of sum_squares contains this call expression:

      add     (  square(x)  ,  square(y)  )
    ________     _________     _________
    operator     operand 0     operand 1
    
    • All three subexpressions are evaluated in the current environment, which begins with the frame labeled sum_squares().
    • The operator subexpression add is a name found in the global frame, bound to the built-in function for addition.
    • The two operand subexpressions must be evaluated in turn(依次,轮流), before addition is applied.
    • Both operands are evaluated in the current environment beginning with the frame labeled sum_squares.
  • In operand 0, squares names a user-defined function in the global frame, while x names the number 5 in the local frame. Python applies square to 5 by introducing yet another local frame that binds x to 5.

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sGcaibpg-1674181433706)(null)]

  • Using this environment, the expression mul(x, x) evaluates to 25.

  • Our evaluation procedure now turns to operand 1 ,for which y names the number 12. Python evaluates the body of square again, this time introducing yet another local frame that binds x to 12. Hence, operand 1 evaluates to 144.

    在这里插入图片描述

  • Finally, applying addition to the arguments 25 and 144 yields a final return value for sum_squares: 169

    在这里插入图片描述

This example illustrates many of the fundamental ideas we have developed so far.

  • Names are bound to values, which are distributed across many independent local frames, along with a single global frame that contains shared names.
  • A new local frame is introduced every time a function is called, even if the same function is called twice.

All of this machinery exists to ensure that names resolve to the correct values at the correct times during program execution. This example illustrates why our model requires the complexity that we have introduced. All three local frames contain a binding for the name x, but that name is bound to different values in different frames. Local frames keep these names separate.

1.3.4 Local Names

One detail of a function’s implementation that should not affect the function’s behavior is the implementer’s choice of names for the function’s formal parameters. Thus, the following functions should provide the same behavior:

>>> def square(x):
        return mul(x, x)
>>> def square(y):
        return mul(y, y)

This principle – that the meaning of a function should be independent of the parameter names chosen by its author – has important consequences for programming languages. The simplest consequence is that the parameter names of a function must remain local to the body of the function.

If the parameters were not local to the bodies of their respective functions, then the parameter x in square could be confused with the parameter x in sum_squares. Critically, this is not the case: the binding for x in different local frames are unrelated. The model of computation is carefully designed to ensure this independence.

We say that the scope of a local name is limited to the body of the user-defined function that defines it. When a name is no longer accessible, it is out of scope. This scoping behavior isn’t a new fact about our model; it is a consequence of the way environments work.

1.3.5 Choosing Names

  • The interchangeability of names does not imply that formal parameter names do not matter at all. On the contrary, well-chosen function and parameter names are essential for the human interpretability of function definition.

  • 下面的一些 guidelines are adapted from the style guide for Python code

    A shared set of conventions smooths communication among members of a developer community.

    • Function names are lowercase, with words separated by underscores. Descriptive names are encouraged.(鼓励见名知意)
    • Function names typically evoke operations applied to arguments by the interpreter (e.g., print, add, square) or the name of the quantity that results (e.g., max, abs, sum).
    • Parameter names are lowercase, with words separated by underscores. Single-word names are preferred.
    • Parameter names should evoke the role of the parameter in the function, not just the kind of argument that is allowed.
    • Single letter parameter names are acceptable when their role is obvious, but avoid “l” (lowercase ell), “O” (capital oh), or “I” (capital i) to avoid confusion with numerals.

There are many exceptions to these guidelines, even in the Python standard library. Like the vocabulary of the English language, Python has inherited words from a variety of contributors, and the result is not always consistent.

1.3.6 Funcitons as Abstractions

  • 1.3.3 中例二的sum_squares 是根据函数square 定义的,但是只依赖于square定义的输入参数和输出值之间的关系

    只关心square的输入输出,中间是怎样的并不关心

  • We can write sum_squares without concerning ourselves with how to square a number. The details of how the square is computed can be supressed, to be considered at a later time.

  • As far as sum_squares is concerned, square is not a particular function body, but rather an abstraction of a function, a so-called functional abstraction. At this level of abstraction, any function tha computes the square is equally good.

  • Thus, considering only the values they return, the following two funcitons for squaring a number should be indistinguishable. Each takes a numerical argument and produces the square of that number as the value.

>>> def square(x):
        return mul(x, x)
>>> def square(x):
        return mul(x, x-1) + x
  • In other words, a function definition should be able to suppress details.

    这里就是封装思想

  • The users of the function may not have written the function themselves, but may have obtained it from another programmer as a “black box”. A programmer should not need to know how the function is implemented in order to use it. The Python Library has this property. Many developers use the functions defined there, but few ever inspect their implementation.

Aspects of a functional abstraction

To master the use of a functional abstraction, it is often useful to consider its three core attributes.

  • The domain of a function is the set of arguments it can take.
  • The range of a function is the set of values it can return.
  • The intent of a function is the relationship it computes between inputs and output (as well as any side effects it might generate).
  • Understanding functional abstractions via their domain, range, and intent is critical to using them correctly in a complex program.

For example, any square function that we use to implement sum_squares should have these attributes:

  • The domain is any single real number.
  • The range is any non-negative real number.
  • The intent is that the output is the square of the input.

These attributes do not specify how the intent is carried out; that detail is abstracted away.

1.3.7 Operations

  • Mathematical operators (such as + and -) provided our first example of a method of combination, but we have yet to define an evaluation procedure for expressions that contain these operators.
  • Python expressions with infix operators (中缀运算符)each have their own evaluation procedures, but you can often think of them as short-hand(简写形式) for call expressions.

比如

>>> 2 + 3
5
# simply consider it to be short-hand for
>>> add(2, 3)
5
  • Infix notation can be nested, just like call expressions. Python applies the normal mathematical rules of operator precedence, which dictate how to interpret a compound expression with multiple operators.
>>> 2 + 3 * 4 + 5
19
evaluates to the same result as
>>> add(add(2, mul(3, 4)), 5)
19
  • The nesting in the call expression is more explicit than the operator version, but also harder to read.

    Python also allows subexpression grouping with parentheses(圆括号), to override the normal precedence(优先) rules (优先级) or make the nested structure of an expression more explicit.

    >>> (2 + 3) * (4 + 5)
    45
    evaluates to the same result as
    >>> mul(add(2, 3), add(4, 5))
    45
    

  • Python的除法

    • Python provides two infix operators: / and //.
  • The former is normal division, so that it results in a floating point, or decimal value, even if the divisor evenly divides the dividend:↳

    >>> 5 / 4
    1.25
    >>> 8 / 4
    2.0
    

    The // operator, on the other hand, rounds the result down to an integer:

    >>> 5 // 4
    1
    >>> -5 // 4
    -2
    

    These two operators are shorthand for the truediv and floordiv functions.

    >>> from operator import truediv, floordiv
    >>> truediv(5, 4)
    1.25
    >>> floordiv(5, 4)
    1
    

    You should feel free to use infix operators and parentheses in your programs. Idiomatic Python prefers operators over call expressions for simple mathematical operations.

1.4 Designing Functions

We now turn to the topic of what makes a good function.

Fundamentally, the qualities of good functions all reinforce the idea that functions are good abstractions.

  • Each function should have exactly one job.
    • That job should be identifiable(能被识别的) with a short name and characterizable in a single line of text.
    • Functions that perform multiple jobs in sequence should be divided into multiple functions.
  • Don’t repeat yourself is a central tenet(原则) of software engineering. The so-called DRY principle states that multiple fragments of code should not describe redundant(多余的) logic.
    • Instead, that logic should be implemented once, given a name, and applied multiple times.
    • If you find yourself copying and pasting a block of code, you have probably found an opportunity for functional abstraction.
  • Functions should be defined generally. Squaring is not in the Python Library precisely because it is a special case of the pow function, which raises numbers to arbitrary powers(任意幂).

1.4.1 Documentation

  • A function definition will often include documentation describing the function, called a docstring, which must be intended along with the function body.

  • Docstrings are conventionally triple quoted.

  • The first line describes the job of the function in one line. The following lines can describe arguments and clarify the behavior of the function:

    def pressure(v, t, n):
            """Compute the pressure in pascals of an ideal gas.
    
            Applies the ideal gas law: http://en.wikipedia.org/wiki/Ideal_gas_law
    
            v -- volume of gas, in cubic meters
            t -- absolute temperature in degrees kelvin
            n -- particles of gas
            """
            k = 1.38e-23  # Boltzmann's constant
            return n * k * t / v
    
  • When you call help with the name of a function as an argument, you see its docstring (type q to quit Python help).

    Orz 原来help也能看自己写的func

在这里插入图片描述
在这里插入图片描述

  • When writing Python programs, include docstrings for all but the simplest functions. (除了最简单的函数之外,所有的函数都要包含文档)

  • Remember, code is written only once, but often read many times.

  • The Python docs include docstring guidelines that maintain consistency across different Python projects.

Comment 注释

  • Comments in Python can be attached to the end of a line following the # symbol.
  • 比如上面那段代码中
    • the comment Boltzmann's constant above describes k.
  • These comments don’t ever appear in Python’s help, and they are ignored by the interpreter. They exist for humans alone.

1.4.2 Default Argument Values

A consequence of defining general functions is the introduction of additional arguments. Functions with many arguments can be awkward to call and difficult to read.

In Python, we can provide default values for the arguments of a function. When calling that function, arguments with default values are optional. If they are not provided, then the default value is bound to the formal parameter name instead. For instance, if an application commonly computes pressure for one mole of particles, this value can be provided as a default:

def pressure(v, t, n=6.022e23):
        """Compute the pressure in pascals of an ideal gas.

        v -- volume of gas, in cubic meters
        t -- absolute temperature in degrees kelvin
        n -- particles of gas (default: one mole)
        """
        k = 1.38e-23  # Boltzmann's constant
        return n * k * t / v

The = symbol means two different things in this example, depending on the context in which it is used.

In the def statement header, = does not perform assignment, but instead indicates a default value to use when the pressure function is called. By contrast, the assignment statement to k in the body of the function binds the name k to an approximation of Boltzmann’s constant.

image-20230119105853812

The pressure function is defined to take three arguments, but only two are provided in the first call expression above. In this case, the value for n is taken from the def statement default. If a third argument is provided, the default is ignored.

As a guideline, most data values used in a function’s body should be expressed as default values to named arguments, so that they are easy to inspect and can be changed by the function caller. Some values that never change, such as the fundamental constant k, can be bound in the function body or in the global frame.

1.5 Control

感觉每一小节的引言都写得很好,娓娓道来,承上启下,令人恍然大悟

The expressive power of the functions that we can define at this point is very limited, because we have not introduced a way to make comparisons and to perform different operations depending on the result of a comparison. Control statements will give us this ability. They are statements that control the flow of a program’s execution based on the results of logical comparisons.

Statements differ fundamentally from the expressions that we have studied so far. They have no value. Instead of computing something, executing a control statement determines what the interpreter should do next.

1.5.1 Statements

  • So far, we have primarily considered how to evaluate expressions(计算表达式).

  • 我们已学的三种statements(语句)

    • assignment
    • def
    • return

    These lines of Python code are not themselves expressions, although they all contain expressions as components.

  • Rather than being evaluated, statements are executed.

    • Each statement describes some change to the interpreter state, and executing a statement applies that change.
    • As we have seen for return and assignment statements, executing statements can involve evaluating subexpressions contained within them.

  • Expressions can also be executed as statements, in which case they are evaluated, but their value is discarded. Executing a pure function has no effect, but executing a non-pure function can cause effects as a consequence of function application.

    例如

    >>> def square(x):
            mul(x, x) # Watch out! This call doesn't return a value.
    

    This example is valid Python, but probably not what was intended. The body of the function consists of an expression. An expression by itself is a valid statement, but the effect of the statement is that the mul function is called, and the result is discarded. If you want to do something with the result of an expression, you need to say so: you might store it with an assignment statement or return it with a return statement:

    >>> def square(x):
            return mul(x, x)
    
  • Sometimes it does make sense to have a function whose body is an expression, when a non-pure function like print is called.

    >>> def print_square(x):
            print(square(x))
    

At its highest level, the Python interpreter’s job is to execute programs, composed of statements. However, much of the interesting work of computation comes from evaluating expressions. Statements govern the relationship among different expressions in a program and what happens to their results.


  • 小结一下
    • 要分清statement 和 expression
    • interpreter 是去 execute statement

1.5.2 Compound Statements

  • In general, Python code is a sequence of statements.

  • A simple statement is a single line that doesn’t end in a colon. A compound statement is so called because it is composed of other statements (simple and compound). Compound statements typically span multiple lines and start with a one-line header ending in a colon(冒号), which identifies the type of statement. Together, a header and an indented suite of statements is called a clause. A compound statement consists of one or more clauses:

    <header>:
        <statement>
        <statement>
        ...
    <separating header>:
        <statement>
        <statement>
        ...
    ...
    
  • We can understand the statements we have already introduced in these terms.

    • Expressions, return statements, and assignment statements are simple statements.
    • A def statement is a compound statement. The suite that follows the def header defines the function body.
  • Specialized evaluation rules for each kind of header dictate when and if the statements in its suite are executed. We say that the header controls its suite. For example, in the case of def statements, we saw that the return expression is not evaluated immediately, but instead stored for later use when the defined function is eventually called.

  • We can also understand multi-line programs now.

    • To execute a sequence of statements, execute the first statement. If that statement does not redirect(改变方向) control, then proceed(继续) to execute the rest of the sequence of statements, if any remain.
  • This definition exposes the essential structure of a recursively defined sequence: a sequence can be decomposed(分解) into its first element and the rest of its elements. The “rest” of a sequence of statements is itself a sequence of statements! Thus, we can recursively apply this execution rule. This view of sequences as recursive data structures will appear again in later chapters.

  • The important consequence of this rule is that statements are executed in order, but later statements may never be reached, because of redirected control(重定向控制).

Practical Guidance. When indenting a suite, all lines must be indented the same amount and in the same way (use spaces, not tabs). Any variation in indentation will cause an error.


  • 小总结一下
    • 函数的def statement 其实就是复合语句
    • 多行程序的执行
      • 首先执行第一个语句,如果这个语句没有重定向控制,就往后继续执行
    • 复合语句可以用递归的思想来看,看作一个递归定义的sequence结构,每次都分为 first element 和 the rest of its elements.

1.5.3 Defining Functions II: Local Assignment

Originally, we stated that the body of a user-defined function consisted only of a return statement with a single return expression. In fact, functions can define a sequence of operations that extends beyond a single expression.

Whenever a user-defined function is applied, the sequence of clauses in the suite of its definition is executed in a local environment — an environment starting with a local frame created by calling that function. A return statement redirects control: the process of function application terminates whenever the first return statement is executed, and the value of the return expression is the returned value of the function being applied.

Assignment statements can appear within a function body. For instance, this function returns the absolute difference between two quantities as a percentage of the first, using a two-step calculation:

image-20230119113653317

The effect of an assignment statement is to bind a name to a value in the first frame of the current environment.

As a consequence, assignment statements within a function body cannot affect the global frame.

The fact that functions can only manipulate their local environment is critical to creating modular programs, in which pure functions interact only via the values they take and return.

Of course, the percent_difference function could be written as a single expression, as shown below, but the return expression is more complex.

>>> def percent_difference(x, y):
        return 100 * abs(x-y) / x
>>> percent_difference(40, 50)
25.0

So far, local assignment hasn’t increased the expressive power of our function definitions. It will do so, when combined with other control statements.

In addition, local assignment also plays a critical role in clarifying the meaning of complex expressions by assigning names to intermediate quantities.


  • 小结
    • return statement 可以 redirect control
    • 函数内部的赋值语句不会影响global frame , functions can only manipulate their local environment

1.5.4 Conditional Statements

从绝对值(absolute values)引入

  • We would like to express that if x is positive, abs(x) returns x. Furthermore, if x is 0, abs(x) returns 0. Otherwise, abs(x) returns -x. In Python, we can express this choice with a conditional statement.

    def absolute_value(x):
        """Compute abs(x)."""
        if x > 0:
            return x
        elif x == 0:
            return 0
        else:
            return -x
    
    result = absolute_value(-2)
    

image-20230119115341674

  • This implementation of absolute_value raises several important issues:

    Conditional statements. A conditional statement in Python consists of a series of headers and suites: a required if clause, an optional sequence of elif clauses, and finally an optional else clause:

    if <expression>:
        <suite>
    elif <expression>:
        <suite>
    else:
        <suite>
    

    When executing a conditional statement, each clause is considered in order. The computational process of executing a conditional clause follows.

    1. Evaluate the header’s expression.
    2. If it is a true value, execute the suite. Then, skip over all subsequent clauses in the conditional statement.

    If the else clause is reached (which only happens if all if and elif expressions evaluate to false values), its suite is executed.

    Boolean contexts. Above, the execution procedures mention “a false value” and “a true value.” The expressions inside the header statements of conditional blocks are said to be in boolean contexts: their truth values matter to control flow, but otherwise their values are not assigned or returned. Python includes several false values, including 0, None, and the boolean value False. All other numbers are true values.

    Boolean values. Python has two boolean values, called True and False. Boolean values represent truth values in logical expressions. The built-in comparison operations, >, <, >=, <=, ==, !=, return these values.

    >>> 4 < 2
    False
    >>> 5 >= 5
    True
    

    This second example reads “5 is greater than or equal to 5”, and corresponds to the function ge in the operator module.

    >>> 0 == -0
    True
    

    This final example reads “0 equals -0”, and corresponds to eq in the operator module. Notice that Python distinguishes assignment (=) from equality comparison (==), a convention shared across many programming languages.

    Boolean operators. Three basic logical operators are also built into Python:

    >>> True and False
    False
    >>> True or False
    True
    >>> not False
    True
    

短路效应

Logical expressions have corresponding evaluation procedures. These procedures exploit the fact that the truth value of a logical expression can sometimes be determined without evaluating all of its subexpressions, a feature called short-circuiting.(短路)

  • To evaluate the expression <left> and <right>:

    • Evaluate the subexpression <left>.
    • If the result is a false value v, then the expression evaluates to v.
    • Otherwise, the expression evaluates to the value of the subexpression <right>.
  • To evaluate the expression <left> or <right>:

    • Evaluate the subexpression <left>.
    • If the result is a true value v, then the expression evaluates to v.
    • Otherwise, the expression evaluates to the value of the subexpression <right>.
  • To evaluate the expression not <exp>:

    • Evaluate <exp>; The value is True if the result is a false value, and False otherwise.

These values, rules, and operators provide us with a way to combine the results of comparisons. Functions that perform comparisons and return boolean values typically begin with is, not followed by an underscore (e.g., isfinite, isdigit, isinstance, etc.).

1.5.5 Iteration

Only through repeated execution of statements do we unlock the full potential of computers. Iterative control structures can execute the same statements many times.

Consider the sequence of Fibonacci numbers, in which each number is the sum of the preceding two:

0, 1, 1, 2, 3, 5, 8, 13, 21, ...

Each value is constructed by repeatedly applying the sum-previous-two rule. The first and second are fixed to 0 and 1. For instance, the eighth Fibonacci number is 13.

We can use a while statement to enumerate n Fibonacci numbers. We need to track how many values we’ve created (k), along with the kth value (curr) and its predecessor (pred). Step through(单步调试) this function and observe how the Fibonacci numbers evolve one by one, bound to curr.

def fib(n):
    """Compute the nth Fibonacci number, for n >= 2."""
    pred, curr = 0, 1   # Fibonacci numbers 1 and 2
    k = 2               # Which Fib number is curr?
    while k < n:
        pred, curr = curr, pred + curr
        k = k + 1
    return curr

result = fib(8)

image-20230120095041049

  • pred, curr = curr, pred + curr 是python里的多重赋值

  • A while clause contains a header expression followed by a suite:

    while <expression>: 
       <suite>
    

    To execute a while clause:

    • Evaluate the header’s expression.
    • If it is a true value, execute the suite, then return to step 1.

    In step 2, the entire suite of the while clause is executed before the header expression is evaluated again.

    In order to prevent the suite of a while clause from being executed indefinitely, the suite should always change some binding in each pass.

    A while statement that does not terminate is called an infinite loop. Press <Control>-C to force Python to stop looping.

1.5.6 Testing

  • Testing a function is the act of verifying that the function’s behavior matches expectations.

    A test is a mechanism for systematically performing this verification. Tests typically take the form of another function that contains one or more sample calls to the function being tested. The returned value is then verified against an expected result. Unlike most functions, which are meant to be general, tests involve selecting and validating calls with specific argument values. Tests also serve as documentation: they demonstrate how to call a function and what argument values are appropriate.

Assertions

Programmers use assert statements to verify expectations, such as the output of a function being tested. An assert statement has an expression in a boolean context, followed by a quoted line of text (single or double quotes are both fine, but be consistent) that will be displayed if the expression evaluates to a false value.

assert fib(8) == 13, 'The 8th Fibonacci number should be 13'

When the expression being asserted evaluates to a true value, executing an assert statement has no effect. When it is a false value, assert causes an error that halts execution.

A test function for fib should test several arguments, including extreme values of n.

def fib_test(): 
    assert fib(2) == 1, 'The 2nd Fibonacci number should be 1' 

	assert fib(3) == 1, 'The 3rd Fibonacci number should be 1' 

	assert fib(50) == 7778742049, 'Error at the 50th Fibonacci number'

When writing Python in files, rather than directly into the interpreter, tests are typically written in the same file or a neighboring file with the suffix _test.py.

Doctests

Python provides a convenient method for placing simple tests directly in the docstring of a function. The first line of a docstring should contain a one-line description of the function, followed by a blank line. A detailed description of arguments and behavior may follow. In addition, the docstring may include a sample interactive session that calls the function:

def sum_naturals(n):
        """Return the sum of the first n natural numbers.

        >>> sum_naturals(10)
        55
        >>> sum_naturals(100)
        5050
        """
        total, k = 0, 1
        while k <= n:
            total, k = total + k, k + 1
        return total

Then, the interaction can be verified via the doctest module. Below, the globals function returns a representation of the global environment, which the interpreter needs in order to evaluate expressions.

from doctest import testmod
testmod()
TestResults(failed=0, attempted=2)

在这里插入图片描述

To verify the doctest interactions for only a single function, we use a doctest function called run_docstring_examples. This function is (unfortunately) a bit complicated to call. Its first argument is the function to test. The second should always be the result of the expression globals(), a built-in function that returns the global environment. The third argument is True to indicate that we would like “verbose” output: a catalog of all tests run.

When the return value of a function does not match the expected result, the run_docstring_examples function will report this problem as a test failure.


When writing Python in files, all doctests in a file can be run by starting Python with the doctest command line option:

python3 -m doctest <python_source_file>

The key to effective testing is to write (and run) tests immediately after implementing new functions. It is even good practice to write some tests before you implement, in order to have some example inputs and outputs in your mind. A test that applies a single function is called a unit test. Exhaustive unit testing is a hallmark of good program design.


basic knowledge and skills

连接阿里云服务器

  • 可以使用控制台右上角的workbench
  • 也可以本地 ssh 用户名@IP地址

给阿里云服务器配置图形界面

第一次配置(之前配置过了,现在来review一下)

参考:https://help.aliyun.com/document_detail/59330.html

  • 首先切换为root用户:sudo su root

  • 然后安装软件包

    • 更新软件源:apt-get update

    • 安装桌面环境所需包

      apt install gnome-panel gnome-settings-daemon metacity nautilus gnome-terminal ubuntu-desktop

  • 然后配置VNC

    Ubuntu18.04

    apt-get install vnc4server

  • 启动VNC: vncserver

    • 第一次需要设置密码

    • 修改配置文件

      • 运行以下命令,备份VNC的xstartup配置文件

        cp ~/.vnc/xstartup ~/.vnc/xstartup.bak

      • 运行以下命令,修改VNC的xstartup配置文件

        vi ~/.vnc/xstartup

      • 按i键进入编辑模式,并将配置文件修改为如下内容

        #!/bin/sh
        export XKL_XMODMAP_DISABLE=1
        export XDG_CURRENT_DESKTOP="GNOME-Flashback:GNOME"
        export XDG_MENU_PREFIX="gnome-flashback-"
        gnome-session --session=gnome-flashback-metacity --disable-acceleration-check &
        
      • :wq保存退出

  • 重启VNC

    1. 运行以下命令,关闭已启动的VNC。

      vncserver -kill :1
      
    2. 运行以下命令,启动一个新的VNC。

      VNC的端口号仍为1。

      vncserver -geometry 1920x1080 :1
      
  • 然后就可以使用VNC Viewer访问了

    • 如果出现无法通过VNC Viewer工具进行远程登录,检查是否已在Ubuntu服务器的防火墙中放行了VNC服务所需的5900和5901端口

之后日常使用

  • 我先在终端里面输入vncserver -geometry 1920x1080 :1
    • 返回A VNC server is already running as :1
    • 然后我去VNC Viewer 点击 connect,显示too many security failures

  • 查了一下解决方案:VNC连接报错“too many security failures”的解决方案

  • 于是 vncserver -kill :1,然后再vncserver -geometry 1920x1080 :1,再去VNC Viewer输入密码就连上啦

  • 好耶

    在这里插入图片描述

VNC Viewer 无法复制粘贴

  • 解决vnc远程桌面无法与本地windows复制粘贴的问题

  • 在terminal里面输入 vncconfig -nowin&

    • 这一步解决了我从VNC viewer往windows复制,但是没有解决从Windows往VNC Viewer复制
  • 又看了好多解决方案,全都无效(我的是Ubuntu18.04)

    • https://unix.stackexchange.com/a/35275
    • https://superuser.com/a/1524282
    • https://help.realvnc.com/hc/en-us/articles/360002253738-Copying-and-Pasting-Text#copying-and-pasting-from-vnc-server-0-1
    • https://help.realvnc.com/hc/en-us/articles/360013336218#how-do-i-fix-it–0-1
    • https://help.realvnc.com/hc/en-us/articles/360013336218-Keyboard-shortcuts-stop-working-in-VNC-Connect#why-does-this-happen–0-2
  • 算了,配合着windows terminal用吧之后…

Infix notation 中缀表达式

  • Infix notation is a way of writing mathematical expressions in which the operator symbol is placed between the operands. For example, in the mathematical expression “3 + 4”, the operator symbol “+” is placed between the operands “3” and “4”.
  • This is in contrast to other forms of notation such as prefix notation (e.g. “+ 3 4”) or postfix notation (e.g. “3 4 +”). Infix notation is the most common form of mathematical notation used in everyday writing and is the standard form used in most programming languages.

python语法糖之多重赋值

  • 参考:https://blog.csdn.net/scfor333/article/details/104316694

致敬一下python tutor的作者 Or2

  • 作者是Philip Guo
  • Philip Guo is an associate professor of Cognitive Science and (by affiliation) Computer Science & Engineering at UC San Diego. His research spans human-computer interaction, data science, programming tools, and online learning. He studies how people learn computer programming and data science, and he builds tools to help people better understand code and data.
  • 第一次知道python tutor是2022年4月份的时候
  • 今天去大佬的主页仔细看了一下,发现他还做了pandastutor和tidydatatutor,OTZ!!!

总结

  • 这个textbook真的写的环环相扣,每一个概念的引入都有很好的过渡,总是让人感叹“噢,原来是因为这样!”
  • 一份短短的教程就让我了解了很多principles ,许多重要的concepts,教程里面给出了很多official 链接,引导我们去看官方文档
  • 这门课的目标是学会manage abstractions,书中也确实一直提到 the power of abstractions

总结

  • 这个textbook真的写的环环相扣,每一个概念的引入都有很好的过渡,总是让人感叹“噢,原来是因为这样!”
  • 一份短短的教程就让我了解了很多principles ,许多重要的concepts,教程里面给出了很多official 链接,引导我们去看官方文档
  • 这门课的目标是学会manage abstractions,书中也确实一直提到 the power of abstractions

相关资源

  • 开源书网址

  • 读着读着感觉要是有一个专门的计算机词典就好了

    • 找了一些别人整理的术语中英文对照
      • http://www.runoob.com/w3cnote/programming-en-cn.html
      • https://github.com/EarsEyesMouth/computerese-cross-references
      • https://rscai.github.io/python99/zh_CN/terminology.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/173187.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【论文翻译】ViTPose: Simple Vision Transformer Baselines for Human Pose Estimation

【论文】https://arxiv.org/abs/2204.12484v3 【github】GitHub - ViTAE-Transformer/ViTPose: The official repo for [NeurIPS22] "ViTPose: Simple Vision Transformer Baselines for Human Pose Estimation" and [Arxiv22] "ViTPose: Vision Transformer F…

IO流操作

文章目录一、字符集常见字符集编码、解码操作二、IO流FileInputStreamFileOutputStreamFileReaderFileWriter常见问题一、字符集 常见字符集 我们的计算机底层是不可以直接存储字符的&#xff0c;计算机中底层只能存储二进制(0、1)&#xff0c;同时二进制是可以转换成十进制的…

Fluent UDF编译环境配置 VS2019

Fluent UDF编译环境配置 VS2019环境配置问题记录继续记录调试过程仅用一个host仅用一个node两个都放进去换个电脑继续报错记录错误环境配置 生成PATH文件的&#xff0c;有的没有权限在当前文件夹&#xff0c;可以用这个命令&#xff0c;还是原来的代码&#xff0c;就是改一下 …

趣味三角——前言和序言

目录 1. 前言 2. 序言 2.1 抄写员Ahmes&#xff0c;公元前1650年 2.2 古埃及的趣味数学 1. 前言 There is perhaps nothing which so occupies the middle position of mathematics as trigonometry. (也许&#xff0c;没有什么东西像三角学一样占据数学的中心位置…

离散数学-图论-欧拉图、哈密顿图、二部图、平面图(14)

欧拉图、哈密顿图、二部图、平面图 1 欧拉图 无向图G是欧拉图⇔\Leftrightarrow⇔G连通,且无奇度点。无向图G是半欧拉图⇔\Leftrightarrow⇔G连通,且仅有两个奇度点。有向图G是欧拉图⇔\Leftrightarrow⇔G强连通,且所有顶点的入度出度。有向图G是半欧拉图⇔\Leftrightarrow⇔…

登录时“自动填充”和“验证码”的实现

自动填充和验证码的实现需求1. 基础登录功能1.1 持久层pojo实体类&#xff1a;代理接口&#xff1a;1.2 业务层1.3 表现层login.jsp&#xff08;登陆界面&#xff09;&#xff1a;LoginServlet&#xff1a;selectAllServlet&#xff1a;brand.jsp&#xff08;登陆成功&#xff…

30.Isaac教程--Costmap规划器

Costmap规划器 ISAAC教程合集地址: https://blog.csdn.net/kunhe0512/category_12163211.html 文章目录Costmap规划器组件消息入门自定义图使用自定义地图改变规划器将 Costmap 添加到视线中将通道添加到配置Isaac SDK 中的标准导航规划器指示机器人在避开障碍物的同时采用最短…

赛意SMOM和金蝶云星空单据接口对接

赛意SMOM和金蝶云星空单据接口对接数据源系统:金蝶云星空金蝶K/3Cloud在总结百万家客户管理最佳实践的基础上&#xff0c;提供了标准的管理模式&#xff1b;通过标准的业务架构&#xff1a;多会计准则、多币别、多地点、多组织、多税制应用框架等&#xff0c;有效支持企业的运营…

数据结构进阶 unordered系列的效率对比

作者&#xff1a;小萌新 专栏&#xff1a;数据结构进阶 作者简介&#xff1a;大二学生 希望能和大家一起进步&#xff01; 本篇博客简介&#xff1a;对比map set和unordered系列map和set的效率 unordered系列的效率对比map/set与unordered_map/unordered_set的区别map/set与uno…

HTTP简史

今天一起来研究Http协议的一些事情&#xff0c;通过本文你将了解到以下内容&#xff1a;Http协议各版本的对比和优缺点Http2.0协议相关的SPDY协议、二进制分帧协议、多路复用、首部压缩、服务推送等基本原理HTTP3.0和QUIC协议乘风破浪前往知识的海洋吧&#xff0c;要开船了&…

Linux常用命令——telnet命令

在线Linux命令查询工具(http://www.lzltool.com/LinuxCommand) telnet 登录远程主机和管理(测试ip端口是否连通) 补充说明 telnet命令用于登录远程主机&#xff0c;对远程主机进行管理。telnet因为采用明文传送报文&#xff0c;安全性不好&#xff0c;很多Linux服务器都不开…

【Java IO流】字符流详解

文章目录1. 前言2. 字符输入流3. 字符输出流4. 字符流底层原理解析4.1 字符输入流4.2 字符输出流1. 前言 在上一篇字符集详解中我们说到了产生乱码的原因&#xff0c;要么是读取数据时未读完整个汉字&#xff0c;要么是因为编码和解码的方式不统一&#xff0c;对于后者我们只需…

PromQL之函数

Prometheus 版本 2.41.0 平台统一监控的介绍和调研直观感受PromQL及其数据类型PromQL之选择器和运算符PromQL之函数 PromQL 聚合函数 PromQL 的聚合函数只能用于瞬时向量&#xff0c;支持的聚合函数有&#xff1a; sum 求和min 最小值max 最大值avg 平均值group 分组&#xf…

Nginx与LUA(5)

您好&#xff0c;我是湘王&#xff0c;这是我的CSDN博客&#xff0c;欢迎您来&#xff0c;欢迎您再来&#xff5e;Nginx诞生以来就获赞无数&#xff0c;反向代理、负载均衡、流量限制与流量扩展都是它的拿手好戏。基本上是互联网应用的主流入口&#xff0c;和计算、即时通讯、存…

python批量下载modis数据(可筛选日期、范围、数据类型)

找了一圈下modis数据的&#xff0c;有的不能空间筛选有的不能下初级产品&#xff08;也可能没找到&#xff09;&#xff0c;不甚满意&#xff0c;自己搞了个 0 前言 用到的主要依赖是selenium&#xff0c;下载网站是https://ladsweb.modaps.eosdis.nasa.gov&#xff0c;环境是…

ensp实现不同VLAN之间的通信

1.VLAN的基本配置 一个简单的VLAN实验&#xff0c;基本配置如图。 其中交换机为S5700。 在只对四台PC配置IP地址&#xff0c;交换机不用配置后&#xff0c;四台PC可以互相ping通。 下面是对交换机配置VLAN的方法 <Huawei>sys #进入系统视图 [Huawei…

钉钉搭和金蝶云星空接口打通对接实战

数据源系统:阿里宜搭宜搭是阿里巴巴自研的基于钉钉和阿里云的低代码平台&#xff0c;可让用户通过简单的拖拽、配置即可完成应用搭建&#xff0c;为每个组织提供低门槛、高效率的数字化业务应用生产新模式。有效缩减企业应用开发时间&#xff0c;助力企业数字化升级。对接目标系…

第四层:友元与函数成员别样定义

文章目录前情回顾友元友元的概念友元的目的友元的关键字友元的两种种用法全局函数做友元类做友元函数成员的别样定义有缘人学友元&#xff0c;急速突破第四层本章知识点&#xff08;图片形式&#xff09;&#x1f389;welcome&#x1f389; ✒️博主介绍&#xff1a;一名大一的…

Python怎么获取节假日信息?

“holidays” 是一个 Python 第三方库&#xff0c;它可以用来解析和处理节假日信息。 该库提供了一系列函数&#xff0c;可以用来检查某一天是否是节假日、获取某一年中所有节假日的列表等。它支持多种国家和地区的节假日&#xff0c;例如美国、加拿大、澳大利亚、英国等。 “…

【软件架构思想系列】分层架构

- 分层架构 -今天谈下架构设计中的分层思想和分层模型。架构思维概述对于架构思维本身仍然是类似系统思维&#xff0c;结构化思维&#xff0c;编程思维等诸多思维模式的一个合集。由于架构的核心作用是在业务现实世界和抽象的IT实现之间建立起一道桥梁&#xff0c;因此…