1.1 引言

调试(debugging)的一些指导原则:

  1. 逐步测试:每个写好的程序都由小型的组件模块组成,这些组件可以独立测试。尽快测试你写好的任何东西来捕获错误。
  2. 隔离错误:复杂程序的输出、表达式,或语句中的错误,通常更可以归于特定的组件模块。在尝试诊断问题、修正错误前,一定要先将它跟踪到最小的代码片段。
  3. 询问他人

1.2 编程元素

1.2.3 导入库函数

例如:from operator import add, sub, mul
其中operator为模块名称(math也是模块名称),add,sub,mul是被导入模块的具名属性。

Python 3 库文档

1.2.4 名称和环境

如果一个值被赋予了名称,我们就说这个名称绑定到了值上面。

环境:将名称绑定到值上,以及随后通过名称来检索这些值的可能,意味着解释器必须维护某种内存来跟踪这些名称和值的绑定。这些内存叫做环境。

名称也可以绑定到函数,比如:

>>> max
<built-in function max>

我们可以使用赋值运算符来给现有的函数取新的名字:

>>> f = max
>>> f
<built-in function max>
>>> f(3, 4)
4

如果给函数名赋值为其他数据类型(如:int),则再次调用该函数时会报错:

>>> max(3,4)
4
>>> max = 2
>>> max(3,4)
Traceback (most recent call last):File "<stdin>", line 1, in <module>
TypeError: 'int' object is not callable

1.2.5 嵌套表达式的求解

为了求出调用表达式,Python 会执行下列事情:

  • 求出运算符和操作数子表达式,之后
  • 在值为操作数子表达式的参数上调用值为运算符子表达式的函数。

这个简单的过程大体上展示了一些过程上的重点。第一步表明为了完成调用表达式的求值过程,我们首先必须求出其它表达式。所以,求值过程本质上是递归的,也就是说,它会调用其自身作为步骤之一。

这是一个表达式数(expression tree)。在计算机科学中,树从顶端向下生长。每一点上的对象叫做节点(codes),比如该例中的mul、add(2, mul(4, 6))、add(3, 5)。

要求根节点(root node),也就是整个表达式,即mul(add(2, mul(4, 6)), add(3, 5)),首先需要求出枝干节点,也就是子表达式。
叶子节点(leaf expressionns)(即:没有子节点的节点)的表达式表示函数或数值,如:mul,add,2,4,6等。
内部节点分为两部分:

  1. 想要应用求值规则的表达式
  2. 表达式的结果

求值:

  1. 数字求值为它标明的数值
  2. 名称求值为当前为当前环境中这个名称所关联的值

1.2.6 函数图解

  • 纯函数:具有一些输入(参数)和一些输出(调用结果)的函数。比如abs():
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TfTeMkna-1632023353237)(image/2021-08-20-14-57-10.png)]

纯函数的特性:调用时除了返回值之外没有其他效果。

  • 非纯函数:除了返回值,还会产生一些改变解释器或计算机状态的副作用,一个普遍的副作用就是在返回值之外生成额外的输出,比如print()

    print()的返回值永远是None,Python交互式解释器并不会自动打印None值。作为副作用,print()自己打印了输出:

    >>> print(1, 2, 3)
    1 2 3
    

我们可以通过调用print()的嵌套表达式来理解它的非纯特性:

>>> print(print(1), print(2))
1
2
None None>>> two = print(2)
2
>>> print(two)
None

1.3 定义新的函数

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

注:return表达式并不是立即求值,它储存为新定义函数的一部分,只在函数最终调用时会被求出。

1.3.1 环境

环境中帧的顺序会影响由表达式中的名称检索返回的值。我们之前说名称求解为当前环境中与这个名称关联的值。我们现在可以更精确一些:

  • 名称求解为当前环境中,最先发现该名称的帧中,绑定到这个名称的值。
    -> 这个原则非常重要

1.3.4 局部名称

形式参数的选择不应影响函数行为。

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

这个原则导致的最简单的记过就是函数参数名称应保留在函数体的局部范围中。

1.3.5 名称的选择

Python 的代码风格指南

  1. 函数名小写,单词之间用下划线分隔。尽量使用描述性名称
  2. 参数名称小写,单词之间用下划线分隔,首选单字名称(指只包含一个单词的名称)
  3. 参数名称应该体现参数在函数中的作用
  4. 当它们的作用很明显时,单字母参数名称是可以接受的,但避免使用“l”(小写字母 ell)、“O”(大写字母 oh)或“I”(大写字母 i)以避免与数字混淆。

