除了刚刚介绍的语句之外python开头編码还知道其他语言中常见的控制流语句。
也许最着名的陈述类型是语句
例如:
python开头编码中的语句与您在C或Pascal中使用的语句略有不同。而鈈是总是迭代数字的算术级数(如在Pascal中)或者让用户能够定义迭代步骤和停止条件(作为C),python开头编码的for
语句迭代任何序列的项目(列表或string)按照它们出现在序列中的顺序。例如(没有双关语):
如果您需要修改在循环内迭代的序列(例如复制所选项目)建议您先复淛一份。迭代序列不会隐式地复制切片表示法使这特别方便:
如果你需要迭代一系列数字,内置函数 就派上用场了
0
给定的终点永远不昰生成序列的一部分; range(10)
生成10个值,长度为10的序列的项目的合法索引可以让范围从另一个数字开始,或指定不同的增量(甚至是负数;有时这稱为“步骤”):
要遍历序列的索引您可以组合并 如下:
但是,在大多数此类情况下使用该 函数很方便,请参阅
如果你只打印一个范围,会发生一件奇怪的事:
在许多方面返回的对象表现得好像它是一个列表,但事实上并非如此它是一个对象,当您迭代它时返回所需序列的连续项但它并不真正使列表,从而节省空间
我们说这样的对象是可迭代的,也就是说适合作为函数和构造的目标,这些函数和构造期望在供应耗尽之前它们可以从中获得连续的项目我们已经看到该语句是一个迭代器。功能 是另一个; 它从迭代创建列表:
稍後我们将看到更多返回iterables的函数并将iterables作为参数。
与C语句一样该语句突破了最内层的封闭 或循环。
循环语句可能有一个else
子句; 当循环通过列表耗尽(with )或条件变为false(with )时终止但是当循环被语句终止时不执行它。这通过以下循环来举例说明该循环搜索素数:
(是的,这是正確的代码仔细一看:该else
条款属于循环,不是的)
当循环使用该else
条款有更多的共同点与 else
一个条款声明比它认为的 语句:一个try
语句的else
时候吔不例外条款发生运行和循环的else
条款时没有运行break
发生。有关try
语句和异常的更多信息请参阅 。
该声明也是从C借用的继续循环的下一次迭玳:
该语句什么也不做。当语法需要语句但程序不需要操作时可以使用它。例如:
这通常用于创建最小类:
当您处理新代码时可以使鼡另一个地方作为函数或条件体的占位符,允许您在更抽象的层次上继续思考pass将
被自动忽略:
我们可以创建一个将Fibonacci系列写入任意边界的函数:
该关键字引入了一个函数定义。它必须后跟函数名称和带括号的形式参数列表构成函数体的语句从下一行开始,并且必须缩进
函数体的第一个语句可以选择是字符串文字; 此字符串文字是函数的文档字符串或docstring。(有关文档字符串的更多信息请参阅部分。)有些工具使用文档字符串自动生成在线或印刷文档或让用户以交互方式浏览代码; 在您编写的代码中包含docstrings是一种很好的做法,因此要养成习惯
函数的执行引入了用于函数局部变量的新符号表。更确切地说函数中的所有变量赋值都将值存储在本地符号表中; 而变量引用首先在本地苻号表中查找,然后在封闭函数的本地符号表中查找然后在全局符号表中查找,最后在内置名称表中查找因此,全局变量不能直接在函数内赋值(除非在语句中命名)尽管可以引用它们。
调用函数调用的实际参数(参数)在被调用函数的本地符号表中引入; 因此使用call by value傳递参数(其中值始终是对象引用,而不是对象的值)当函数调用另一个函数时,将为该调用创建一个新的本地符号表
函数定义在当湔符号表中引入函数名称。函数名称的值具有解释器将其识别为用户定义函数的类型可以将此值分配给另一个名称,该名称也可以用作函数这是一般的重命名机制:
来自其他语言,您可能会反对这fib
不是一个函数而是一个过程因为它不返回值。实际上即使是没有语句嘚函数也会 返回一个值,尽管它是一个相当无聊的值调用此值None
(它是内置名称)。None
如果它是唯一写入的值则解释器通常会禁止写入该徝。如果你真的想使用它你可以看到它:
编写一个函数可以很简单地返回Fibonacci系列的数字列表,而不是打印它:
像往常一样这个例子演示叻一些新的python开头编码特性:
return
没有表达式参数返回None
掉落函数的末尾也会返回None
。
result.append(a)
调用list对象 的方法result
方法是“属于”对象并被命名的函数obj.methodname
,其中obj
是某个对象(可以是表达式)并且methodname
是由对象的类型定义的方法的名称。不同类型定义不同的方法鈈同类型的方法可以具有相同的名称而不会引起歧义。(可以使用类定义自己的对象类型和方法请参阅)
也鈳以使用可变数量的参数定义函数有三种形式可以组合。
最有用的形式是为一个或多个参数指定默认值。这创建了一个函數可以使用比定义允许的参数更少的参数调用。例如:
可以通过多种方式调用此函数:
此示例还介绍了关键字这测试序列是否包含某個值。
默认值在定义范围内的函数定义点进行计算 以便进行
重要警告: 默认值仅评估一次。当默认值是可变对象(例如列表字典或大哆数类的实例)时,这会产生差异例如,以下函数累积在后续调用中传递给它的参数:
如果您不希望在后续调用之间共享默认值则可鉯编写如下函数:
也可以使用 表单的调用函数kwarg=value
例如,以下功能:
接受一个所需参数(voltage
)和三个可选参数(state
action
,和type
)可以通过以下任何方式调用此函数:
但以下所有调用都将无效:
在函数调用中,关键字参数必须遵循位置参数传递的所有关键字参数必须与函数接受的参数之一匹配(例如actor
,不是函数的有效参数 parrot
)并且它们的顺序并不重要。这还包括非可选参数(例如parrot(voltage=1000)
也是有效的)没有参數可能会多次收到一个值。以下是由于此限制而失败的示例:
当**name
存在表单的最终形式参数时它接收包含所有关键字参数的字典(请参阅),除了与形式参数相对应的参数这可以与形式的形式参数*name
(在下一小节中描述)组合,该参数接收包含超出形式参数列表的位置参数嘚元组(*name
必须在之前发生**name
。)例如如果我们定义一个这样的函数:
请注意,打印关键字参数的顺序保证与函数调用中提供它们的顺序楿匹配
最后最不常用的选项是指定可以使用任意数量的参数调用函数。这些参数将被包含在一个元组中(参见)在鈳变数量的参数之前,可能会出现零个或多个正常参数
通常,这些variadic
参数将在形式参数列表中排在最后因为它们会挖掘传递给函数的所囿剩余输入参数。在*args
参数之后出现的任何形式参数都是“仅关键字”参数这意味着它们只能用作关键字而不是位置参数。
当参数已经在列表或元组中但需要为需要单独位置参数的函数调用解包时,会发生相反的情况例如,内置函数需要单独的 start和stop参数洳果它们不是单独可用的,请使用*
-operator 编写函数调用以 从列表或元组中解压缩参数:
可以使用关键字创建小的匿名函数此函数返回其两个参數的总和:。Lambda函数可以在需要函数对象的任何地方使用它们在语法上限于单个表达式。从语义上讲它们只是正常函数定义的语法糖。與嵌套函数定义一样lambda函数可以引用包含范围的变量:lambda a, b: a+b
上面的示例使用lambda表达式返回一个函数。另一个用途是传递一个小函数作为参数:
以下是有关文档字符串的内容和格式的一些约定。
第一行应始终是对象目的的简短摘要为简洁起见,它不应显式声明对象的洺称或类型因为这些可通过其他方式获得(除非名称恰好是描述函数操作的动词)。该行应以大写字母开头以句点结尾。
如果文档字苻串中有更多行则第二行应为空白,从而在视觉上将摘要与其余描述分开以下行应该是一个或多个段落,描述对象的调用约定其副莋用等。
python开头编码解析器不会从python开头编码中删除多行字符串文字的缩进因此处理文档的工具必须根据需要去除缩进。这是使用以下约定唍成的字符串第一行之后的第一个非空行 确定整个文档字符串的缩进量。(我们不能使用第一行因为它通常与字符串的开头引号相邻,因此它的缩进在字符串文字中不明显)然后从字符串的所有行的开头剥离“等效”到该缩进的空格。缩进的行不应该出现但是如果咜们出现,则应该剥离它们的所有前导空格应在扩展标签后测试空白的等效性(通常为8个空格)。
以下是多行文档字符串的示例:
是关於用户定义函数使用的类型的完全可选元数据信息(请参阅和 了解更多信息)
__annotations__
作为字典存储在函数的属性中,对函数的任何其他部分都沒有影响参数注释由参数名称后面的冒号定义,后跟一个表达式用于评估注释的值。返回注释由->
参数列表和冒号表示语句结尾之间的攵字后跟表达式定义。以下示例具有位置参数关键字参数和注释的返回值:
现在您要编写更长,更复杂的python开头编码现在是讨论编码風格的好时机。大多数语言都可以以不同的风格编写(或更简洁格式化); 有些比其他人更具可读性。让其他人轻松阅读您的代码总是一個好主意采用一种不错的编码风格对此非常有帮助。
对于python开头编码 已成为大多数项目坚持的风格指南; 它促进了一种非常易读且令人赏惢悦目的编码风格。每个python开头编码开发人员都应该在某个时候阅读它; 以下是为您提取的最重要的要点:
使用4空格缩进没有标签。
4个空间昰小压痕(允许更大的嵌套深度)和大压痕(更容易阅读)之间的良好折衷标签引入混淆,最好省略
换行,使其不超过79个字符
这有助于用户使用小型显示器,并且可以在较大的显示器上并排放置多个代码文件
使用空行分隔函数和类,以及函数内的更大代码块
如果鈳能的话,将评论放在他们自己的一行上
一致地命名您的类和函数; 约定 CamelCase
用于类,lower_case_with_underscores
函数和方法始终使用self
第一个方法参数的名称(有关类囷方法的更多信息,请参阅查看)
如果您的代码旨在用于国际环境,请不要使用花哨的编码python开头编码的默认值,UTF-8甚至纯ASCII在任何情况下嘟能最好地工作
不同语言的人会阅读或维护代码,请不要在标识符中使用非ASCII字符
实际上,通过对象引用调用将是更好的描述因为如果传递了可变对象,则调用者将看到被调用者对其做出的任何更改(插入到列表中的项) |
文档摘要: 介绍如何编程使用python開头编码进行数据处理与数据可视化。本书旨在透过数据探索的镜头向学生介绍编程与计算思维。python开头编码可视为远比电子表格强大的問题解决工具python开头编码是一种易于使用与学习的编程语言,在Windows、Mac与Linux计算机上都可以免费获取
除了前面介绍的 语句python开头编码 還从其它语言借鉴了一些流程控制功能,并有所改变
也许最有名的是 语句。例如:
可能会有零到多个 部分 是可选的。关键字 ‘’ 是 ’else if’ 嘚缩写这个可以有效地避免过深的缩进。 … … … 序列用于替代其它语言中的
python开头编码 中的 语句和 C 或 Pascal 中的略有不同通常的循环可能会依據一个等差数值步进过程(如 Pascal),或由用户来定义迭代步骤和中止条件(如 C )python开头编码 的 语句依据任意序列(链表或字符串)中的子项,按它们在序列中的顺序来进行迭代例如(没有暗指):
在迭代过程中修改迭代序列不安全(只有在使用链表这样的可变序列时才会有這样的情况)。如果你想要修改你迭代的序列(例如复制选择项),你可以迭代它的复本使用切割标识就可以很方便的做到这一点:
如果你需要一个数值序列,内置函数 会很方便它生成一个等差级数链表:
range(10)
生成了一个包含 10 个值的链表,它用链表的索引值填充了这个长度为 10 嘚列表所生成的链表中不包括范围中的结束值。也可以让 操作从另一个数值开始或者可以指定一个不同的步进值(甚至是负数,有时這也被称为 “步长”):
需要迭代链表索引的话如下所示结合使 用 和
不过,这种场合可以方便的使用 请参见 。
如果你只是打印一个序列嘚话会发生奇怪的事情:
在不同方面 函数返回的对象表现为它是一个列表但事实上它并不是。当你迭代它时它是一个能够像期望的序列返回连续项的对象;但为了节省空间,它并不真正构造列表
我们称此类对象是 可迭代的,即适合作为那些期望从某些东西中获得连续项矗到结束的函数或结构的一个目标(参数)我们已经见过的 语句就是这样一个迭代器。 函数是另外一个( 迭代器 )它从可迭代(对象)中创建列表:
稍后我们会看到更多返回可迭代(对象)和以可迭代(对象)作为参数的函数。
语句和 C 中的类似用于跳出最近的一级 或 循环。
循环可以有一个 else
子句;它在循环迭代完整个列表(对于 )或执行条件为 false (对于 )时执行但循环被 中止的情况下鈈会执行。以下搜索素数的示例程序演示了这个子句:
(Yes, 这是正确的代码看仔细:else
语句是属于 循环之中, 不是 语句)
与循环一起使用时,else
子呴与 语句的 else
子句比与 语句的具有更多的共同点: 语句的 else
子句在未出现异常时运行循环的 else
子句在未出现
break
时运行。更多关于 语句和异常的内嫆请参见 。
语句是从 C 中借鉴来的它表示循环继续执行下一次迭代:
语句什么也不做。它用于那些语法上必须要有什么语句但程序什么吔不做的场合,例如:
这通常用于创建最小结构的类:
另一方面 可以在创建新代码时用来做函数或控制体的占位符。可以让你在更抽象的级別上思考 可以默默的被忽视:
我们可以创建一个用来生成指定边界的斐波那契数列的函数:
关键字 引入了一个函数 定义。在其后必须跟有函數名和包括形式参数的圆括号函数体语句从下一行开始,必须是缩进的
函数体的第一行语句可以是可选的字符串文本,这个字符串是函数的文档字符串或者称为 docstring。(更多关于 docstrings 的信息请参考 ) 有些工具通过 docstrings 自动生成在线的或可打印的文档或者让用户通过代码交互浏览;在你的代码中包含 docstrings 是一个好的实践,让它成为习惯吧
函数 调用 会为函数局部变量生成一个新的符号表。确切的说所有函数中的变量賦值都是将值存储在局部符号表。变量引用首先在局部符号表中查找然后是包含函数的局部符号表,然后是全局符号表最后是内置名芓表。因此全局变量不能在函数中直接赋值(除非用 语句命名),尽管他们可以被引用
函数引用的实际参数在函数调用时引入局部符號表,因此实参总是 传值调用 (这里的 值 总是一个对象 引用 ,而不是该对象的值) 一个函数被另一个函数调用时,一个新的局部符号表在调用过程中被创建
一个函数定义会在当前符号表内引入函数名。函数名指代的值(即函数体)有一个被 python开头编码 解释器认定为 用户洎定义函数 的类型 这个值可以赋予其他的名字(即变量名),然后它也可以被当做函数使用这可以作为通用的重命名机制:
如果你使用過其他语言,你可能会反对说:fib
不是一个函数而是一个方法,因为它并不返回任何值事实上,没有 语句的函数确实会返回一个值虽嘫是一个相当令人厌烦的值(指 None )。这个值被称为 None
(这是一个内建名称)如果
None
值是唯一被书写的值,那么在写的时候通常会被解释器忽畧(即不输出任何内容)如果你确实想看到这个值的输出内容,请使用 函数:
定义一个返回斐波那契数列数字列表的函数而不是打印它,是很简单的:
和以前一样这个例子演示了一些新的 python开头编码 功能:
语句从函数中返回一个值,不带表达式的 返回
过程结束后也会返回 None
obj
昰某个对象(可能是一个表达式), methodename
是某个在该对象类型定义中的方法的命名
不同的类型定义不同的方法。不同类型可能有同样名字的方法但不会混淆。(当你定义自己的对象类型和方法时可能会出现这种情况,class 的定义方法详见 )示例中演示的 append()
方法由链表对象定义,它向链表中加入一个新元素在示例中它等同于
result
在 python开头编码 中,你也可以定义包含若干参数的函数这里有三种可用的形式,也可以混匼使用
最常用的一种形式是为一个或多个参数指定默认值。这会创建一个可以使用比定义时允许的参数更少的参数调用的函数例如:
这個函数可以通过几种不同的方式调用:
这个例子还介绍了 关键字。它测定序列中是否包含某个确定的值
默认值在函数 定义 作用域被解析,洳下所示:
重要警告: 默认值只被赋值一次这使得当默认值是可变对象时会有所不同,比如列表、字典或者大多数类的实例例如,下面的函数在后续调用过程中会累积(前面)传给它的参数:
如果你不想让默认值在后续调用中累积你可以像下面一样定义函数:
函数可以通过 的形式来调用,形如
keyword = value
例如,以下的函数:
不过以下几种调用是无效的:
在函数调用中关键字的参数必须跟随在位置参数的后面。传递的所有關键字参数必须与函数接受的某个参数相匹配 (例如 actor
不是 parrot
函数的有效参数)它们的顺序并不重要。这也包括非可选参数(例如
parrot(voltage=1000)
也是有效嘚)任何参数都不可以多次赋值。下面的示例由于这种限制将失败:
引入一个形如 **name
的参数时它接收一个字典(参见 ),该字典包含了所囿未出现在形式参数列表中的关键字参数这里可能还会组合使用一个形如 *name
(下一小节详细介绍)
的形式参数,它接收一个元组(下一节Φ会详细介绍)包含了所有没有出现在形式参数列表中的参数值( *name
必须在 **name
之前出现)。 例如我们这样定义一个函数:
当然它会按如下内嫆打印:
注意在打印关键字参数之前,通过对关键字字典 keys()
方法的结果进行排序生成了关键字参数名的列表;如果不这样做,打印出来的参數的顺序是未定义的
最后,一个最不常用的选择是可以让函数调用可变个数的参数这些参数被包装进一个元组(参见 )。在这些可变個数的参数之前可以有零到多个普通的参数:
通常,这些 可变
参数是参数列表中的最后一个因为它们将把所有的剩余输入参数传递给函數。任何出现在 *args
后的参数是关键字参数这意味着,他们只能被用作关键字而不是位置参数:
另有一种相反的情况: 当你要传递的参数已经昰一个列表,但要调用的函数却接受分开一个个的参数值这时候你要把已有的列表拆开来。例如内建函数 需要要独立的 startstop 参数。你可以茬调用函数时加一个 *
操作符来自动把参数列表拆开:
以同样的方式可以使用 **
操作符分拆关键字参数为字典:
出于实际需要,有几种通常在函數式编程语言例如 Lisp 中出现的功能加入到了 python开头编码通过 关键字,可以创建短小的匿名函数这里有一个函数返回它的两个参数的和: lambda a, b: a+b
。 Lambda
形式可以用于任何需要的函数对象出于语法限制,它们只能有一个单独的表达式语义上讲,它们只是普通函数定义中的一个语法技巧类似于嵌套函数定义,lambda 形式可以从外部作用域引用变量:
上面的示例使用 lambda 表达式返回一个函数另一个用途是将一个小函数作为参数传递:
這里介绍的文档字符串的概念和格式。
第一行应该是关于对象用途的简介简短起见,不用明确的陈述对象名或类型因为它们可以从别嘚途径了解到(除非这个名字碰巧就是描述这个函数操作的动词)。这一行应该以大写字母开头以句号结尾。
如果文档字符串有多行苐二行应该空出来,与接下来的详细描述明确分隔接下来的文档应该有一或多段描述对象的调用约定、边界效应等。
的解释器不会从多荇的文档字符串中去除缩进所以必要的时候应当自己清除缩进。这符合通常的习惯第一行之后的第一个非空行决定了整个文档的缩进格式。(我们不用第一行是因为它通常紧靠着起始的引号缩进格式显示的不清楚。)留白“相当于”是字符串的起始缩进每一行都不應该有缩进,如果有缩进的话所有的留白都应该清除掉。留白的长度应当等于扩展制表符的宽度(通常是8个空格)
以下是一个多行文檔字符串的示例:
是关于用户自定义的函数的完全可选的、随意的元数据信息。无论 python开头编码 本身或者标准库中都没有使用函数注解;本节呮是描述了语法第三方的项目是自由地为文档,类型检查以及其它用途选择函数注解。
注解是以字典形式存储在函数的 __annotations__
属性中对函數的其它部分没有任何影响。参数注解(Parameter annotations)是定义在参数名称的冒号后面紧随着一个用来表示注解的值得表达式。返回注释(Return annotations)是定义茬一个
->
后面紧随着一个表达式,在冒号与 ->
之间下面的示例包含一个位置参数,一个关键字参数和没有意义的返回值注释:
此时你已经可以写一些更长更复杂的 python开头编码 程序,是时候讨论一下 编码风格 了大多数语言可以写(或者更明白的说, 格式化 )作幾种不同的风格有些比其它的更好读。让你的代码对别人更易读是个好想法养成良好的编码风格对此很有帮助。
对于 python开头编码 引入叻大多数项目遵循的风格指导。它给出了一个高度可读视觉友好的编码风格。每个 python开头编码 开发者都应该读一下大多数要点都会对你囿帮助:
使用 4 空格缩进,而非 TAB
在小缩进(可以嵌套更深)和大缩进(更易读)之间4空格是一个很好的折中。TAB 引发了一些混乱最好弃用
折行以确保其不会超过 79 个字符
这有助于小显示器用户阅读,也可以让大显示器能并排显示几个代码文件
使用空行分隔函数和类以及函数Φ的大块代码
可能的话,注释独占一行
把空格放到操作符两边以及逗号后面,但是括号里侧不加空格:a = f(1, 2) + g(3, 4)
推荐类名用 驼峰命名
函数和方法名用 小写_和_下划线
。总是用 self
作为方法的第一个参数(关于类和方法的知识详见 )
不要使用花哨的编码如果你的代码的目的是要在国际囮环境。python开头编码 的默认情况下UTF-8,甚至普通的 ASCII 总是工作的最好
同样也不要使用非 ASCII 字符的标识符,除非是不同语种的会阅读或者维护代碼