1. 编程与Python简介
1.1 编程与Python简介
编程 (Programming) 是一种指导计算机执行任务的过程。这涉及了创建所谓的程序,这些程序是包含一系列步骤的指令。在执行程序时,计算机将遵循这些指令以完成特定的任务。每一种编程语言(Programming Language)都有自己的语法和规则,这些规则定义了指令的编写方式。
Python 是一种高级、动态类型的解释型语言(Interpreted Language)。它被设计成易于阅读,并具有显著的可读性优势。在Python中,重要的是清晰的语法和代码的可读性,这也是 Guido van Rossum 在1989年创建Python时的原始理念,他强调的是“一种方法,最好只有一种,尽管这可能并不明显”。
与C++相比,Python语言的主要区别之一在于其类型系统。在C++中,数据类型在编译时是静态决定的(也就是说,在编译程序之前),而在Python中,类型是动态决定的,即在运行时。此外,Python是解释执行的,而C++是编译执行的。
Python的设计原则都包含在Zen of Python 中,也称之为Python之禅。其中包含了诸如“简单胜于复杂”、“明了胜于隐晦”等原则,这正是Python语言的魅力所在。
让我们看一个Python的示例代码:
# 这是一个Python的示例代码 print("Hello, World!")
在以上代码中,print()
函数用于在控制台上输出文本。在这个例子中,它输出了文本 “Hello, World!”。
如果我们想要表述这个句子,我们可以说:“Use the print
function to output ‘Hello, World!’ on the console. (使用print函数在控制台上输出 ‘Hello, World!’)”。
在接下来的章节中,我们将深入探讨Python的基础语法,并通过实例来学习Python和C++之间的差异。
2. 编码
2.1 Python 编码的重要性
在Python中,编码(Encoding)是至关重要的一环。在我们谈论编码时,我们是指字符集的编码,也就是字符如何在计算机中被表示和处理的方式。如果不使用正确的编码,你的Python程序可能会遇到一些问题,如乱码或字符解读错误。
C++默认使用的是ASCII编码,对于非ASCII字符,例如中文、日语或阿拉伯语,ASCII无法表示。而Python3使用Unicode(Unicode),这使得Python3可以处理世界上几乎所有语言的文本。
在日常英语交流中,我们通常说 “Python uses Unicode for text encoding” (Python使用Unicode进行文本编码)。
Python的编码可以在脚本的顶部通过特殊的注释来指定,一般格式如下:
# -*- coding: utf-8 -*-
这告诉Python解释器,我们将使用UTF-8编码来读取源代码。UTF-8编码是Unicode标准的一种实现,它能够兼容ASCII编码,同时也能够处理任何Unicode字符。
这是一个示例,它展示了如果不设置正确的编码,Python可能会遇到解读问题。
# Without encoding specification print("你好, 世界!")
在不支持中文字符的环境中运行以上代码,你可能会得到一个字符解读错误。但是,如果你在文件开头指定了正确的编码,问题就能得到解决。
# -*- coding: utf-8 -*- print("你好, 世界!")
这就是为什么我们需要在编程中设置合适的编码。它不仅能帮助我们处理多语言文本,还能提高程序的兼容性和健壮性。
在C++中,你可能需要进行额外的工作来处理Unicode字符,包括引入特殊的库和使用特殊的函数,而Python3为我们处理了这些问题,使得编程变得更简单。
接下来,我们将详细讨论如何在Python中设置编码。
2.2 如何在Python中设置编码
在Python中,你可以通过在源文件的开头添加一行特殊注释来设置编码。Python编译器会读取这个注释,以确定应该使用哪种字符集编码来解析源代码。
这里是常见的编码设置注释:
# -*- coding: utf-8 -*-
以上注释告诉Python解释器,你将使用UTF-8编码来读取和解析源代码。UTF-8是Unicode的一种实现,它可以兼容ASCII,并且能处理任何Unicode字符。Python3默认就是使用UTF-8编码的。
我们来看一个具体的例子,这个例子演示了如何使用编码注释处理非ASCII字符:
# -*- coding: utf-8 -*- print("你好,世界!")
在这个例子中,我们使用中文字符,如果没有在文件开头指定UTF-8编码,Python解释器可能无法正确解析这些中文字符。
值得注意的是,如果你的代码完全是使用ASCII字符写的,那么你不需要指定编码,因为UTF-8是与ASCII兼容的。但是,如果你的代码中包含非ASCII字符,例如使用了中文、法语、德语等语言的字符,那么你应该在文件的开头添加编码注释。
在日常英语交流中,我们通常说 “You can specify the encoding used by Python with a special comment at the top of your file.” (你可以在文件顶部使用特殊注释来指定Python使用的编码。)
对于从C/C++转向Python的开发者来说,这是一个很大的优点。在C/C++中,处理Unicode字符可能需要大量的工作,包括引入特殊的库和使用特殊的数据类型。但在Python中,处理Unicode只需要一个简单的文件头注释,使得开发过程更为简单和直接。
这个功能使得Python更具有国际化的特性,它可以处理世界上任何语言的文本,这也是Python在全球范围内流行的原因之一。
3. Python中的标识符
3.1 定义和规则
在编程语言中,标识符(identifier)是用来识别特定项目的名称。在Python中,标识符可以是类(class)、函数(function)、模块(module)、变量(variable)等的名字。
在Python3中,标识符有以下规则:
- 标识符由字母、数字和下划线(_)组成,但不能以数字开头。
- Python是区分大小写的语言,因此,
myname
和MyName
是两个不同的标识符。 - 尽管Python3支持非ASCII标识符,但通常建议使用英文标识符。
# 正确的标识符 my_var = 10 _var = 20 var9 = 30 # 错误的标识符 9var = 40 # 这会抛出一个语法错误,因为标识符不能以数字开头
在英语中,我们常常会说:“I’m declaring a variable called my_var
, which is set to 10.”(我正在声明一个名为 my_var
的变量,将其设置为10。)
与C/C++的区别
在C++中,标识符规则和Python类似,但C++不支持非ASCII标识符。这是Python更加国际化的一个体现。
例如,你不能在C++中使用如下的标识符:
int 变量 = 10; // 这在C++中是无效的
但在Python中,这是完全可以的:
变量 = 10 # 这在Python中是有效的
尽管如此,我们还是建议在编程时,无论在使用何种语言,都最好使用英文标识符,因为这会使你的代码更易于被全球的开发者理解和使用。
在英语中,当你需要对C++中的标识符规则进行描述时,你可以这样说:“In C++, identifiers must start with a letter or an underscore, and the rest of the identifier can contain letters, numbers, and underscores. But unlike Python, non-ASCII identifiers are not allowed.” (在C++中,标识符必须以字母或下划线开头,标识符的其他部分可以包含字母、数字和下划线。但与Python不同的是,C++不允许使用非ASCII标识符。)
当我们在阅读Python的官方文档或其他著作,如《Python核心编程》时,我们会发现Python非常重视标识符的规则和使用习惯。这是因为标识符是代码可读性和可
维护性的关键部分。在Python的源码中,我们可以看到标识符的使用都是遵循一定的规则和约定的,例如PEP 8提供了Python的编码规范,包括标识符的命名规则和最佳实践。
项目 | Python | C++ |
标识符规则 | 字母/数字/下划线 | 字母/数字/下划线 |
是否支持非ASCII标识符 | 是 | 否 |
是否区分大小写 | 是 | 是 |
是否能以数字开头 | 否 | 否 |
以上表格总结了Python和C++在标识符方面的主要区别。这些细微的差别可能会对编程有重要的影响,尤其是在编写多语言项目或从一种语言迁移到另一种语言时。
理解这些规则和差异对于编程人员来说非常重要,不仅有助于我们编写出更好的代码,而且还能帮助我们更好地理解不同编程语言的设计理念和优势。在学习和使用Python的过程中,我们应该充分利用其灵活性和表达力,同时也不忘遵守其规则,写出清晰、简洁且可维护的代码。
3.2 标识符的命名最佳实践
选择好的标识符名称对于编写清晰、易读的代码至关重要。以下是一些Python标识符命名的最佳实践:
- 清晰性:标识符应清楚地表明它代表的是什么。例如,
student_names
比s
或sn
更清晰。
# 好的标识符命名示例 student_names = ['John', 'Mary', 'Paul'] # 不好的标识符命名示例 s = ['John', 'Mary', 'Paul'] # 这会让其他人难以理解你的代码意图
- 长度:标识符应足够长,以便其他人理解其含义,但也不能太长,否则会让代码显得冗余和难以阅读。
- 使用小写字母和下划线:对于变量和函数名,推荐使用小写字母和下划线(这被称为蛇形命名,snake_case)。对于类名,推荐使用驼峰命名(CamelCase)。
# 好的标识符命名示例 def calculate_average(nums): return sum(nums) / len(nums) class StudentRecord: pass # 不好的标识符命名示例 def c(nums): # 这会让其他人难以理解你的代码意图 return sum(nums) / len(nums) class studentrecord: # 应使用驼峰命名法来命名类 pass
与C/C++的区别
在C++中,虽然也有类似的命名习惯,但C++社区中更倾向于使用驼峰命名法(CamelCase)或帕斯卡命名法(PascalCase)。同时,C++的标准库中,下划线开头的标识符有特殊含义,因此在命名时需要避免使用下划线开头。
在英语口语中,当我们讨论这个话题时,我们可能会这样说:“When naming identifiers in Python, we usually use snake_case for variable and function names, and CamelCase for class names. But in C++, the community prefers CamelCase or PascalCase. Also, identifiers that begin with an underscore have special meanings in the C++ standard library.” (在Python中命名标识符时,我们通常对变量和函数名使用蛇形命名法,对类名使用驼峰命名法。但在C++中,社区更喜欢使用驼峰命名法或帕斯卡命名法。此外,在C++标准库中,以下划线开头的标识符具有特殊含义。)
在Python官方文档和《Python核心编程》等经典著作中,都强调了命名约定的重要性。根据PEP 8,我们在命名Python标识符时应遵循以上的最佳实践,这将有助于我们编写出更清晰、更易维护的代码。
4. 保留字 (Reserved Words)
4.1 保留字的概念及其列表
在Python中,保留字(Reserved Words,或称之为关键字 Key Words)是被编程语言保留,有特定功能的单词,不能用作标识符(如变量名,函数名等)。这些保留字在Python中都是小写的。
以下是Python 3的保留字列表:
import keyword print(keyword.kwlist)
运行上述代码,你将看到Python 3的所有保留字,如下所示:
['False', 'None', 'True', 'and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']
对于有C++基础的读者,你们应该注意到Python的保留字列表并不包含C++的保留字,例如"public", "private"或"virtual"等。这是因为Python不是一种面向对象的语言,它没有诸如私有或公有访问修饰符的概念。
对比C++,Python的保留字数量较少,表明Python语法更简洁,但这并不意味着Python的功能较弱,实际上Python是一种功能强大的语言。
在口语交流中,你可以这样描述保留字:“In Python, reserved words, also known as keywords, are identifiers that are reserved by the language and have special meanings. They can’t be used for other purposes such as naming variables or functions.”(在Python中,保留字,也称关键字,是语言保留的标识符,具有特殊含义。它们不能用于其他用途,如命名变量或函数。)
4.2 保留字的使用示例
接下来,我们会通过一些实例来说明Python保留字的使用。这些实例对于理解保留字在实际编程中如何使用是非常有帮助的。
if, else, elif
在Python中,if
, else
, elif
用于构建条件语句(conditional statements)。
age = 20 if age > 18: print("You are an adult.") else: print("You are a minor.")
如果你有C++经验,你可能会注意到Python的 elif
相当于C++中的 else if
。
for, while, break, continue
for
和 while
用于创建循环(loops),break
用于跳出循环,而 continue
用于跳过循环的当前迭代。
for i in range(5): if i == 3: continue print(i)
在此代码中,当 i
等于 3 时, continue
语句导致循环跳过剩余的代码块并直接进入下一次迭代。
def, class
def
和 class
关键字用于定义函数和类。
def my_function(): print("Hello from my function!") class MyClass: def my_method(self): print("Hello from my method!")
对于熟悉C++的读者来说,Python中的 def
相当于C++中的函数声明,而Python的 class
用法与C++的类似。不过请注意,在Python中,我们使用 def
关键字来定义类的方法,而不是像C++那样直接在类内部定义函数。
这些都是Python保留字的基本使用情况。每个保留字都有其特定的用途和上下文,这就是为什么我们不能使用它们作为变量名或函数名的原因。
5. 注释
5.1 Python中的注释
在Python中,我们使用 #
符号来开始一个单行注释,也就是说,在 #
之后的所有内容都将被Python解释器忽略。在编程中,我们通常使用注释来解释代码的功能,这对于后期的代码维护非常重要。
# 这是一个单行注释 print("Hello, World!") # 这是在代码后面添加的注释
在这个例子中,Python解释器会忽略所有 #
之后的内容,只执行 print("Hello, World!")
。
与C++或C语言不同,在Python中并没有专门的多行注释符号(如C++中的/*...*/
)。然而,我们可以使用三个连续的单引号('''
)或双引号("""
)来创建多行字符串,这个特性也常被用于创建多行注释。
''' 这是一个多行注释 这是注释的第二行 这是注释的第三行 ''' print("Hello, World!")
这里的多行字符串被Python解释器忽略,因此它们也可以被用作多行注释。
请注意,使用多行字符串作为注释并不是Python官方推荐的方式,它在Python社区中的接受度各不相同。Python官方推荐的方式是在每一行前面都使用一个 #
符号来创建多行注释。比如:
# 这是一个多行注释 # 这是注释的第二行 # 这是注释的第三行 print("Hello, World!")
这种方式虽然略显冗余,但是它更符合Python的设计理念——“明确胜于隐晦”(“Explicit is better than implicit”,摘自《Python之禅》)。
与此同时,Python也提供了一种特殊的注释——文档字符串(也称为 docstrings)。文档字符串使用三个连续的单引号('''
)或双引号("""
)创建,通常用于解释一个函数、模块或类的功能。它们被包含在函数、模块或类的定义之中,并可以通过内置的 help()
函数查看。
def add(a, b): ''' 这是一个用于加法的函数。 它接受两个参数 a 和 b,返回他们的和。 ''' return a + b help(add)
运行上面的代码将会输出函数 add
的文档字符串。
总的来说,Python的注释风格与C++在形式和用途上有所不同。尽管Python没有专门的多行注释符号,但其提供的其他
工具和规范仍使得代码注释在Python程序中起到了重要的作用。这体现了Python设计的一个基本原则——“There should be one-- and preferably only one --obvious way to do it.” (“应该有一种,最好只有一种显而易见的做法。”,摘自《Python之禅》)。
下面是一张总结Python和C++注释差异的表格:
注释类型 | Python | C++ |
单行注释 | 使用 # |
使用 // |
多行注释 | 使用 # 或 ''' 或 """ |
使用 /*...*/ |
函数/类文档 | 使用 ''' 或 """ |
无特定规定,通常使用 // 或 /*...*/ |
在日常交流中,我们通常会这样描述Python注释:“In Python, we use the hash symbol for single-line comments, and triple quotes for multi-line comments or docstrings."(在Python中,我们使用井号进行单行注释,使用三重引号进行多行注释或文档字符。)
请注意,在实际编程中,注释的使用并非仅仅为了解释代码的功能。良好的注释还可以增强代码的可读性,提供代码的使用说明,甚至有助于代码的调试过程。
这就是Python中注释的全部内容。与C++相比,Python的注释语法更加简洁明了。但无论在哪种语言中,编写清晰、详细的注释都是一个良好编程习惯的重要部分,也是实现代码可读性和可维护性的关键。
5.2 如何正确地使用注释
Python 中的注释是一个强大的工具,能够帮助我们提高代码的可读性和维护性。当我们在代码中添加注释时,需要注意以下几点:
- 清晰性:注释应该直接并且清晰。它需要简单明了地描述代码的功能,以便其他人(或者未来的你)能够理解代码的作用和运作方式。
# 正确示例 # 使用 FizzBuzz 算法打印从 1 到 100 的数字 # 如果数字可以被 3 整除,打印 'Fizz' # 如果数字可以被 5 整除,打印 'Buzz' # 如果数字既可以被 3 又可以被 5 整除,打印 'FizzBuzz'
- 精确性:注释需要正确反映代码的行为。如果代码被修改了,相关的注释也需要进行更新。
# 错误示例 x = 10 # 设置 x 为 5 # 正确示例 x = 10 # 设置 x 为 10
- 适度性:注释不能过多,也不能过少。过多的注释可能会干扰代码的阅读,而过少的注释可能会使代码难以理解。适量的注释可以在需要解释的地方提供帮助,而不会干扰代码的阅读。
# 错误示例 x = 10 # 设置 x 为 10 x = x + 5 # 将 5 加到 x 上 # 正确示例 # 初始化变量 x,并执行后续计算 x = 10 x = x + 5
- 文档字符串(Docstrings):对于函数、模块或类,应始终添加文档字符串。这些注释可以使用内置的
help()
函数来查看,为使用者提供了有关函数、模块或类的直接信息。
def add(a, b): ''' 这是一个用于执行加法运算的函数。 它接收两个参数 a 和 b,并返回他们的和。 ''' return a + b
在实际的编程实践中,注释的使用应灵活多变,以适应不同的情况和需求。总的来说,好的注释能够为代码提供清晰、准确和有用的信息,帮助我们更好地理解和使用代码。
6. 行与缩进
6.1 Python的缩进规则
在Python编程中,代码的格式和排列方式具有重要意义,这主要是通过行与缩进(Indentation)来体现的。Python使用缩进,即在每一行代码的开始处使用空格或制表符来组织代码,这与C++等其他语言使用花括号来定义代码块的方式有着明显的区别。
在Python中,连续的代码块如果具有相同的缩进,则它们属于同一代码块。这意味着,缩进在Python中具有语义意义,而不仅仅是为了代码的美观。例如,下面的函数定义就展示了Python的缩进规则:
def function_name(parameters): # 函数定义 statement_1 # 语句1 statement_2 # 语句2 if condition: # 条件语句 statement_3 # 语句3 statement_4 # 语句4
在这个示例中,statement_1
,statement_2
,if condition:
和 statement_4
都有相同的缩进级别,因此他们属于同一个代码块,即 function_name
的主体。然后,statement_3
是 if condition:
的一部分,因为它的缩进比前面的代码多,这意味着它是 if condition:
的一个子代码块。
同样的规则也适用于循环和类的定义等其他结构。不正确的缩进将导致 IndentationError
,这是Python编程中最常见的错误之一。
请注意,Python没有严格规定使用空格还是制表符进行缩进,但是,PEP 8推荐使用4个空格进行缩进。
与C++的比较
在C++中,花括号 {}
用于定义代码块的范围,而不是依赖于缩进。这意味着,在C++中,代码的缩进并没有实际的意义,它只是为了提高代码的可读性。例如,下面的C++代码是完全有效的:
if (condition) { statement_1; statement_2; }
即使 statement_1
和 statement_2
没有缩进,它们仍然是 if
条件的一部分,因为它们在花括号 {}
内部。然而,为了提高可读性,通常推荐在代码块内部
进行缩进,如下:
if (condition) { statement_1; statement_2; }
这样的代码更易于理解,因为缩进清楚地显示了代码的层次结构。尽管如此,缩进在C++中并不是强制的,与Python的严格缩进规则形成了鲜明的对比。
当我们在聊天或者描述Python的缩进规则时,我们通常会说,“In Python, indentation is used to define the block structure of the program"(在Python中,缩进用于定义程序的块结构)。而在C++中,我们则会说,“In C++, curly braces are used to define the block structure of the program”(在C++中,花括号被用来定义程序的块结构)。
要注意的是,这两种语言在描述和使用代码块的方式上存在显著的差异。尽管在C++中使用缩进可以提高代码的可读性,但它并没有实际的语义含义。相反,在Python中,适当的缩进不仅提高了代码的可读性,而且是程序正确执行的必要条件。
另一个需要注意的是,Python中的缩进错误会引发运行时错误,即IndentationError
,这在C++中并不会发生。因此,对于有C++背景的Python新手来说,了解和掌握Python的缩进规则是非常重要的。
下表总结了Python和C++在缩进和代码块定义方面的主要差异:
特性 | Python | C++ |
代码块定义 | 缩进(Indentation) | 花括号(Curly Braces) |
缩进错误 | 导致IndentationError |
无错误,但可能影响代码的可读性 |
缩进方式 | 空格或制表符,推荐4个空格 | 无硬性规定,通常为一个制表符或几个空格 |
以上内容基于Python 3和C++的基础语法。在实践中,每种语言的缩进规则可能因编程风格、项目要求等因素而略有不同。
6.2 行与缩进在Python编程中的重要性
行与缩进在Python编程中的重要性无法过分强调。正如我在前面的部分所介绍的,Python使用缩进来组织代码块,这种方法与C++和其他许多编程语言截然不同。
正确的缩进和行的组织可以确保Python代码的结构清晰,易于理解。这在阅读、理解、调试和维护代码时至关重要。通过将相关的语句组织在同一个缩进级别下,我们可以清楚地看到代码的结构和逻辑流程。例如:
def calculate_sum(n): # This function calculates the sum of all numbers up to n total = 0 # Initialize total to 0 for i in range(n+1): # Loop from 1 to n total += i # Add i to total return total # Return the total
此代码块定义了一个函数,该函数计算从1到n的所有数字的总和。缩进清楚地显示了哪些语句是函数的一部分,哪些语句是循环的一部分。这种清晰的结构对于理解代码的工作方式是非常重要的。
此外,行与缩进也有助于提高代码的美观度。一个良好缩进和组织的代码会让人觉得更易于阅读,从而更可能被其他开发者所理解和使用。
需要注意的是,不正确的缩进会导致IndentationError
,这是Python中最常见的错误之一。这再次强调了理解和应用正确缩进的重要性。
与C++的比较
对比C++,C++中的代码块通常由花括号({}
)定义,而不是依赖于缩进。尽管在C++中良好的缩进可以提高代码的可读性,但是缩进错误并不会导致编译错误。这是C++与Python的一个主要区别。例如,下面的C++代码即使没有正确的缩进也能正确运行:
int calculate_sum(int n) { int total = 0; // Initialize total to 0 for(int i=0; i<=n; i++) // Loop from 1 to n total += i; // Add i to total return total; // Return the total }
但是,为了提高代码的可读性,通常建议使用良好的缩进和代码组织。
英文描述缩进在Python中的重要性,我们通常会说,"In Python, correct indentation is not just for aesthetics, but it is syntactically significant. Poor indentation can lead to Indentation
Error, which is a common error in Python."(在Python中,正确的缩进不仅仅是为了美观,它在语法上是有意义的。糟糕的缩进可能会导致缩进错误,这是Python中常见的错误。)
7. 多行语句
在编程中,有时候你可能需要把一个语句分成多行来提高代码的可读性。在这一章节,我们将会讨论Python和C++在这一方面的不同,并会提供一些具体的示例。
7.1 多行语句的实现
在Python中,语句通常以新行作为结束。但是,我们可以通过使用反斜杠(\
)来实现多行语句。在遇到反斜杠时,Python解释器会知道该语句尚未结束,将继续到下一行。
例如:
total = item_one + \ item_two + \ item_three
在此例中,我们的语句被分成了三行。在Python中,这被称为line continuation(行续连)。
在C++中,与Python不同,一行语句通常以分号(;
)作为结束,不能直接像Python那样通过反斜杠进行行续连。如果你希望在C++中实现多行语句,你需要把整个表达式放在圆括号中,这样编译器就能理解该语句是连续的。
例如:
int total = (item_one + item_two + item_three);
在上述的C++代码中,整个加法表达式被放在圆括号中,编译器知道这是一个完整的表达式,即使它跨越了多行。
语句的分行对于代码的可读性和理解非常重要,特别是当你的表达式或语句很长或复杂时。在编程实践中,行续连在Python中被广泛接受,但在C++中,人们更倾向于避免过长的行,这样代码更容易阅读和维护。
在英语口语交流中,我们一般会这样描述行续连的概念:“To continue a statement over multiple lines in Python, you can use a backslash. In C++, statements are typically enclosed in parentheses if they span multiple lines."(在Python中,如果你想让一个语句跨越多行,你可以使用反斜杠。在C++中,如果语句跨越多行,通常将其放在圆括号内。)
这个表达方式的语法规则是先讲述做什么(continue a statement over multiple lines),然后说明怎么做(use a backslash 或 enclose…in parentheses)。当你描述编程概念时,首先说清楚你要解决什么问题(做什么),然后再说明具体的解决方案(怎么做
),这是非常有效的沟通方式。
在《Python核心编程》中,也提到了Python的行续连机制。此书指出,尽管Python提供了行续连机制,但推荐在可能的情况下使用括号(圆括号、方括号和大括号)来隐式地进行行续连,因为这样可以提供更好的可读性。
例如,以下Python代码:
total = (item_one + item_two + item_three)
在上述代码中,我们使用圆括号来包围整个表达式,Python解释器将会知道这个表达式是连续的,即使它跨越了多行。
下面的表格对比了Python和C++在处理多行语句方面的不同:
语言 | 分隔符 | 是否需要特殊字符 | 示例 |
Python | 新行 | 需要反斜杠或括号 | 如上文所示 |
C++ | 分号 | 需要圆括号 | 如上文所示 |
总的来说,Python和C++在处理多行语句时使用了不同的方法,选择使用哪种方法取决于你的实际需求和编程风格。
7. 多行语句
在编程中,有时候你可能需要把一个语句分成多行来提高代码的可读性。在这一章节,我们将会讨论Python和C++在这一方面的不同,并会提供一些具体的示例。
7.1 多行语句的实现
在Python中,语句通常以新行作为结束。但是,我们可以通过使用反斜杠(\
)来实现多行语句。在遇到反斜杠时,Python解释器会知道该语句尚未结束,将继续到下一行。
例如:
total = item_one + \ item_two + \ item_three
在此例中,我们的语句被分成了三行。在Python中,这被称为line continuation(行续连)。
在C++中,与Python不同,一行语句通常以分号(;
)作为结束,不能直接像Python那样通过反斜杠进行行续连。如果你希望在C++中实现多行语句,你需要把整个表达式放在圆括号中,这样编译器就能理解该语句是连续的。
例如:
int total = (item_one + item_two + item_three);
在上述的C++代码中,整个加法表达式被放在圆括号中,编译器知道这是一个完整的表达式,即使它跨越了多行。
语句的分行对于代码的可读性和理解非常重要,特别是当你的表达式或语句很长或复杂时。在编程实践中,行续连在Python中被广泛接受,但在C++中,人们更倾向于避免过长的行,这样代码更容易阅读和维护。
在英语口语交流中,我们一般会这样描述行续连的概念:“To continue a statement over multiple lines in Python, you can use a backslash. In C++, statements are typically enclosed in parentheses if they span multiple lines."(在Python中,如果你想让一个语句跨越多行,你可以使用反斜杠。在C++中,如果语句跨越多行,通常将其放在圆括号内。)
这个表达方式的语法规则是先讲述做什么(continue a statement over multiple lines),然后说明怎么做(use a backslash 或 enclose…in parentheses)。当你描述编程概念时,首先说清楚你要解决什么问题(做什么),然后再说明具体的解决方案(怎么做
),这是非常有效的沟通方式。
在《Python核心编程》中,也提到了Python的行续连机制。此书指出,尽管Python提供了行续连机制,但推荐在可能的情况下使用括号(圆括号、方括号和大括号)来隐式地进行行续连,因为这样可以提供更好的可读性。
例如,以下Python代码:
total = (item_one + item_two + item_three)
在上述代码中,我们使用圆括号来包围整个表达式,Python解释器将会知道这个表达式是连续的,即使它跨越了多行。
下面的表格对比了Python和C++在处理多行语句方面的不同:
语言 | 分隔符 | 是否需要特殊字符 | 示例 |
Python | 新行 | 需要反斜杠或括号 | 如上文所示 |
C++ | 分号 | 需要圆括号 | 如上文所示 |
总的来说,Python和C++在处理多行语句时使用了不同的方法,选择使用哪种方法取决于你的实际需求和编程风格。
7.2 多行语句的使用示例
接下来,让我们通过一些实例来详细了解Python和C++中多行语句的使用。
Python
在Python中,我们可以使用反斜杠(\
)或括号来实现多行语句。以下是一些示例:
- 使用反斜杠(
\
):
total = 1 + 2 + 3 + \ 4 + 5 + 6 + \ 7 + 8 + 9
- 使用圆括号:
total = (1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9)
- 使用方括号(列表):
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
- 使用大括号(集合或字典):
squares = {1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}
C++
在C++中,如果一条语句要跨越多行,我们通常使用圆括号。以下是一个示例:
int total = (1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9);
请注意,Python和C++的多行语句最好不超过80字符,这是一个广泛接受的编程最佳实践,旨在提高代码的可读性。
当我们在英语中描述这些代码时,我们通常会说:“In Python, you can break a statement into multiple lines with a backslash or parentheses. In C++, you can break a statement into multiple lines with parentheses."(在Python中,你可以使用反斜杠或括号将语句分成多行。在C++中,你可以使用括号将语句分成多行。)
这种表述方式遵循了我们之前讨论的语法规则:首先解释你要做什么(将语句分成多行),然后解释如何做(使用反斜杠、括号或其他方法)。
8. Python 中的数字类型 (Numeric Types)
Python的数字类型有几种基本形式:整型(Integers)、浮点型(Floating-Point Numbers)、复数(Complex Numbers)。
8.1 Python支持的数字类型
8.1.1 整型 (Integers)
在Python中,整型(int)用于表示整数,其大小只受限于可用内存的大小。在C++中,整数的类型(如int, long)的大小通常受到特定平台的限制。
例如,在Python中,你可以很容易地操作大整数:
big_int = 1234567890123456789012345678901234567890 print(big_int + 1) # 输出: 1234567890123456789012345678901234567891
在英语口语中,我们会说 “Assign a big integer to the variable big_int
and then print the result of adding 1 to big_int
.”(将一个大整数赋值给变量big_int
,然后打印big_int
加1的结果。)
8.1.2 浮点型 (Floating-Point Numbers)
Python的浮点型(float)用于表示小数。与C++不同,Python不区分单精度和双精度浮点数,所有的浮点数都具有相同的精度。
pi = 3.14159 print(pi) # 输出: 3.14159
在英语口语中,我们会说 “Assign the value of Pi to the variable pi
and then print the value of pi
.”(将π的值赋值给变量pi
,然后打印pi
的值。)
8.1.3 复数 (Complex Numbers)
Python中的复数(complex)包含两部分:实部和虚部。这是C++不直接支持的一个类型。
complex_num = 3 + 4j print(complex_num) # 输出: (3+4j)
在英语口语中,我们会说 “Assign a complex number to the variable complex_num
and then print the value of complex_num
.”(将一个复数赋值给变量complex_num
,然后打印complex_num
的值。)
以下是Python和C++支持的数字类型的对比:
类型 | Python | C++ |
整型 | √ | √ |
浮点型 | √ | √ |
复数 | √ | × |
以上示例和解释基于《Python学习手册》(Learning Python)和Python官方文档。理解Python的数字类型对于理解Python如何操作数据至关重要。
8.2 数字类型的使用示例
以下是Python中各种数字类型的一些基本操作:
8.2.1 整型的使用
整型在Python中广泛用于各种计算。例如:
a = 5 b = 2 print(a + b) # 加法:输出7 print(a - b) # 减法:输出3 print(a * b) # 乘法:输出10 print(a / b) # 除法:输出2.5 print(a // b) # 整数除法:输出2 print(a % b) # 模运算(余数):输出1 print(a ** b) # 幂运算:输出25
在英语口语中,我们会说 “Perform various arithmetic operations with the integers a
and b
, and then print the results.”(使用整数a
和b
执行各种算术运算,然后打印结果。)
8.2.2 浮点型的使用
浮点型在Python中也有多种使用方式,包括参与算术运算、函数调用等:
c = 5.0 d = 2.0 print(c + d) # 加法:输出7.0 print(c - d) # 减法:输出3.0 print(c * d) # 乘法:输出10.0 print(c / d) # 除法:输出2.5 print(c // d) # 整数除法:输出2.0 print(c % d) # 模运算(余数):输出1.0 print(c ** d) # 幂运算:输出25.0
在英语口语中,我们会说 “Perform various arithmetic operations with the floating-point numbers c
and d
, and then print the results.”(使用浮点数c
和d
执行各种算术运算,然后打印结果。)
8.2.3 复数的使用
Python的复数类型可以进行各种复数运算:
x = 3 + 4j y = 1 + 2j print(x + y) # 加法:输出(4+6j) print(x - y) # 减法:输出(2+2j) print(x * y) # 乘法:输出(-5+10j) print(x / y) # 除法:输出(2+0j)
在英语口语中,我们会说 “Perform various arithmetic operations with the complex numbers x
and y
, and then print the results.”(使用复数x
和y
执行各种算术运算,然后打印结果。)
以上的操作和说明都是基于Python的官方文档和《Python学习手册》(Learning Python)。理解这些数字类型的操作对于理解Python如何处理数据非常重要。
9. 字符串(Strings)
9.1 Python中的字符串定义和操作
在Python中,字符串(Strings)是存储字符系列的数据类型。可以使用单引号(‘)、双引号(")或三引号(’‘’ 或 “”")来创建字符串。三引号可以跨越多行,用于创建多行字符串。
相对于C/C++,Python的字符串更具灵活性。例如,Python无需在字符串的结尾添加空字符(‘\0’),而C/C++需要。
示例1:定义一个字符串
str1 = 'Hello, World!' print(str1) # 输出:Hello, World!
在这个示例中,我们创建了一个名为 str1
的字符串变量,并赋予其值 ‘Hello, World!’。
如果你是一个C/C++程序员,你可能会觉得这与你在C/C++中声明字符串的方式不同。在C/C++中,你需要声明一个字符数组或者使用指针来创建字符串,如:
char str1[] = "Hello, World!";
在Python中,一切都更简单、更直观。
字符串的操作
Python 提供了一系列的字符串操作,这包括连接(concatenation)、重复(repetition)、切片(slicing)以及一些常用的字符串方法。
示例2:字符串的连接
在Python中,我们可以使用 +
运算符来连接字符串,这一点与C/C++中的字符串连接方法有很大的区别。
str1 = 'Hello,' str2 = ' World!' str3 = str1 + str2 print(str3) # 输出:Hello, World!
如果你熟悉C/C++,你可能会知道在C/C++中,你需要使用 strcat()
函数或者 stringstream
来完成字符串的连接。
以下是Python字符串常用的一些方法的简单总结:
Python方法 | 描述 |
string.capitalize() | 将字符串的第一个字符转化为大写,其余部分转为小写。 |
string.upper() | 将字符串中的所有字符转化为大写。 |
string.lower() | 将字符串中的所有字符转化为小写。 |
string.count(sub) | 返回子串 sub 在字符串中出现的次数。 |
string.find(sub) | 返回子串 sub 在字符串中首次出现的位置。如果找不到,返回 -1。 |
string.replace(old, new) | 返回一个新的字符串,其中 old 的所有出现都被 new 替换。 |
在语言交流中,当你想讨论Python中的字符串时,你可以这样描述:
在Python中,我们使用引号来创建字符串。我们可以使用一些内置的字符串方法,如 upper()
、 lower()
、 find()
等,这些方法使得
处理字符串变得非常方便。
在Python中,我们使用引号来创建字符串。我们可以使用一些内置的字符串方法,如 upper()
、 lower()
、 find()
等,这些方法使得处理字符串变得非常方便。
在Python中,我们使用引号(quotes)来创建字符串(strings)。我们可以使用一些内置的字符串方法,如 upper()
(转大写)、 lower()
(转小写)、 find()
(找寻子串)等,这些方法使得处理字符串变得非常方便(convenient)。
在这句描述中,我们首先明确了我们正在讨论Python(在Python中)。然后,我们描述了创建字符串的方法(我们使用引号来创建字符串)。接着,我们列出了一些可以对字符串进行操作的方法,并解释了它们的功能(使用一些内置的字符串方法,如 upper()
、 lower()
、 find()
等)。最后,我们总结了这些方法的优点(使得处理字符串变得非常方便)。
9.2 字符串函数和方法
Python提供了丰富的内置函数和方法来处理字符串,这些函数和方法非常强大并易于使用,远比C/C++的字符串操作更为方便。
常用字符串函数
下面是一些在Python中处理字符串时经常使用的内置函数:
len(string)
:返回字符串的长度。str(object)
:将一个对象转化为字符串。
示例1:字符串函数的使用
str1 = 'Hello, World!' print(len(str1)) # 输出:13 num = 123 print(str(num)) # 输出:'123'
相比之下,在C/C++中,我们需要使用 strlen()
函数来获取字符串的长度,而将其他数据类型转换为字符串则需要使用诸如 sprintf()
或 stringstream
的函数。
常用字符串方法
在Python中,每个字符串都是 str
类的实例,所以我们可以使用很多可用的方法来处理字符串。以下是一些常用的方法:
string.split(separator)
:使用指定的分隔符将字符串拆分为子字符串的列表。string.strip(chars)
:返回移除了指定字符的字符串的副本。string.startswith(prefix)
:检查字符串是否以指定的前缀开始。string.endswith(suffix)
:检查字符串是否以指定的后缀结束。
示例2:字符串方法的使用
str1 = 'Hello, World!' print(str1.split(',')) # 输出:['Hello', ' World!'] str2 = ' Hello, World! ' print(str2.strip()) # 输出:'Hello, World!' print(str1.startswith('Hello')) # 输出:True print(str1.endswith('World!')) # 输出:True
相较于C/C++,Python的这些内置方法提供了更高效、更简洁的方式来处理字符串。例如,C/C++没有内置的 split()
方法,开发者需要手动实现;而 strip()
方法在C/C++中通常需要通过遍历字符串并创建新的字符串来实现。
当我们在日常对话中讨论Python字符串时,我们可以这样描述:
“In Python, we have a wide variety of built-in string methods such as split()
, strip()
, startswith()
, endswith()
, etc. These methods make string manipulation a lot easier in Python compared to languages like C/C++.”(在Python中,我们有各种各样的内置字符串方法,如 split()
、 strip()
、 startswith()
、 endswith()
等等。相比于C/C++等语言,这些方法使得Python的字符串操作更为简单。)
第十章 空行 (Blank Lines)
10.1 Python中空行的使用
在Python中,空行(Blank Lines)被视为白色空间(whitespace),通常不会影响代码的语义,但会增强代码的可读性。空行可被用于在逻辑上分隔函数和类的定义,或者在具有相关功能的代码块之间提供视觉上的间隔。
Python的规范PEP8建议,在函数和类的定义之间使用两个空行,而在类的方法之间使用一个空行。这有助于突出代码的结构和组织方式,使之更容易理解。
def function1(): pass def function2(): pass class MyClass: def method1(self): pass def method2(self): pass
在上面的例子中,我们使用两个空行将两个函数分隔开,并在类的方法之间使用一个空行。这使得代码结构清晰,易于理解。
不同的是,在C++中,空行的使用主要取决于开发者的个人习惯或者项目的编码规范。和Python一样,空行也被用于提高代码的可读性,但在语法上没有明确的规定。
讨论:空行在口语交流中的表述方式
在口语交流中,我们可以将空行描述为"blank lines",例如在讨论代码时,我们可以说:“Remember to include blank lines between your function definitions for better readability.” (记得在你的函数定义之间添加空行以提高代码的可读性。)
引用Python3名著的观点
在"Fluent Python"一书中,作者Luciano Ramalho强调了清晰的代码组织和结构的重要性,其中就包括合理地使用空行来提高代码的可读性。
10.2 空行在代码中的角色
在Python中,空行在代码中扮演着"视觉上的间隔"角色。这意味着它们通常不会影响代码的执行,但能有效地帮助开发者区分不同的代码块,从而使代码更易于阅读和理解。以下是空行在Python代码中的常见应用:
- 在函数或者类的定义之间添加空行以创建视觉上的间隔
- 在具有逻辑关联的代码块之间添加空行以增加代码的可读性
- 在注释和代码之间添加空行以突出注释
以下是具体的示例:
# 一个函数定义的示例 def function1(): # some code here pass # 另一个函数定义的示例 def function2(): # some code here pass
在这个示例中,我们在两个函数定义之间使用了空行。这样做可以使得每个函数的开始和结束更加明显,提高代码的可读性。
与此相比,C++对于空行的使用没有明确的规定,大多数情况下,开发者根据自己的习惯或者项目的编码规范来决定是否使用空行。
讨论:空行在口语交流中的表述方式
在英语口语交流中,我们可以用"spacing"或者"spacing out"来描述在代码中添加空行的行为。例如,我们可以说:“Make sure to space out your function definitions with blank lines for better readability.”(确保使用空行将你的函数定义分隔开,以提高代码的可读性。)
引用Python3名著的观点
在《Python编程:从入门到实践》一书中,作者Eric Matthes提倡使用空行来将代码块分隔开,以帮助开发者和阅读者更好地理解代码的结构和逻辑。
第十一章:等待用户输入
11.1 使用input()
函数
在Python中,我们使用input()
函数(函数,Function)来等待用户输入(Wait for User Input)。input()
函数可以接受一个字符串作为参数,这个字符串将作为提示信息(prompt message)展示给用户。
这是一个基本的使用示例:
user_name = input("Please enter your name: ") print("Hello, " + user_name + "!")
在这个例子中,"Please enter your name: "是提示信息。用户输入的文本会被input()
函数返回,然后被赋值给user_name
变量。
在C/C++中,我们通常使用scanf
函数或者cin
对象来接收用户的输入。相比之下,Python的input()
函数使用起来更为简单和直观。
让我们来比较一下这两种语言在等待用户输入方面的差异:
Python | C/C++ |
user_name = input("Please enter your name: ") |
char user_name[50]; printf("Please enter your name: "); scanf("%s", user_name); |
如你所见,Python的语法更简洁,更易读。
要注意,input()
函数返回的是一个字符串(String)。如果你需要用户输入一个数字并想把它作为整数(Integer)或浮点数(Float)处理,你需要使用int()
或float()
函数来进行转换。这是一个示例:
age = input("Please enter your age: ") age = int(age) # Convert the user input to an integer
如果你在美式英语中向别人描述这个过程,你可以说:“First, I call the input
function with a prompt message asking the user to enter their age. This function waits for the user to type something and press Enter. Then it returns the user input as a string. Since I need the age as a number, I convert the string to an integer using the int
function.”(首先,我调用input
函数并给出一个提示信息,要求用户输入他们的年龄。这个函数等待用户输入内容并按下回车键。然后它会将用户输入的内容作为字符串返回。由于我需要将年龄作为数字处理,所以我使用int
函数将字符串转换为整数。)
这里,“call”(调用)用于描述我们如何使用函数,“convert”(转换)用于描述我们如何改变数据的类型。
在进一步探讨底层实现之前,我们首先需要理解,Python是一种高级的、解释型的编程语言。这意味着Python中的函数,如input()
,其实是Python解释器(Python interpreter)为我们提供的预先编译好的函数。要查看input()
函数的具体实现,我们需要查看Python的源代码。在CPython实现中,
input()
函数的核心逻辑在Python/bltinmodule.c
文件中的builtin_input
函数中实现。
我要强调的是,深入研究底层源码并理解其中的实现细节并非初学者必须的。然而,了解Python是如何实现其内建函数的,将会帮助你更深入地理解Python是如何工作的,这对于你的学习和发展是有利的。
用户输入的验证
当使用input()
函数接收用户输入时,往往需要进行输入验证(Input validation)。例如,如果你请求用户输入他们的年龄,你可能需要确认他们输入的是否是一个有效的数字。这是一个简单的验证示例:
while True: age = input("Please enter your age: ") if age.isdigit(): age = int(age) break else: print("That's not a valid age. Please try again.")
在这个例子中,我们使用一个无限循环(Infinite loop)来反复请求用户输入,直到他们输入一个有效的年龄。我们使用字符串的isdigit()
方法来检查输入是否全部由数字组成。如果是,我们就将其转换为整数并退出循环。否则,我们就打印一个错误信息,并再次请求输入。
不同的情况可能需要不同的验证策略。理解如何进行有效的输入验证是一个重要的编程技巧。
接下来,我们会进一步探讨等待用户输入的更多内容。
11.2 用户输入的处理和验证
在开发应用时,一个常见的需求是获取并处理用户输入。但用户的输入往往是不可预测的,所以我们需要进行输入验证(Input Validation),确保用户输入满足我们的要求。
基本输入验证
基本的输入验证涉及到检查输入是否符合预期的格式或范围。例如,如果我们需要用户输入他们的年龄,我们可以这样做:
while True: age = input("Please enter your age: ") if age.isdigit() and 1 <= int(age) <= 120: age = int(age) break else: print("That's not a valid age. Please try again.")
在这个例子中,我们使用isdigit()
方法检查输入是否全部由数字组成,并使用范围检查来验证年龄是否在一个合理的范围内(假设1至120岁)。只有当输入既是数字又在合理范围内时,我们才接受输入并退出循环。
复杂输入验证
有时候,我们需要处理更复杂的输入格式,比如电子邮件地址、电话号码或密码。在这种情况下,我们通常会使用正则表达式(Regular Expressions)来进行复杂的格式匹配和验证。
import re email_pattern = re.compile(r"[^@]+@[^@]+\.[^@]+") while True: email = input("Please enter your email: ") if email_pattern.match(email): break else: print("That's not a valid email. Please try again.")
这个例子中,我们使用一个简单的正则表达式来匹配电子邮件地址。re.compile()
函数会将正则表达式的字符串形式编译为一个Pattern对象。我们可以使用这个Pattern对象的match()
方法来检查一个字符串是否匹配这个模式。
需要注意的是,虽然在C/C++中我们也可以通过类似的方式进行输入验证,但Python的代码通常更为简洁,更易于理解。
错误处理
在处理用户输入时,一个重要的概念是错误处理(Error Handling)。例如,当我们尝试将用户输入转换为整数或浮点数时,如果输入的不是数字,就会抛出一个错误。我们可以通过错误处理机制来捕获这些错误,并给出适当的响应。
while True: number = input("Please enter a number: ") try: number = float(number) break except ValueError: print("That's not a valid number. Please try again.")
在这个例子中,我们将尝试将输入转换为浮点数的代码放在try
语句块中。如果输入的不是一个有效的数字,float()
函数会抛出ValueError
。我们使用except
语句来捕获这个错误,并打印一个错误信息。
在美式英语中,你可以这样描述这个过程:“I ask the user to enter a number. I then try to convert the input to a float. If this raises a ValueError, I catch the error and ask the user to try again.”(我要求用户输入一个数字。然后,我尝试将输入转换为浮点数。如果这导致了一个ValueError,我就捕获这个错误,并让用户再试一次。)
理解如何进行有效的输入验证和错误处理是编程中的一个重要技巧,无论你是使用Python,还是C/C++。
12.同一行显示多条语句
在Python中,我们通常每行只写一条语句,这是编程中的一种最佳实践。然而,有时候,出于简洁和代码的整洁性考虑,我们可能需要在一行中写多条语句。
12.1 在一行中使用多个语句的规则
Python中,多条语句在一行的写法需要用到分号 ;
。它允许我们在单行内书写多条独立的语句。在Python解释器遇到分号时,它会认为这是一条新的语句的开始。
x = 1; y = 2; z = x + y
这在Python中是完全有效的,解释器会逐个执行这三条语句,但是它并不是一个推荐的做法。在编程规范PEP 8中,一般推荐一行只写一条语句,使得代码更易于阅读。
在C++中,语句的结束是通过分号来表示的。例如:
int x = 1; int y = 2; int z = x + y;
这在C++编程中是非常常见的。在C++中,每行一条语句并用分号结束是一种规则,而在Python中,这更多的是一种风格问题。
在口语交流中,如果你想描述这种在一行中使用多个语句的情况,你可以说: “You can include multiple statements on one line by separating them with a semicolon.” (你可以通过分号来在一行中包含多个语句)。这个句子的结构符合美式英语的语法规则,主语"You"(你)在动词"can include"(可以包含)之前,而宾语 “multiple statements”(多个语句)在动词之后,最后通过介词短语"on one line by separating them with a semicolon."(在一行中通过分号分隔它们)来说明主语做什么。
在学习Python的过程中,推荐读者参考《Python Cookbook》这本书。这本书中,作者David Beazley 和 Brian K. Jones对于Python的各种用法有非常深入的阐述和探讨。
Python的语句分隔符规则是在解释器的源码中实现的,在Python的 parsemodule.c
文件中,我们可以找到相关的源代码实现。这个文件处理Python的语法解析,包括语句的分隔等等。
在使用多条语句一行的情况下,这里有一个方法的对比表格:
语言 | 是否需要分号 | 示例 |
Python | 不需要,但可用于分隔多条语句 | x = 1; y = 2; z = x + y |
C/C++ | 需要,用于结束一条语句 | int x = 1; int y = 2; int z = x + y; |
以上对比表格,清晰地展示了Python和C/C++在语句分隔上的主要区别。
12.2 适当和不适当的用例
虽然Python允许我们在一行中使用多个语句,但这并不意味着我们应该经常使用这种技巧。事实上,过度使用这种技术可能会导致代码难以阅读和理解,违反了Python的设计原则:“可读性至关重要”。
适当的用例
当你想在代码中插入一个短而简单的语句,而这个语句与当前行的主要语句相关,这种情况下,使用分号来添加多个语句可能是合适的。比如:
if x > 0: y = 1; print('y is 1')
在这个例子中,如果x
大于0
,y
就被赋值为1
,然后打印出一条消息。这两个操作都是相对简单和短小的,因此可以在一行中一起出现。
不适当的用例
如果你的语句是复杂的,或者需要多行来适当地组织,那么将多条语句放在同一行就不是一个好主意。例如:
for i in range(10): x = i * 2; print(f'The double of {i} is {x}'); y = i ** 2; print(f'The square of {i} is {y}')
这行代码实在是太长,尽管Python语法允许你这么写,但它并不易于阅读。更好的做法是将每个操作分解成单独的行:
for i in range(10): x = i * 2 print(f'The double of {i} is {x}') y = i ** 2 print(f'The square of {i} is {y}')
与C/C++的比较:在C/C++中,由于每个语句都必须以分号结束,所以放置多个语句在同一行的情况相对较少。在Python中,由于不需要分号结束语句,所以更注重代码的可读性和清晰性。
在口语交流中,你可以说: “While Python allows multiple statements on one line separated by semicolons, it is often clearer to write one statement per line.” (虽然Python允许一行中用分号分隔的多个语句,但每行写一条语句通常会更清晰。) 这个句子在语法上是完全符合美式英语的规则的。
根据Brian Kernighan和P.J. Plauger在《The Elements of Programming Style》一书中的观点,我们应该避免过度使用一行中的多个语句,以保持代码的可读性。如果一行代码太长或太复杂,应该分解为多行。
与此同时,我们可以在Python的源码中看到,Python解释器在处理一行中的多个语句时,会将每个语句解析为单独的语法单位,这也是Python的解析器可以正确处理一行中的多个语句的原因。
下表是一种方法的对比,总结了在何时何地适合使用多语句一行:
场景 | 是否适合使用多语句一行 |
语句短小、相关性高 | 是 |
语句复杂、需要多行展示 | 否 |
第十三章:多个语句构成代码组 (Code Blocks)
13.1 代码组的定义 (Definition of Code Blocks)
在Python中,多个语句可以形成一个代码组,这种方式与C++在语义上有相似之处,但在具体的语法格式上存在显著差异。在Python中,代码组(Code Blocks)通常用于定义函数体(Function Body)、循环体(Loop Body)、条件判断(Conditional Statements)等。
Python使用缩进(Indentation)来明确代码组的边界。这是Python的一大特色,也使得Python的代码具有很高的可读性。然而,C++则通过大括号{}
来划定代码块的范围。
以下是一个Python中定义函数(Function)的例子:
def greeting(name): # 这是一个代码组 print("Hello, " + name + "!")
在这个例子中,print
语句就是函数greeting
的代码组。它们都有相同的缩进级别,表示它们属于同一代码组。
对比C++的例子:
void greeting(string name) { // 这是一个代码组 cout << "Hello, " << name << "!"; }
在英语口语交流中,你可以如此描述Python的代码组(Code Blocks):“In Python, we define code blocks with the same level of indentation. This is different from languages like C++, where code blocks are defined by braces."
(在Python中,我们通过相同的缩进级别来定义代码组。这与C++等语言不同,C++中的代码组是通过大括号来定义的。)
本章节内容引用了《Fluent Python》的一些观点,该书非常深入地讨论了Python的内部机制和实现原理。以下是关于Python和C++代码组的表格对比:
Python | C++ | |
代码组的定义方式 | 使用相同的缩进级别 | 使用大括号{} |
是否需要分号结尾 | 不需要 | 需要 |
是否对缩进敏感 | 是 | 否 |
在了解Python代码组的同时,也要注意到Python与C++的这些差异,这将有助于你更好地理解和使用Python。
13.2 如何使用代码组组织代码 (Organizing Code Using Code Blocks)
在Python中,你可以使用代码组(Code Blocks)来组织你的代码,特别是在构造函数(Functions)、条件判断(Conditional Statements)和循环(Loops)时。以下是一些使用代码组的示例。
函数(Function)
在定义函数时,我们使用代码组来定义函数的主体。例如:
def say_hello(name): # 定义函数 # 下面的代码组成了一个代码组 print(f'Hello, {name}!')
这个函数say_hello
包含了一个print
语句的代码组。
条件判断 (Conditional Statements)
我们也可以在条件判断中使用代码组。例如:
temperature = 30 if temperature > 20: # 如果温度大于20 # 这里是一个代码组 print('It is warm.') else: # 否则 # 这里是另一个代码组 print('It is cold.')
循环 (Loops)
在循环结构中,我们同样使用代码组来定义每次循环执行的操作。例如:
for i in range(5): # 对于范围内的每个数 # 下面的代码构成一个代码组 print(f'This is loop {i}.')
在以上所有例子中,代码组都由同一缩进级别的语句组成。
在英语口语交流中,你可以如此描述代码组的使用:“In Python, we use code blocks to organize the body of functions, loops, and conditional statements. Code blocks are denoted by the same level of indentation."
(在Python中,我们使用代码组来组织函数、循环和条件语句的主体。代码组通过相同的缩进级别来标识。)
与C++相比,Python的代码更加简洁清晰,无需使用大括号和分号。这种特性使得Python代码更加易于阅读和理解。
14. print
输出
14.1 Python 的 print
函数
在Python中,print()
函数(打印函数)是最基本的输出方法。它将参数转换为字符串形式并将其写入到标准输出设备(通常是屏幕)。在语言交流中,我们通常会说"print something out"或者"print out something"(打印某物)来表达这个概念。
一个简单的print()
使用示例如下:
print("Hello, World!")
运行这段代码,你将在屏幕上看到输出 “Hello, World!”。
在C++中,相应的输出函数是 std::cout
,但Python的 print()
功能更强大,使用起来也更直观。例如,在C++中,我们可能需要将多个元素连接起来进行输出:
std::cout << "Hello, " << "World!" << std::endl;
而在Python中,我们可以简单地在 print()
函数中使用逗号分隔各个元素:
print("Hello,", "World!")
这将同样在屏幕上输出 “Hello, World!”。
14.1.1 print
函数的参数
print()
函数具有多个参数,包括以下几种:
参数 | 描述 |
object(s) | 一个或多个对象,将按照他们在括号中的顺序进行打印 |
sep=‘separator’ | 用于分隔多个对象,默认为 ’ '(空格) |
end=‘end’ | 输出结束后的字符,默认为 ‘\n’(换行) |
file | 定义流打印的目标文件,可以是标准的系统输出(sys.stdout),或者一个实际的文件 |
flush | 输出是否被缓存通常决定于 file,但如果 flush 关键字参数为 True,流会被强制刷新 |
以下示例展示了 sep
和 end
参数的使用:
print("Hello", "World", sep='-', end='!')
这将在屏幕上输出 “Hello-World!”。
在Python中,print
是一个内建函数(built-in function),这意味着它总是可用的,无需任何导入。在C++中,你必须包含 才能使用
std::cout
,但在Python中,print()
是始终可用的。
14.2 print
函数的各种使用方式
Python中的 print()
函数具有多种用法,使得输出的自定义更为灵活。以下是一些基本的使用方法:
14.2.1 打印多个参数
print()
函数可以接受任意数量的参数,并默认以空格为分隔符打印。例如:
print("Hello", "World", "from", "Python")
这将输出: “Hello World from Python”
14.2.2 使用分隔符
使用 sep
参数,我们可以自定义分隔符:
print("Hello", "World", sep=' -> ')
这将输出:“Hello -> World”
14.2.3 控制行尾字符
print()
默认在每次打印后都会添加一个换行符。通过修改 end
参数,我们可以更改行尾字符:
print("Hello", end=' ') print("World")
这将输出:“Hello World”,而不是默认的两行。
14.2.4 输出到文件
除了默认的标准输出设备(即屏幕)以外,我们还可以通过 file
参数将输出重定向到文件:
with open('output.txt', 'w') as f: print("Hello World", file=f)
这将把 “Hello World” 写入名为 “output.txt” 的文件中,而不是打印到屏幕。
这是Python的print
函数优于C++中的 std::cout
的一点,因为在C++中,我们需要使用文件流(如 std::ofstream
)才能将输出写入文件。
14.2.5 打印格式化字符串
我们还可以使用 print()
函数打印格式化的字符串。Python 3引入了一个新的方式来格式化字符串,即使用 “f-strings”:
name = "Python" print(f"Hello, {name}!")
这将输出:“Hello, Python!”
这个技术在C++中没有直接的等价物,虽然C++20引入了 std::format
来实现类似的功能。
以上这些例子展示了 print()
函数的灵活性和易用性。熟练掌握这些用法将在你的Python编程旅程中大有裨益。
15. 模块导入:import
与 from...import
15.1 模块的定义和创建
在Python中,模块(Module)是一个包含所有你定义的函数和变量的文件,其后缀名是.py
。模块可以被别的程序引入,以使用该模块中的函数等功能。这也是使用 Python 标准库的方法。
创建一个模块非常简单,你只需要创建一个 .py
后缀的文件,然后在其中定义你的函数或变量。例如,我们创建一个名为 mymodule.py
的模块,内容如下:
# mymodule.py def say_hello(name): print(f"Hello, {name}!")
然后我们可以在另一个 Python 文件中导入和使用 mymodule
模块:
# main.py import mymodule mymodule.say_hello("World") # 输出:Hello, World!
在C++中,模块系统的概念是通过包含头文件来实现的。例如,我们可能会有一个 mymodule.h
头文件和一个 mymodule.cpp
文件,然后在其他的 .cpp
文件中通过 #include "mymodule.h"
来使用模块的功能。Python的模块系统比C++的更加灵活和易用,因为Python会自动处理导入和模块代码的执行。
这就是创建和使用模块的基本方法。接下来,我们将进一步探讨 import
和 from...import
的具体用法。在交流中,我们常常会说 “import a module”(导入一个模块)或 “from a module, import a function”(从一个模块中导入一个函数)。
15.2 如何使用 import
和 from...import
Python 提供了多种导入模块的方法,主要有 import
和 from...import
。下面我们来详细讲解一下这两种方法的用法和区别。
15.2.1 使用 import
导入模块
import
语句最基本的形式是直接导入一个模块。当解释器遇到 import
语句,如果模块在当前的搜索路径就会被导入。
例如,让我们导入Python的内建模块 math
:
import math print(math.pi) # 输出:3.141592653589793
在这个例子中,我们导入了 math
模块,然后使用 .
访问符号来调用 math
模块中的 pi
变量。
15.2.2 使用 from...import
导入模块中的特定部分
如果我们只需要用到模块中的某个函数或者变量,就可以使用 from...import
语句来导入特定的部分:
from math import pi print(pi) # 输出:3.141592653589793
在这个例子中,我们直接从 math
模块中导入了 pi
变量,然后可以直接使用这个变量,而不需要 math.
这个前缀。
相比于 C++ 的 #include
语句,Python 的 import
与 from...import
提供了更多的灵活性。在 C++ 中,#include
语句会包含整个头文件,但在 Python 中,我们可以选择导入整个模块,也可以仅导入模块中的某个函数或变量。
我们也常常在口语交流中说 “I am importing the math module”(我正在导入 math 模块)或 “I am importing the pi variable from the math module”(我从 math 模块中导入了 pi 变量)。注意在这些情况下,我们通常会使用 “from…import…” 的结构来表示我们从一个大的部分(模块)中提取出一个小的部分(函数、变量等)。
下表总结了 Python 的 import
和 from...import
与 C++ 的 #include
的一些主要差异:
特性 | Python import |
Python from...import |
C++ #include |
导入整个模块 | ✔️ | ✔️ | |
只导入模块的一部分 | ✔️ | ||
需要使用模块名访问 | ✔️ | ✔️ | |
可以直接访问导入的部分 | ✔️ | ✔️ |
接下来,我们将深入讨论 import
和 from...import
的区别。
15.3 import
与 from...import
的区别
尽管 import
和 from...import
都是用于在 Python 中导入模块的语句,但它们之间还是存在一些关键差异。这些差异主要体现在导入方式,以及如何访问导入的模块或函数。
15.3.1 import
的特点
当我们使用 import
语句时,我们是在导入整个模块。这意味着我们可以访问模块中定义的所有函数和变量。然而,要访问这些函数或变量,我们需要在它们前面加上模块的名字和一个点。例如:
import math print(math.pi) # 输出:3.141592653589793
在这个例子中,我们需要使用 math.pi
而不是只用 pi
来访问 pi
变量。这是因为 pi
是 math
模块的一部分。
这种做法的优点是清楚地显示了函数或变量来自哪个模块,有助于代码的可读性和避免命名冲突。缺点是可能导致代码略显冗长。
15.3.2 from...import
的特点
相比之下,from...import
语句允许我们只导入模块中的特定部分,并且可以直接使用这些函数或变量,而无需在前面添加模块名。例如:
from math import pi print(pi) # 输出:3.141592653589793
在这个例子中,我们直接导入了 pi
变量,然后可以直接使用 pi
,而不需要前缀 math.
。
这种方法的优点是可以使代码更简洁。然而,它可能会导致命名冲突,特别是当我们从多个模块中导入函数或变量时。此外,如果不熟悉模块中的函数或变量,可能会使得代码的可读性降低。
在C++中,虽然没有与 from...import
完全等价的构造,但是使用命名空间可以得到类似的效果。例如,我们可以使用 using namespace std;
来导入 std
命名空间中的所有函数和变量,然后就可以直接使用它们,而不需要 std::
前缀。然而,这种做法并不推荐,因为它可能导致命名冲突。
总的来说,import
和 from...import
在Python中都是有用的工具,
选择使用哪一个取决于你的具体需求。
16. 命令行参数(Command Line Arguments)
16.1 Python 中的 sys
模块和 argv
在Python中,我们经常需要从命令行获取参数。Python的内建 sys
模块为我们提供了这样的工具。特别是 sys.argv
,这是一个在Python中实现命令行参数的列表。该列表的第一项(即 sys.argv[0]
)是脚本名,其余的项是传递给脚本的参数。
例如,如果我们有一个名为 test.py
的Python脚本,并且在命令行中执行 python test.py arg1 arg2
,则 sys.argv[0]
将是 "test.py"
,sys.argv[1]
将是 "arg1"
,sys.argv[2]
将是 "arg2"
。
让我们看一个例子:
import sys print('脚本名 (Script Name): ', sys.argv[0]) print('第一个参数 (First argument): ', sys.argv[1]) print('第二个参数 (Second argument): ', sys.argv[2]) print('命令行参数列表 (The command line arguments list): ', str(sys.argv))
你可以在命令行中运行这个脚本,并传递一些参数。例如,python test.py arg1 arg2
,你将会看到这样的输出:
脚本名 (Script Name): test.py 第一个参数 (First argument): arg1 第二个参数 (Second argument): arg2 命令行参数列表 (The command line arguments list): ['test.py', 'arg1', 'arg2']
在C++中,命令行参数通过主函数的参数进行访问。主函数通常定义为 int main(int argc, char *argv[])
,其中 argc
是参数计数器,表示传递给程序的参数数目,argv
是参数向量,是一个包含所有参数的数组。
在Python中,我们不需要显式定义一个入口点(如C++中的 main
函数)。当我们运行Python脚本时,它将从第一行开始运行,除非我们定义了一个入口点。这就是Python和C++在处理命令行参数上的主要区别。
口语交流中,你可能会说:“In Python, sys.argv
is used to access command-line arguments passed to the script. It’s a list where the first item is the script name itself and the rest are the arguments in order.” (在Python中,我们使用 sys.argv
来访问传递给脚本的命令行参数。它是一个列表,其中第一项是脚本名称本身,其余的是按顺序的参数。)
总的来说,命令行参数是在执行脚本时传递给程序的参数。在Python中,我们使用 sys.argv
来访问这些参数,这是
一个列表,其中包含脚本名称和所有的参数。与C++等其他语言不同,Python不需要定义一个特定的入口点来获取这些参数。
Python | C++ | |
命令行参数的获取 | 使用 sys.argv 列表 |
通过 main 函数的参数 |
入口点 | 不必要 | 必须 (main 函数) |
在《Fluent Python》一书中,Luciano Ramalho也讨论了 sys
模块和 argv
的使用,并提供了一些有趣的示例来演示如何在实际编程中使用这些功能。
接下来,我们将探讨如何在更复杂的场景中使用 sys.argv
,并处理更复杂的命令行参数。
16.2 如何使用命令行参数
在Python中,使用命令行参数可以增强脚本的灵活性和可用性。接下来,我们将演示如何在实际中使用命令行参数。
让我们看一个简单的例子,其中我们将脚本用作一个简单的加法器,将所有传递的命令行参数相加:
import sys # 确保有足够的参数传入 if len(sys.argv) < 3: print("至少需要两个参数进行加法运算 (At least two arguments are required for addition operation).") sys.exit() # 将参数转化为整数,然后求和 sum = 0 for num in sys.argv[1:]: sum += int(num) print('合计 (Total): ', sum)
如果我们运行 python test.py 5 10 15
,则输出将是 合计 (Total): 30
。
在C++中,我们也可以进行类似的操作,但需要处理 argv
数组和 argc
计数器。
口语交流中,你可能会说:“Command-line arguments are useful when we want to provide inputs that modify the behavior of our script. In Python, we use the sys.argv
list to access these arguments and perform operations based on them.” (命令行参数在我们需要提供改变脚本行为的输入时很有用。在Python中,我们使用 sys.argv
列表来访问这些参数,并根据这些参数执行操作。)
注意,sys.argv
包含的都是字符串,如果需要进行数学运算,必须先将其转换为适当的数值类型。同时,由于 sys.argv
至少会有一个元素(脚本名),在使用之前检查其长度也是一种好的做法。
此外,对于更复杂的命令行参数解析需求,Python还提供了 argparse
模块。argparse
允许我们定义期望的命令行参数类型,为命令行参数提供帮助信息,并在用户提供无效输入时产生有用的错误消息。