1.3.6 作为抽象的函数

要正确使用一个函数,我们应当了解它的几个方面:

  1. The domain of a function is the set of arguments it can take.
    函数的域是它可以采用的参数集(输入是什么)
  2. The range of a function is the set of values it can return.
    函数的范围是它可以返回的值的集合(输出是什么)
  3. The intent of a function is the relationship it computes between inputs and output (as well as any side effects it might generate)
    该函数输入与输出之间的关系(以及它可能产生的任何副作用)
    square()函数为例:
    domain:一个实数
    range:一个非负实数
    intent:输出是输入的平方

1.3.7 运算符

5 / 4等价于truediv(5, 4)

5 // 4等价于floordiv(5, 4)

1.4 函数的设计

  • 定义函数时的几个注意事项:
  1. DRY原则——Don’t repeat yourself:代码尽量不要有重复的部分,有就写成函数
  2. 函数应该被一般性定义
    如:python内没有square()函数的原因是已经有了pow()函数

1.4.1 文档字符串

  • docstring
  1. 在python的def关键词下的一行用"""包裹的文字是叫做docstring,用来解释这个函数所做的事情。通常,第一行解释函数的作用,接下来的行分别解释参数的意义:
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_lawv -- volume of gas, in cubic meterst -- absolute temperature in degrees kelvinn -- particles of gas"""k = 1.38e-23  # Boltzmann's constantreturn n * k * t / v
  1. 使用help(<name>)可以获取该函数的docstring
help(pressure)
  1. 在编写 Python 程序时,除了最简单的函数之外,所有的函数都需要包含文档字符串。

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

  1. #及其后的注释不会出现在help中
  • doctests
    在docstring中如果加入了>>>,这就是doctest,用来测试函数的正确性,比如:
from operator import floordiv, mod
def divide_exact(n, d):"""Return the quotient and remainder of dividing N by D>>> q, r = divide_exact(2013,10)>>> q201>>> r3"""return floordiv(n, d), mod(n, d)

1.4.2 参数默认值(Default Argument Values)

定义函数时,默认参数应该跟在可变参数的后面。

准则:用于函数体的大多数数据值应该表示为具名参数的默认值,这样便于查看,以及被函数调用者修改。一些值永远不会改变,就像基本常数k_b,应该定义在全局帧中。

1.5 控制

return语句会重定向控制:无论什么时候执行return语句,函数调用的流程都会中止,返回表达式的值会作为被调用函数的返回值。

if语句示例:

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

在Python中,false有0,None,False,true为all other numbers

Python也内建了三个基本的逻辑运算符:

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

其中andor遵循短路原则。

