Advanced Search
Search Results
155 total results found
Conditional Operators
Right now, we know how to use simple conditions in if-else statements. What if we wanted to check the opposite of a condition? What about chaining conditions? not The purpose of this operator is to negate the condition it's applied to. For example: not True i...
2.1 引言
在第一章中,我们专注于计算过程,以及程序设计中函数的作用。我们看到了如何使用原始数据(数值)和原始操作(算术运算),如何通过组合和控制来形成复合函数,以及如何通过给予过程名称来创建函数抽象。我们也看到了高阶函数通过操作通用计算方法来提升语言的威力。这是编程的本质。 这一章会专注于数据。数据允许我们通过使用已经获得的计算工具,表示和操作与世界有关的信息。脱离数据结构的编程可能会满足于探索数学特性,但是真实世界的情况,比如文档、关系、城市和气候模式,都拥有复杂的结构,它最好使用复合数据类型来表现。归功于互联网的高速发展...
3.1 引言
第一章和第二章描述了编程的两个基本元素:数据和函数之间的紧密联系。我们看到了高阶函数如何将函数当做数据操作。我们也看到了数据可以使用消息传递和对象系统绑定行为。我们已经学到了组织大型程序的技巧,例如函数抽象,数据抽象,类的继承,以及泛用函数。这些核心概念构成了坚实的基础,来构建模块化,可维护和可扩展的程序。 这一章专注于编程的第三个基本元素:程序自身。Python 程序只是文本的集合。只有通过解释过程,我们才可以基于文本执行任何有意义的计算。类似 Python 的编程语言很实用,因为我们可以定义解释器,它是一个执行...
2.7 泛用方法
这一章中我们引入了复合数据类型,以及由构造器和选择器实现的数据抽象机制。使用消息传递,我们就能使抽象数据类型直接拥有行为。使用对象隐喻,我们可以将数据的表示和用于操作数据的方法绑定在一起,从而使数据驱动的程序模块化,并带有局部状态。 但是,我们仍然必须展示,我们的对象系统允许我们在大型程序中灵活组合不同类型的对象。点运算符的消息传递仅仅是一种用于使用多个对象构建组合表达式的方式。这一节中,我们会探索一些用于组合和操作不同类型对象的方式。 2.7.1 字符串转换 我们在这一章最开始说,对象值的行为应该类似它所表达的数...
2.6 实现类和对象
在使用面向对象编程范式时,我们使用对象隐喻来指导程序的组织。数据表示和操作的大部分逻辑都表达在类的定义中。在这一节中,我们会看到,类和对象本身可以使用函数和字典来表示。以这种方式实现对象系统的目的是展示使用对象隐喻并不需要特殊的编程语言。即使编程语言没有面向对象系统,程序照样可以面向对象。 为了实现对象,我们需要抛弃点运算符(它需要语言的内建支持),并创建分发字典,它的行为和内建对象系统的元素差不多。我们已经看到如何通过分发字典实现消息传递行为。为了完整实现对象系统,我们需要在实例、类和基类之间发送消息,它们全部都...
2.5 面向对象编程
面向对象编程(OOP)是一种用于组织程序的方法,它组合了这一章引入的许多概念。就像抽象数据类型那样,对象创建了数据使用和实现之间的抽象界限。类似消息传递中的分发字典,对象响应行为请求。就像可变的数据结构,对象拥有局部状态,并且不能直接从全局环境访问。Python 对象系统提供了新的语法,更易于为组织程序实现所有这些实用的技巧。 但是对象系统不仅仅提供了便利;它也为程序设计添加了新的隐喻,其中程序中的几个部分彼此交互。每个对象将局部状态和行为绑定,以一种方式在数据抽象背后隐藏二者的复杂性。我们的约束程序的例子通过在约...
2.4 可变数据
我们已经看到了抽象在帮助我们应对大型系统的复杂性时如何至关重要。有效的程序整合也需要一些组织原则,指导我们构思程序的概要设计。特别地,我们需要一些策略来帮助我们构建大型系统,使之模块化。也就是说,它们可以“自然”划分为可以分离开发和维护的各个相关部分。 我们用于创建模块化程序的强大工具之一,是引入可能会随时间改变的新类型数据。这样,单个数据可以表示独立于其他程序演化的东西。对象行为的改变可能会由它的历史影响,就像世界中的实体那样。向数据添加状态是这一章最终目标:面向对象编程的要素。 我们目前引入的原生数据类型 --...
2.3 序列
序列是数据值的顺序容器。不像偶对只有两个元素,序列可以拥有任意(但是有限)个有序元素。 序列在计算机科学中是强大而基本的抽象。例如,如果我们使用序列,我们就可以列出伯克利的每个学生,或者世界上的每所大学,或者每所大学中的每个学生。我们可以列出上过的每一门课,提交的每个作业,或者得到的每个成绩。序列抽象让数千个数据驱动的程序影响着我们每天的生活。 序列不是特定的抽象数据类型,而是不同类型共有的一组行为。也就是说,它们是许多序列种类,但是都有一定的属性。特别地, **长度。**序列拥有有限的长度。 **元素选择。**序...
2.2 数据抽象
由于我们希望在程序中表达世界中的大量事物,我们发现它们的大多数都具有复合结构。日期是年月日,地理位置是精度和纬度。为了表示位置,我们希望程序语言具有将精度和纬度“粘合”为一对数据的能力 -- 也就是一个复合数据结构 -- 使我们的程序能够以一种方式操作数据,将位置看做单个概念单元,它拥有两个部分。 复合数据的使用也让我们增加程序的模块性。如果我们可以直接将地理位置看做对象来操作,我们就可以将程序的各个部分分离,它们根据这些值如何表示来从本质上处理这些值。将某个部分从程序中分离的一般技巧是一种叫做数据抽象的强大的设计...
1.6 高阶函数
我们已经看到,函数实际上是描述复合操作的抽象,这些操作不依赖于它们的参数值。在square中, >>> def square(x): return x * x 我们不会谈论特定数值的平方,而是一个获得任何数值平方的方法。当然,我们可以不定义这个函数来使用它,通过始终编写这样的表达式: >>> 3 * 3 9 >>> 5 * 5 25 并且永远不会显式提及square。这种实践适合类似square的简单操作。但是对于更加复杂的操作会变得困难。通常,缺少函数定义会对我们非常不利,它会强迫我们始终工作...
Loops
We learned about conditions and saw how we can use them to make our code run only when we want it to. What if we wanted to do something over and over until a condition was met? For example, what if we wanted to count down from 5? Brute Force We could do this: ...
1.5 控制
我们现在可以定义的函数能力有限,因为我们还不知道一种方法来进行测试,并且根据测试结果来执行不同的操作。控制语句可以让我们完成这件事。它们不像严格的求值子表达式那样从左向右编写,并且可以从它们控制解释器下一步做什么当中得到它们的名称。这可能基于表达式的值。 1.5.1 语句 目前为止,我们已经初步思考了如何求出表达式。然而,我们已经看到了三种语句:赋值、def和return语句。这些 Python 代码并不是表达式,虽然它们中的一部分是表达式。 要强调的是,语句的值是不相干的(或不存在的),我们使用执行而不是求值来描...
1.4 实践指南:函数的艺术
函数是所有程序的要素,无论规模大小,并且在编程语言中作为我们表达计算过程的主要媒介。目前为止,我们讨论了函数的形式特性,以及它们如何使用。我们现在跳转到如何编写良好的函数这一话题。 每个函数都应该只做一个任务。这个任务可以使用短小的名称来定义,使用一行文本来标识。顺序执行多个任务的函数应该拆分在多个函数中。 不要重复劳动(DRY)是软件工程的中心法则。所谓的DRY原则规定多个代码段不应该描述重复的逻辑。反之,逻辑应该只实现一次,指定一个名称,并且多次使用。如果你发现自己在复制粘贴一段代码,你可能发现了一个使用函数抽...
1.3 定义新的函数
我们已经在 Python 中认识了一些在任何强大的编程语言中都会出现的元素: 数字是内置的数值,算数运算是函数。 嵌套函数提供了组合操作的手段。 名称到值的绑定提供了有限的抽象手段。 现在我们将要了解函数定义,一个更加强大的抽象技巧,名称通过它可以绑定到复合操作上,并可以作为一个单元来引用。 我们通过如何表达“平方”这个概念来开始。我们可能会说,“对一个数求平方就是将这个数乘上它自己”。在 Python 中就是: >>> def square(x): return mul(x, x) 这定义了一个...
1.2 编程元素
编程语言是不仅仅是操作计算机来执行任务的一种手段,它也充当着一种框架,我们在其中组织计算过程的想法。程序用于在编程社群的成员之间交流这些想法。所以,程序必须为人们阅读而编写,并且顺便可以让机器执行。 当我们描述一种语言时,我们应该特别注意这种语言提供的将简单的想法组合为更复杂的想法的方法。每个强大的语言都拥有这样的三种机制: 原语表达式和语句,表示语言提供的最简单的构建代码块 组合方法,通过它由简单的元素来构建复杂的元素 抽象方法,复杂的元素可以通过它来命名,以及作为整体来操作 在编程中,我们处理两种元素:函...
1.1 入门
计算机科学是一个极其宽泛的学科。全球的分布式系统、人工智能、机器人、图形、安全、科学计算,计算机体系结构和许多新兴的二级领域,每年都会由于新技术和新发现而扩展。计算机科学的快速发展广泛影响了人类生活。商业、通信、科学、艺术、休闲和政治都被计算机领域彻底改造。 计算机科学的巨大生产力可能只是因为它构建在一系列优雅且强大的基础概念上。所有计算都以表达信息、指定处理它所需的逻辑、以及设计管理逻辑复杂性的抽象作为开始。对这些基础的掌握需要我们精确理解计算机是如何解释程序以及执行计算过程。 这些基础概念在伯克利长期被教授,使...
Environments
If you haven't read my notes on environment diagrams, now is a good time to read those. Parent Frames With the exception of the global frame, every function's execution frame has a parent: the frame in which the function was created. When you call a function, ...
Higher Order Functions
Remember the add_2 function from the previous section on lambdas? What if we wanted to make a generic add_x function, where x is any arbitrary value? I know this sounds ridiculous: why would you overcomplicate a simple x + y operation? Bear with me here -- the...
Lambdas
Let's take a break from all this new condition and loop stuff and go back to something we recognize: functions. Remember these? def hello(): print("world!") Simple one-line functions like these are pretty common (though typically they'll do something more...
3.2 函数和所生成的过程
函数是计算过程的局部演化模式。它规定了过程的每个阶段如何构建在之前的阶段之上。我们希望能够创建有关过程整体行为的语句,而过程的局部演化由一个或多个函数指定。这种分析通常非常困难,但是我们至少可以试图描述一些典型的过程演化模式。 在这一章中,我们会检测一些用于简单函数所生成过程的通用“模型”。我们也会研究这些过程消耗重要的计算资源,例如时间和空间的比例。 3.2.1 递归函数 如果函数的函数体直接或者间接自己调用自己,那么这个函数是递归的。也就是说,递归函数的执行过程可能需要再次调用这个函数。Python 中的递归函...