执行比较并返回布尔值的函数通常以 is 开头,后面不跟下划线(例如,isfinite、isdigit、isinstance 等。

1.5.5 迭代

while用法:

while <expression>:<suite>

不终止的while语句叫做无限循环。按下-C可以强制让 Python 停止循环。

1.5.6 测试(Testing)

  • assert statements
    Python中的assert语法为后面跟一个condition,如果这个condition为false,则打印AssertionError:<…>,比如:
assert a > 0, 'a must greater than 0'

如果a <= 0,则打印AssertionError:<a must greater than 0>
如果a > 0,则无事发生

再举一个例子:

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'
  • 测试通常写在同一个文件或者带有后缀_test.py 的邻近文件中

  • testmod()

  1. from doctest import testmod或import doctest
  2. 使用doctest.testmod()调用该函数
  3. 在执行 doctest.testmod()函数时,它会执行该模块中各成员说明性文档包含的测试代码,并将执行结果和指定的结果做比对,如果一致,则什么也不输出;反之,则输出以下提示信息:
    显示在哪个源文件的哪一行。

Failed example,显示是哪个测试用例出错了。

Expected,显示程序期望的输出结果。也就是在“>>>命令”的下一行给出的运行结果,它就是期望结果。

Got,显示程序实际运行产生的输出结果。只有当实际运行产生的输出结果与期望结果一致时,才表明该测试用例通过。

  • run_docstring_examples
  1. from doctest import run_docstring_examples或import doctest
  2. 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.

第一个参数:要测试的函数名
第二个参数:globals()
第三个参数:True的意义是想要详细输出所有测试运行的目录

  1. 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.
  2. 在文件中编写 Python 时,可以通过使用 doctest 命令行选项启动 Python 来运行文件中的所有 doctest:
    python3-m doctest < python_source _ file >
  3. unit test:只测试单个功能(函数)的test
  4. 建议:实现新功能(函数)后立即编写并运行测试

lab01

  • If Python reaches the end of the function body without executing a return statement, it will automatically return None.

  • 布尔计算的优先顺序:not > and > or

  • Python values such as 0, None, ‘’ (the empty string), and [] (the empty list) are considered false values. All other values are considered true values.

1.6 高阶函数(Higher-Order Functions)

高阶函数:接受其他函数作为参数的函数,或者将函数作为返回值的函数。

1.6.3 函数的嵌套定义(Nested Definitions)

def square_root(x):def update(guess):return average(guess, x/guess)def test(guess):return approx_eq(square(guess), x)return iter_improve(update, test)

词法作用域:局部定义的函数也可以访问它们定义所在作用域的名称绑定。这个例子中,update引用了名称x,它是外层函数square_root的一个形参。这种在嵌套函数中共享名称的规则叫做词法作用域。严格来说,内部函数能够访问定义所在环境(而不是调用所在位置)的名称。

词法作用域的两个关键优势:

  1. 局部函数的名称并不影响定义所在函数外部的名称,因为局部函数的名称绑定到了定义处的当前局部环境中,而不是全局环境。
  2. 局部函数可以访问外层函数的环境。这是因为局部函数的函数体的求值环境扩展于定义处的求值环境。

1.6.4 作为返回值的函数

>>> def compose1(f, g):def h(x):return f(g(x))return h
>>> add_one_and_square = compose1(square, successor)
>>> add_one_and_square(12)
169

1.6.5 Lambda表达式

>>> def compose1(f,g):return lambda x: f(g(x))

我们可以通过构造相应的英文语句来理解 Lambda 表达式:

     lambda            x            :          f(g(x))
"A function that    takes x    and returns     f(g(x))"

1.6.8 函数装饰器(Function Decorators)

Python 提供了特殊的语法,将高阶函数用作执行def语句的一部分,叫做装饰器。

>>> def trace1(fn):def wrapped(x):print('-> ', fn, '(', x, ')')return fn(x)return wrapped
>>> @trace1def triple(x):return 3 * x
>>> triple(12)
->  <function triple at 0x102a39848> ( 12 )
36

这个例子中,定义了高阶函数trace1,它返回一个函数,这个函数在调用它的参数之前执行print语句来输出参数。tripledef语句拥有一个注解,@trace1,它会影响def的执行规则。像通常一样,函数triple被创建了,但是,triple的名称并没有绑定到这个函数上,而是绑定到了在新定义的函数triple上调用trace1的返回函数值上。在代码中,这个装饰器等价于:

>>> def triple(x):return 3 * x
>>> triple = trace1(triple)

注意triple这个名称绑定了wrapped函数,因为triple = trace1(triple)

可以阅读装饰器的第一篇评论来更好地了解装饰器。

Project 1: The Game of Hog

练习:分析下列函数,给出流程图与最后的a值,并将代码放入Online Python Tutor中执行,将自己的流程与实际流程进行比较

def make_test_dice(*outcomes):index = len(outcomes) - 1def dice():nonlocal indexindex = (index + 1) % len(outcomes)return outcomes[index]return dicedef roll_dice(num_rolls, dice):sum = 0tag = 0while num_rolls:current_num = dice()if current_num == 1:tag = Truesum += current_numnum_rolls -= 1if tag is True:return 1else:return sumdef make_averaged(fn, num_samples=4):def average(*args):i, total = 0, 0while (i < num_samples):total += fn(*args)i += 1return total / num_samplesreturn averagedice = make_test_dice(3, 1, 5, 6)
averaged_roll_dice = make_averaged(roll_dice, 4)
a = averaged_roll_dice(2, dice)

注意:

  1. 名称绑定的是函数,不同的名称可以绑定相同的函数,使用名称的本质是调用这个名称绑定的函数
    例子:

    def make_test_dice(*outcomes):index = len(outcomes) - 1def dice():nonlocal indexindex = (index + 1) % len(outcomes)return outcomes[index]
    return dice
    

    这里的return值绑定的是dice函数,所以如果调用make_test_dice,比如a = make_test_dice(3, 1, 5, 6),本质上就是把名称a绑定到dice函数。

  2. *args:传入不定长度的参数

  3. make_test_dice(3, 1, 5, 6)中的3,1,5,6以元组形式传入

CS61A第一章笔记相关推荐

  1. 计算机应用基础自学手写笔记,计算机应用基础第一章笔记.docx

    计算机应用基础第一章笔记 1.计算机工具的变迁 2.计算机的发展过程 3.冯.诺依曼计算机的工作原理 4.计算机系统的硬件和软件组成 5.计算机的性能指标 6.影响计算机的性能因素 7.数据在计算机中 ...

  2. 《Python深度学习》第一章笔记

    <Python深度学习>第一章笔记 1.1人工智能.机器学习.深度学习 人工智能 机器学习 深度学习 深度学习的工作原理 1.2深度学习之前:机器学习简史 概率建模 早期神经网络 核方法 ...

  3. Spring第一章笔记

    Spring第一章笔记 第一步: 配置pom文件导入依赖 <dependencies><dependency><groupId>org.springframewor ...

  4. 【智能计算系统笔记】第一章笔记及课后习题

    第一章笔记及课后习题 笔记 课后习题 1. 简述强人工智能和弱人工智能的区别. 2. 简述人工智能研究的三个学派. 3. 一个有两个输入的单个神经元构成的感知机能完成什么任务? 4. 深度学习的局限性 ...

  5. app研发录第一章笔记

    app研发录第一章笔记

  6. css高级教程第一章笔记

    2019独角兽企业重金招聘Python工程师标准>>> 大年30,今天刚刚看完第一章,上传上来一些笔记. 1.css:可以将文档的表现部分与内容分开 2.id:是唯一的,id可以用来 ...

  7. 《数据库系统概论》第一章笔记

    本书第一章,介绍了一些数据库的基本概念,是理解后序章节的基础. 笔记基本上对这些基础概念的摘录. 做笔记的目的,一是加深记忆和理解,二是方便以后资料查找. 1.1 数据库系统概述 1.1.1 数据库系 ...

  8. 自动驾驶决策规划算法第一章笔记 忠厚老实的老王

    第一章 自动驾驶决策规划算法数学基础 第一节:决策规划算法的地位和作用 该笔记来自b站up主(偶像):憨厚老实的老王视频链接主页 第二节:为什么规划中经常见到五次多项式

  9. Java核心技术·卷二·第一章笔记

    Java核心技术·卷二·笔记 第一章:Java8的流库 Java8引入的用来以"做什么而非怎么做"的方式的处理集合 1.1 从迭代到流的操作 package com.package ...

  10. 高等数学A(一)第一章笔记分享

    学校里有许多学弟学妹们马上就面临高数的期中考试了,不知道大家准备的怎么样了.我不敢自诩大佬,但是对自己的笔记还是很满意的!而且我依靠着这套笔记,在期末顺利拿到了满绩点. 希望大家在看完以后能有所收获, ...

最新文章

  1. 用Xamarin 实现园友的 :Android浮动小球与开机自启动
  2. gitkraen_超详细!Github团队协作教程(Gitkraken版)
  3. 飞鸽传书谈哈希表之数学原理
  4. OJ1180: 成绩统计(结构体专题)(C语言)
  5. c语言双精度百分号,C语言输出百分号%的方法和示例
  6. 2018-07-06笔记(LNMP配置)
  7. 被苹果“先捧后杀”的操作系统
  8. 剑指offer(Python版本)
  9. c语言以空格分割字符串_如何统计字符串中单词的个数?
  10. C#实现请求服务器,类似于asp下的getHTTPPage(url)功能
  11. Android基本动画
  12. Android通过webservice连接SQLServer 详细教程(数据库+服务器+客户端)
  13. R语言——相关系数图
  14. 服务器usb驱动安装系统安装失败怎么办,USB3.0驱动无法安装失败怎么办?USB驱动失败失败的解决方法...
  15. 第一章概述-------第一节--1.2互联网概述
  16. arcgis新建图层信息复制_ArcGIS中的数据库之间复制和粘贴数据
  17. Nginx基础应用配置小结 - 运维笔记
  18. Synchronized的前因后果
  19. serverless入门介绍
  20. leetcode阶段总结——拓扑排序

热门文章

  1. C# 字符串转JSON格式
  2. Basic SECS concept渣渣中文翻译
  3. 运算放大器分析----虚短和虚断简单计算
  4. 5 Openstack-Ussuri-Placement部署-ubuntu1804
  5. 百度云盘加速器for mac
  6. python建立英文语料库_使用NLTK创建新的语料库
  7. C语言----最长公共子串(动态规划)
  8. 单词播放器5.10发布
  9. 【立创开源】RGBW调光台灯
  10. Visio科学图形包下载以及安装详细教程