python3.11教程1:python基础语法、程序控制、函数

一、Python简介

1.1 为什么学习python

  在计算机编程中,编程是指编写一系列指令,以便计算机执行特定的任务。编程语言就像是我们与计算机进行交流的工具,它们允许我们用人类可以理解的方式来描述任务和操作。

Python 是一种广泛使用的高级编程语言,它的语法简单清晰,非常适合初学者入门。Python 可以用来开发各种类型的应用,包括 Web 应用、数据分析、人工智能等。

为什么要学习 Python 呢?Python 具有以下几个优点:

  • 易学易用: Python 的语法简洁明了,不需要大量的符号和标记,使得它成为编程入门的绝佳选择。
  • 广泛应用: Python 在多个领域都有应用,从 Web 开发到科学计算,都可以使用 Python 来完成任务。
  • 强大的社区支持: Python 拥有庞大的社区和丰富的文档,你可以轻松找到解决问题的方法和资源。
  • 大量的库和框架: Python 生态系统中有许多开源库和框架,可以帮助你更快速地完成项目。

1.2 python安装与配置

  打开python官网,选择合适的python版本进行安装。在windows系统中,打开cmd,输入where python,就可以看到当前系统的python安装目录。

在这里插入图片描述

安装之后,按照以下步骤配置python的环境变量:

  1. 在开始菜单中搜索并打开“环境变量”设置。

  2. 在系统变量区域,找到名为 Path 的变量,并双击它。

  3. 在弹出的窗口中,点击“编辑”,然后输入 Python 的安装路径,例如我的路径就是C:\Users\LS\AppData\Local\Programs\Python\Python311\python.exe
    在这里插入图片描述

  配置好环境变量后,cmd下输入python --version即可查看当前系统的python版本(如果你有多个 Python 版本安装在系统中,这个命令会显示默认的 Python 版本。)。

1.3 python解释器

  Python 解释器是一种程序,它能够读取并执行 Python 代码。每当你编写 Python 代码并运行时,实际上是通过解释器将你的代码转换成计算机可以理解的指令。Python 有多个解释器可供选择,以下是一些常见的 Python 解释器:

Python 解释器有两种主要使用方式:

  • CPython :Python 编程语言的官方实现,使用C语言开发,是最常用的 Python 解释器之一,在多数情况下,“Python” 指的就是 CPython
    CPython 使用全局解释锁(Global Interpreter Lock,GIL)来确保在同一时间只能有一个线程执行 Python 代码。这可以导致在多线程程序中存在一些性能限制(在多线程章节会详述)。

  • Jython:Jython是运行在Java虚拟机(JVM)上的Python解释器。它允许Python代码与Java代码相互调用,可以在Java平台上使用Python进行开发。

  • IronPython:运行在 .NET 平台上

  • PyPy:一个高性能的 JIT (即时编译)编译器实现,在某些情况下比CPython更快地执行代码。

  • MicroPython:用于 IoT 设备和嵌入式系统,专为资源受限的环境设计,可以在微控制器和其他小型设备上运行

python解释器主要有两种使用方式:

  1. 交互式模式: 这是一种逐行执行代码的方式。你可以打开一个交互式解释器窗口,输入一行代码,然后解释器会立即执行并返回结果。这对于测试代码片段和快速实验非常有用。

在cmd中,输入python即可进入python交互模式,按下Ctrl+z后回车,即可退出,或者是输入quit()

  1. 脚本模式: 这是一种将一组代码保存在文件中,并一次性运行的方式。你可以创建一个以 .py 结尾的 Python 脚本文件,然后在终端或命令提示符中运行它。解释器会按顺序执行文件中的代码。

例如,假设你有一个名为 hello.py 的脚本文件,其中包含以下代码:

print("Hello, world!")

你可以在终端中输入以下命令运行脚本:

python hello.py

1.4 命令行参数

1.4.1 sys.argv变量

  当你在命令行中运行一个 Python 脚本时,Python 解释器会把你输入的命令行信息转换成一个列表,这个列表被称为“命令行参数列表”。这个列表中包含了一些有用的信息,比如脚本的名字和其他参数。

假设你有一个名为 script.py 的 Python 脚本,当你在命令行中输入以下内容时:

python script.py arg1 arg2

Python 解释器会将这些内容转换成一个列表,并存到 sys 模块的 argv 变量里。

['script.py', 'arg1', 'arg2']

  在这个列表中,第一个元素 'script.py' 是脚本的名字,后面的元素 'arg1''arg2' 是其他参数。如果你要访问这个命令行参数列表,你可以使用 sys.argv 来进行访问:

# 参数列表中至少包含一个元素,即脚本的名称
import sys
# 获取脚本名
script_name = sys.argv[0]

# 获取其他参数
other_args = sys.argv[1:]

  如果你使用特殊的选项,例如 -c-m,Python 会在列表中提供额外的信息。例如,当你运行以下命令时:

python -c "print('Hello, world!')"

列表会变成:

['-c', "print('Hello, world!')"]

  这告诉你使用了 -c 选项,并且要执行的代码是 "print('Hello, world!')"。如果使用选项 -m modulesys.argv[0] 就是包含路径的模块的完整名称。

1.4.2 -c和-m选项

  -c-m 是 Python 解释器的命令行选项,前者用于执行一行代码,后者 用于运行指定模块。

  • -c 选项:

  -c commend 选项允许你在命令行中执行一行 Python 代码,这在需要快速执行一些简单的操作时很有用,而不需要创建一个完整的脚本文件。你可以将要执行的代码放在引号中(Python 语句经常包含空格或其他会被 shell 特殊对待的字符,通常建议用引号将整个 command 括起来)。下面是几个简单示例:

  1. 简单计算
python -c "print(10 + 20)"
  1. 多行代码块:你也可以在一行中编写多行代码,只需要使用 ; 分隔:
python -c "x = 5; y = 10; print(x + y)"
  1. 使用模块:你可以导入并使用 Python 的内置模块,例如时间模块。
python -c "import time; print(time.strftime('%Y-%m-%d'))"
  1. 创建列表:
python -c "my_list = [1, 2, 3]; doubled = [x * 2 for x in my_list]; print(doubled)"
  1. 条件语句
python -c "x = 15; y = 10; print('x is greater' if x > y else 'y is greater')"
  • -m选项

  -m module表示在 sys.path 中搜索指定模块,并以 __main__ 模块执行其内容。module是模块名,不包括文件扩展名(.py)。许多标准库模块都包含在执行时,都可以以脚本方式调用的代码,例如 timeit 模块:

python -m timeit -s 'setup here' 'benchmarked code here'
python -m timeit -h # for details

你也可以额外指定模块的路径:

# 运行my_package 包中的模块my_module
python -m my_package.my_module

有关此部分更多内容,请参考《命令行与环境》

1.5 解释器的运行环境

1.5.1 编码格式

  编码格式(Encoding)是一种规则或标准,它定义了如何映射字符集中的字符到数字编码,以便于将文本和字符转换为二进制数据,使计算机可以处理、存储和传输它们。因为计算机内部只能处理二进制数据,因此任何文本数据在传输到计算机或存储在磁盘上之前,都必须经过编码转换。一些常见的编码格式包括:

  1. ASCII(美国信息交换标准代码): 最早的字符编码标准。ASCII编码定义了128个字符(7位二进制数,比特流),用于表示英文字母(大写和小写)、数字、标点符号以及一些控制字符(如换行、回车、制表符等)。以下是一些常见的ASCII字符及其描述:
ASCII 值 字符 描述
32 空格
33 ! 感叹号
48 0 数字0
65 A 大写字母A
97 a 小写字母a
126 ~ 波浪号
127 删除
  1. Unicode: 一个更为广泛的字符编码标准,用于表示世界上几乎所有语言的字符。Unicode支持数千个字符,使用16位或32位的二进制数来表示字符。

  2. UTF-8(Unicode Transformation Format - 8-bit): 是Unicode的一种编码方式,使用8位二进制数表示字符。从 Python 3 开始,python源码文件默认编码就是UTF-8,因为它具有很好的兼容性和节省空间的特点。

  3. UTF-16 和 UTF-32: 也是Unicode的编码方式,分别使用16位和32位的二进制数来表示字符。它们用于需要大范围字符支持的应用程序。

1.5.2 编码声明

  Python 源码文件的字符编码通常在文件开头通过特殊的注释来指定,这个注释称为“编码声明”(Encoding Declaration)。编码声明使用类似于以下形式的注释:

# -*- coding: encoding -*-

  通常情况下,Python 源码文件的编码声明会写在文件的第一行。但是,如果源码文件以 UNIX “shebang” 行(也称为解释器指令,用于指定脚本在执行时要使用的解释器)开头,那么编码声明应该写在文件的第二行,例如:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# 这是一个 Python 源码文件的例子,它使用 UTF-8 编码

def print_unicode():
    print("你好,世界!")  # 这里包含了中文字符

print_unicode()

  在这个示例中,第一行 #!/usr/bin/env python 是 UNIX “shebang” 行,它告诉操作系统要使用 env 工具来查找系统中的 Python 解释器。因此,编码声明 # -*- coding: utf-8 -*- 被放在文件的第二行。

二、Python基础语法

参考《词法分析》《Python 语言参考手册》

2.1 行结构

Python 程序可以拆分为多个 逻辑行,以下是一些基本概念:

  • 物理行(Physical Line): 物理行是指在实际代码文件中的一行文本。每当你在编辑器中按下回车键创建一个新行,就会增加一个物理行。
  • 逻辑行(Logical Line): 逻辑行是指在 Python 解释器中被视为单个语句的一行或多行代码。在 Python 中,一个逻辑行可能跨越多个物理行。
    • 显示拼接: Python 可以使用反斜杠(\)来显式地将多个物理行拼接行为一个逻辑行
if 1900 < year < 2100 and 1 <= month <= 12 \
   and 1 <= day <= 31 and 0 <= hour < 24 \
   and 0 <= minute < 60 and 0 <= second < 60:   # Looks like a valid date
        return 1
  • 隐式拼接:你也可以使用圆括号、方括号、花括号内的表达式来拼接多个物理行:
month_names = ['Januari', 'Februari', 'Maart',      # These are the
               'April',   'Mei',      'Juni',       # Dutch names
               'Juli',    'Augustus', 'September',  # for the months
               'Oktober', 'November', 'December']   # of the year
  • 注释:注释是用来解释代码的说明性文本,它不会被解释器执行
    • 单行注释: 在 Python 中,使用 # 符号来表示单行注释,注释会从 # 开始一直延伸到该行的结尾。
    • 多行注释(文档字符串): 在 Python 中,使用三个引号 '''""" 来表示多行注释,也称为文档字符串(docstring)。文档字符串可以跨足够多的物理行,通常被放置在函数、类或模块的开头,以提供相关文档和说明。
  • 编码声明:见本文1.5.1章节
  • 缩进:用于定义语句的层次结构,同一个代码块内的所有语句应该具有相同的缩进级别。
    可以使用空格或制表符进行缩进,但不要混合使用二者。通常情况下,每个缩进级别使用 4 个空格(或者一个Tab键)。

2.2 变量(标识符)

  在 Python 中,你可以使用变量来存储数据,并在后续的代码中使用。变量名是标识符,通常由字母、数字和下划线组成,但不能以数字开头

以下是一些变量的示例:

age = 25
name = "Alice"
height = 1.75
is_student = True

  在这个例子中,age 存储整数值,name 存储字符串,height 存储浮点数,is_student 存储布尔值。

  Python 有35个的关键字(也称为保留字),它们具有预定义的含义和功能,不能用作标识符(例如变量名、函数名等)。

False class finally is return None
continue for lambda try True def
from nonlocal while and del global
not with as elif if or
yield assert else import pass break
except in raise await async

这些保留字在编写 Python 代码时有特定的含义,因此不能用作变量名或函数名等标识符。

2.3 字节串

  在 Python 中,字符串和字节串是两种表示文本数据的方式,它们在处理和表示文本上有一些重要的区别。

  • 字符串(String ): 字符串表示文本数据,它是用单引号 '' 或双引号 "" 包裹的一串字符序列。字符串字面值可以包含任何字符,包括字母、数字、特殊字符等。例如:
string1 = 'Hello, World!'
string2 = "Python is fun."
  • 字节串(Bytes ): 字节串表示字节数据,它是用单引号 b'' 或双引号 b"" 包裹的一串字节序列。字节串用于处理二进制数据,如图像、音频等文件。每个字节串中的字符都是 0 到 255 之间的整数。例如:
bytes1 = b'Hello, World!'
bytes2 = b'\x48\x65\x6c\x6c\x6f'  # 使用十六进制表示字节

区别与用途:

  1. 编码方式: 字符串是用于表示文本数据的,它可以使用不同的编码方式(如 UTF-8、ASCII)来存储不同语言的字符。字节串是原始的字节序列,只能包含 ASCII 字符;字节串数值大于等于 128 时,必须用转义表示。
  2. 操作和方法: 字符串具有字符串操作和方法,如拼接、分割、格式化等。字节串主要用于处理二进制数据,不支持字符串的大多数操作和方法。

2.4 转义字符和原字符

  在Python中,转义字符\...是一些特殊字符序列,它们用于表示一些无法直接输入或显示的字符,如换行、制表符等。

  如果不希望前置 \ 字符转义成特殊字符,可以使用 原始字符串(raw string),在引号前添加 r 即可。原始字符串还有一个微妙的限制:一个原始字符串不能以奇数个 \ 字符结束。

  下面是Python中常见的转义字符以及它们的原字符对应关系:

转义字符 原字符 描述
\\ \ 反斜杠
\’ 单引号
\" " 双引号
\n 换行 换行符
\r 回车 回车符
\t 制表符 水平制表符(Tab)
\b 退格 退格符
\f 走纸换页 换页符
\uXXXX Unicode 16进制表示的Unicode字符
\UXXXXXXXX Unicode 32进制表示的Unicode字符
  • 单引号和双引号:
    • 字符串可以用成对的单引号 '...'或双引号 "..."来标示,结果完全相同。
    • 要标示引号本身,我们需要对它进行“转义”,即在前面加一个 \。 或者,我们也可以使用不同类型的引号(即外层用双引号,内层用单引号,反过来也可以)
print('He said, \'Hello\' to me.')  
print("She replied, \"Hi there!\"")  
# 也可以外面使用双引号,里面使用单引号,或者反过来
print("He said, 'Hello' to me.")  
print('She replied, "Hi there!')  
He said, 'Hello' to me.
She replied, "Hi there!"
  • 换行符和制表符
print("Hello\nWorld")   
print("Hello\tWorld")   
print("Hello\bWorld")   
print("Hello\rWorld")   
print("Hello\fWorld")
Hello			# 换行符
World
Hello	World   # 制表符
HellWorld 		# 退格符
World			# 回车符
HelloWorld      # 换页符
  • 反斜杠:反斜杠在字符串中被用于表示转义字符,如果你只使用一个反斜杠,Python 会认为你想要输入一个特殊的字符,而不是真正的反斜杠。所以想表示一个反斜杠,需要使用\\,或者是使用原字符r。
print('C:\some\name')   				#  \n被表示成了换行符   							 
print(r'C:\some\name')  					
print('C:\\some\\name') 					
print(r"This is a raw string with \n ") 
C:\some
ame				
C:\some\name
C:\some\name
This is a raw string with \n      

2.5 分隔符

分隔符 说明
() 圆括号,用于表示元组、函数调用等
[] 方括号,用于表示列表、索引等
{} 花括号,用于表示字典、集合等
, 逗号,用于分隔列表、元组、字典中的元素等
: 冒号,用于表示切片、字典中的键值对等
. 点号,用于调用对象的属性、方法等
; 分号,用于分隔代码行
@ at 符号,用于装饰器、装饰器函数等
= 赋值运算符,用于赋值操作
-> 用于定义函数的返回类型

2.6 文本样式

在Unix-like终端中,可以使用ANSI转义码来控制文本的前景色、背景色和显示方式。在Python中,您可以使用这些转义码来在print函数中设置文本的样式。

前景色 背景色 颜色 显示方式 意义
30 40 黑色 0 终端默认设置
31 41 红色 1 高亮显示
32 42 绿色 4 使用下划线
33 43 黄色 5 闪烁
34 44 蓝色 7 反白显示
35 45 紫红色 8 不可见

例如print('\033[4;32;43m' + 'Colored Text' + '\033[0m')

  • \033[4;32;43m:这部分设置了显示方式和前景色、背景色。4表示使用下划线显示,32表示前景色为绿色,43m表示背景色为黄色;
  • 'Colored Text':这是文本内容;
  • \033[0m:这部分将显示方式恢复为默认。
# 设置前景色为红色,背景色为蓝色,高亮显示方式:

print('\033[1;31;44m' + 'Highlighted Text' + '\033[0m')                                             

  请注意,这些效果在支持ANSI转义码的终端中才会有效。在不同终端和环境中,可能会有不同的效果。在Python中使用ANSI转义码时,最后要使用\033[0m来将设置恢复为默认值。

三、程序控制

  如果是把一个值与多个常量进行比较,或者检查特定类型或属性,match 语句更有用。详见 match 语句。
Python的控制语句用于控制程序的执行流程,使得程序可以根据不同的条件做出不同的决策。Python中常见的控制语句包括条件语句(if语句)、循环语句(for循环和while循环)以及跳转语句(break、continue和return)。

以下是各种控制语句的详细介绍:

3.1 条件语句

3.1.1 if 语句

  if语句用于在满足特定条件时执行特定的代码块。它的基本结构如下:

if 条件:
    # 条件成立时执行的代码块
elif 其他条件:
    # 如果上一个条件不成立,但其他条件成立时执行的代码块
else:
    # 如果所有条件都不成立时执行的代码块

  if语句可以有零个或多个 elif 部分,else 部分也是可选的。你也可以使用更简洁的三元运算符,在一行代码中根据条件选择两个不同的值,例如:

x = 10
result = "x 大于 5" if x > 5 else "x 小于等于 5"
print(result)

3.1.2 match语句

  如果是把一个值与多个常量进行比较,或者检查特定类型或属性,match 语句更有用。

  match语句是Python 3.10版本引入的一项新特性,用于模式匹配,即将一个值与多个模式进行比较,并执行与匹配的模式相对应的代码块。它提供了一种更简洁、更直观的方式来处理多个条件分支,使代码更易于理解和维护。以下是match语句的基本结构:

match value:
    case pattern_1:
        # 匹配 pattern_1 时执行的代码块
    case pattern_2:
        # 匹配 pattern_2 时执行的代码块
    # ...
    case _:
        # 默认情况下执行的代码块

  在match语句中,value是要进行模式匹配的值,而pattern则是要匹配的模式。每个case子句都包含一个模式和对应的代码块。模式可以是常量、变量、序列、映射等。以下是一些match语句的使用示例:

  1. 匹配常量和变量
match value:
    case 0:
        print("Zero")
    case x:
        print(f"Non-zero value: {
      
      x}")
        
print(result)

你也可以使用 | (表示 or)在一个模式中组合几个值:

def http_error(status):
    match status:
        case 400:
            return "Bad request"
        case 401 | 403 | 404:
    		return "Not allowed"
        case 404:
            return "Not found"
        case 418:
            return "I'm a teapot"
        case _:
            return "Something's wrong with the internet"
  1. 匹配序列、字典
match sequence:
    case []:
        print("Empty sequence")
    case [x, y]:
        print(f"Two elements: {
      
      x}, {
      
      y}")
    case [x, *rest]:
        print(f"First element: {
      
      x}, Rest: {
      
      rest}")
match data:
    case {
    
    "name": "Alice", "age": age}:
        print(f"Name: Alice, Age: {
      
      age}")
    case {
    
    "name": name, "age": age}:
        print(f"Name: {
      
      name}, Age: {
      
      age}")
  1. 嵌套匹配:
match value:
    case [x, y] if x == y:
        print("Equal elements")
    case [x, y]:
        print("Different elements")
    case _:
        print("Other case")
  1. 使用match表达式:
result = match value:
    case 0:
        "Zero"
    case x:
        f"Non-zero value: {
      
      x}"

print(result)

  这段代码和第一个示例基本是一样的处理,只不过最后会把两种匹配情况下value的值,最后赋值给result这个变量。最后,print(result)语句将打印result的值,这可能是ZeroNon-zero value: x

更多使用方法,可参考 官方文档《4.6 match 语句》

3.2 循环语句

循环语句用于重复执行一段代码块,直到满足某个条件为止。Python支持for循环和while循环。

3.2.1 for 循环

for循环用于遍历序列(如列表、元组、字符串等)中的每个元素,并执行相应的代码块。基本结构如下:

for 变量 in 序列:
    # 循环体,对每个元素执行的代码块

示例:

fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
    print(fruit)

3.2.2 while 循环

while循环用于在满足条件的情况下重复执行一段代码块,直到条件不再满足为止。基本结构如下:

while 条件:
    # 循环体,满足条件时执行的代码块

示例:

count = 0
while count < 5:
    print(count)
    count += 1

3.2.3 循环中的else子句

  Python中的循环语句可以附带一个else子句,它在循环正常结束时执行,但循环被break中断后就不会执行。下面的搜索质数的 for 循环就是一个例子,其中else 子句属于 for 循环,不属于 if 语句。

  循环正常结束,在for 循环中就是成功进行最后一次循环迭代,没有被break中断;在while循环中就是循环条件变为假值后结束循环。

for num in range(2, 10):
    for i in range(2, num):
        if num % i == 0:
            print(num, "不是质数")
            break
    else:
        print(num, "是质数")

3.2.4 生成器表达式和列表推导式

  生成器表达式和列表推导式都允许你在一行代码中创建新的序列,或者从现有的序列中选择、转换或过滤元素。

  • 生成器表达式:生成结果是一个可迭代的生成器,只在迭代时才生成元素(惰性计算),因此在处理大量数据时更节省内存、更高效。
squares = (x ** 2 for x in range(10))
evens = (x for x in range(10) if x % 2 == 0)

print(list(squares))  # 转换为列表
print(list(evens))
  • 列表推导式:生成结果是一个列表,即一次性生成并存储所有的元素。
squares = [x ** 2 for x in range(10)]
even_squares = [x ** 2 for x in range(10) if x % 2 == 0]

print(squares)
print(even_squares)

  生成器表达式使用的语法与列表推导式非常相似,只是使用圆括号而不是方括号。在大多数情况下,生成器表达式的运行速度更快,因为它避免了一次性创建和存储大量元素。如果你需要一次性操作所有元素并创建一个新列表,列表推导式是不错的选择。如果你需要按需生成数据并进行迭代,生成器表达式更合适。

3.3 跳转语句

跳转语句用于改变程序的执行流程。

  • break语句:break 语句将跳出最近的一层 for 或 while 循环。
  • continue语句:用于结束当前循环的这一轮迭代,继续执行下一轮循环。
  • return语句:用于从函数中返回值,并终止函数的执行。

示例:

for num in range(10):
    if num == 5:
        break  # 当 num 等于 5 时跳出循环
    print(num)

for num in range(10):
    if num % 2 == 0:
        continue  # 当 num 是偶数时跳过本次循环的剩余部分,继续下一轮循环
    print(num)

def add(x, y):
    return x + y  # 返回 x 和 y 的和,并终止函数执行

3.4 pass 语句

  pass 语句不执行任何动作。语法上需要一个语句,但程序毋需执行任何动作时,可以使用该语句。这常用于创建一个最小的类:

class MyEmptyClass:
    pass

pass 还可用作函数或条件语句体的占位符,让你保持在更抽象的层次进行思考:

def initlog(*args):
    pass   # Remember to implement this!

3.5 循环控制进阶

3.5.1 enumerate函数:在循环中同时获取索引和元素。

语法:enumerate(iterable, start=0)。其中,iterable是要枚举的可迭代对象(如列表、元组、字符串等),start是索引的起始值(默认为0)。

fruits = ["apple", "banana", "cherry"]
for index, fruit in enumerate(fruits):
    print(f"Index {
      
      index}: {
      
      fruit}")
Index 0: apple
Index 1: banana
Index 2: cherry

3.5.2 zip函数:在循环中同时遍历多个序列。

  zip(iterable1, iterable2, ...)函数返回一个迭代器,每次迭代都会返回一个元组,其中包含了传入的每个可迭代对象的对应元素:

numbers = [1, 2]
letters = ['a', 'b', 'c']
zipped = zip(numbers, letters)  # 创建一个zip对象,可用于迭代

for item in zipped:
    print(item)  						 # 输出:(1, 'a'),(2, 'b')

  在此示例中,zipped是一个迭代器,每次迭代返回一个元组,包含来自numbersletters对应位置的元素。需要注意的是,如果两个输入可迭代对象的长度不一致,zip()函数会截断到最短的长度。

3.5.3 reversed 函数:可用于对序列进行逆向循环

  reversed()函数是Python内置函数之一,用于反转序列类型(列表、元组、字符串等)的数据。需要注意的是,reversed()函数返回的是一个迭代器,而不是实际的列表或序列,这意味着它只能被遍历一次。如果想要创建一个反转后的列表,可以使用list()函数将迭代器转换为列表。

for i in reversed(range(1, 10, 2)):
    print(i) 							 # 输出 9,7,5,3,1

3.5.4 . sorted 函数:在不改动原序列的基础上,按指定顺序循环序列

basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
for f in sorted(set(basket)):
    print(f)							 # 输出apple,banana,orange,pear
    

3.5.5 sortsorted详解

3.5.5.1 基本语法

   sort()sorted()都是Python中用于排序序列(如列表)的函数,它们可以按照升序(从小到大)或降序(从大到小)的方式排列元素。

1. sort()方法:对列表本身进行原地排序,即直接修改原列表,不会返回新的列表。基本语法如下:

list.sort(key=None, reverse=False)
  • key:用于指定排序的规则(可选参数),可以是一个函数,它会应用于列表中的每个元素,并返回一个用于比较的关键字。
  • reverse:指定排序顺序,为True时降序排序(默认为False)。

示例:

names = ["Alice", "Bob", "Charlie", "David"]
names.sort(key=len)
print(names)  						   # 输出:['Bob', 'Alice', 'David', 'Charlie']

2. sorted()函数:一个全局函数,用于对任何可迭代对象(如列表、元组、字符串等)进行排序,返回一个新的已排序的列表(不会修改原始序列)。基本语法如下:

sorted(iterable, key=None, reverse=False)
  • iterable:要排序的可迭代对象。
  • key:用于指定排序的规则(可选参数),可以是一个函数,它会应用于可迭代对象中的每个元素,并返回一个用于比较的关键字。
  • reverse:指定排序顺序,为True时降序排序(默认为False)。

使用sorted()函数的示例:

names = ["Alice", "Bob", "Charlie", "David"]
sorted_names = sorted(names, key=len)
print(sorted_names)  				 # 输出:['Bob', 'Alice', 'David', 'Charlie']

3. 操作对象

  因为sort是对被操作对象进行原地修改,而sorted不会修改原对象,所以sorted 函数可以应用于任何可迭代对象,包括列表、元组、字符串、集合、字典的键、自定义对象的排序键等,它将返回一个新的排序后的列表。而元组和字符串是不可修改的,所以sort方法对齐不适用,下面举例说明:

# 列表排序
my_list = [4, 2, 1, 3]
my_list.sort()  														# 就地排序
sorted_list = sorted(my_list)  											# 返回新的排序后列表

# 字符串排序
my_string = "hello"
sorted_string = ''.join(sorted(my_string))  							# 返回新的排序后字符串

# 元组排序
my_tuple = (3, 1, 2)
sorted_tuple = tuple(sorted(my_tuple)) 			 						# 返回新的排序后元组

# 自定义对象排序
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

people = [Person('Alice', 25), Person('Bob', 30), Person('Eve', 22)]
sorted_people = sorted(people, key=lambda person: person.age)  			# 按年龄排序
3.5.5.3 key 参数用于复杂排序的各种可能

  key参数在排序时用于指定一个函数,这个函数将应用于可迭代对象中的每个元素,并返回一个用于比较的关键字。通过key参数,您可以实现对复杂对象的排序,例如根据对象的某个属性或特征进行排序。下面是一些示例,演示了不同类型的key参数的可能性:

  1. 按照字符串长度排序:
names = ["Alice", "Bob", "Charlie", "David"]
sorted_names = sorted(names, key=len)
print(sorted_names)  				 # 输出:['Bob', 'Alice', 'David', 'Charlie']
  1. 按照字符串的最后一个字符排序:
words = ["apple", "banana", "cherry", "date"]
sorted_words = sorted(words, key=lambda x: x[-1])
print(sorted_words)  				# 输出:['banana', 'cherry', 'apple', 'date']
  1. 按照对象的某个属性排序:
# 根据每个人的年龄进行排序
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

people = [Person("Alice", 25), Person("Bob", 30), Person("Charlie", 22)]
sorted_people = sorted(people, key=lambda person: person.age)
for person in sorted_people:
    print(person.name, person.age)
Charlie 22
Alice 25
Bob 30
  1. 按照自定义函数返回值排序:
numbers = [3, 5, 8, 1, 4]
def custom_key(num):
    return num % 2  				 # 奇数在前,偶数在后

sorted_numbers = sorted(numbers, key=custom_key)
print(sorted_numbers)  				 # 输出:[3, 5, 1, 8, 4]
  1. 按照字典中某个键的值排序:
# 根据水果价格进行排序
fruits = [
    {
    
    "name": "apple", "price": 1.0},
    {
    
    "name": "banana", "price": 0.5},
    {
    
    "name": "cherry", "price": 2.0}
]
sorted_fruits = sorted(fruits, key=lambda fruit: fruit["price"])
for fruit in sorted_fruits:
    print(fruit["name"], fruit["price"])
banana 0.5
apple 1.0
cherry 2.0

四、函数

4.1 函数的基本定义

  在编程中,函数是一种可重用的代码块,用于执行特定任务或操作。通过使用函数,我们可以我们能够将一个大问题分解成多个小任务,从而简化编程过程;可以将代码组织得更加模块化,使其易于管理和维护。

  在Python中,我们使用关键字 def 来定义函数。它可以接受输入(参数),执行特定操作,并返回输出(结果)。函数定义的基本结构如下:

def function_name(parameters):
    # 函数体
    # 执行任务的代码
    return result  # 可选的返回值

其中:

  • function_name 是函数的名称,你可以为函数取一个有意义的名字。
  • parameters 是函数的参数列表,它们是函数执行所需的输入。

  一旦你定义了函数,就可以在代码的其他地方调用它。调用函数时,你需要提供参数,以便函数可以使用它们来执行操作。下面是一个简单的示例:

def greet(name):
    return "Hello, " + name + "!"

# 调用函数
result = greet("Alice")
print(result)  							# 输出:Hello, Alice!

  在上面的示例中,我们定义了一个名为 greet 的函数,它接受一个参数 name。当我们调用 greet("Alice") 时,函数会返回 "Hello, Alice!"

4.2 作用域、局部变量和全局变量

  在Python中,“作用域”(Scope)是一个指定变量可见性和可访问性的概念。作用域规定了在哪些地方可以访问或引用变量。Python有两种主要的作用域:

  • 全局作用域(Global Scope):全局作用域是程序中所有函数之外的区域,通常包括在顶层定义的变量和函数。在全局作用域中声明的变量称之为全局变量,可以在整个程序中进行访问。

  • 局部作用域(Local Scope):函数内部声明的变量默认属于局部变量,其作用域就是局部作用域,即只能在函数内部进行访问。局部变量仅在函数执行时才存在,当函数执行完毕后,局部变量会被销毁,所以函数外部无法直接访问这些变量。

关于全局变量和局部变量,还遵循以下原则:

  1. 在函数内部尝试修改全局变量的值,Python将会创建一个新的局部变量,而不会影响全局变量。要在函数内部修改全局变量的值,需要使用 global 关键字。
  2. 在局部作用域中,如果有一个与全局作用域同名的变量,那么局部作用域的变量会遮蔽(覆盖)全局作用域的变量,但不会影响全局变量的值。
  3. 局部变量为组合数据类型且未创建时,等同于全局变量

以下是一个展示全局变量和局部变量之间关系的例子:

global_var = 5  # 这是一个全局变量

def modify_global():
	 # 如果不使用global关键字,那么global_var就是函数内部的一个局部变量,且没有预先定义,所以程序会报错。
    global global_var  										# 使用 global 关键字来引用全局变量
   
    global_var += 1
    local_var = 10  										# 这是一个局部变量
    print("Inside the function: global_var =", global_var)
    print("Inside the function: local_var =", local_var)

modify_global()
print("Outside the function: global_var =", global_var)    # 全局变量的值被修改了
print("Outside the function: local_var =", local_var)      # 这里会报错,因为 local_var 是局部变量,函数外部无法访问
Inside the function: global_var = 6
Inside the function: local_var = 10
Outside the function: global_var = 6

  在下面的示例中,虽然函数内部的局部变量 global_var 与全局变量 global_var 同名,但在函数内部打印时,使用的是局部变量 global_var 的值(6),而在函数外部打印时,使用的是全局变量 global_var 的值(5)。

global_var = 5  		# 这是一个全局变量

def modify_global():
	global_var =6  		# 同名局部变量遮蔽全局变量
    global_var += 1  
    print("Inside the function: global_var =", global_var)

modify_global()
print("Outside the function: global_var =", global_var)  # 外部的全局变量的值没有改变
Inside the function: global_var = 7
Inside the function: local_var = 10
Outside the function: global_var = 5

  当函数内部使用一个未创建的局部变量,并且这个局部变量是一个组合数据类型(如列表、字典等),那么在函数内部对该局部变量的修改会影响到全局变量,就好像这个局部变量是全局变量一样。

my_list = [1, 2, 3]  			 # 这是一个全局变量

def modify_list():
    my_list.append(4)  			 # 在函数内部使用未创建的局部变量 my_list

modify_list()
print(my_list) 					 # 输出:[1, 2, 3, 4]

  在这个示例中,函数 modify_list 内部没有显式地声明 my_list 是局部变量,而是直接对其进行了修改。由于 my_list 是一个组合数据类型(列表),Python 认为它是全局变量,并且在函数内部对它的修改实际上影响了全局变量。

4.3 参数

4.3.1 五种函数参数

  在编程中,函数参数是我们传递给函数的值,这些值用于在函数内执行特定操作。按照函数的定义,参数可以分为形参和实参

  • 形参(Parameters):这些是函数定义中列出的参数,用于接收输入数据。
  • 实参(Arguments):函数在调用时传递给函数的实际值。

按照参数的传递方式,可以分为以下几类:

  1. 位置参数:最常见的参数类型。当我们调用函数时,位置参数按照它们在函数定义中的顺序传递。
def greet(name, age):
    return "Hello, " + name + "! You are " + str(age) + " years old."

result = greet("Alice", 25)
print(result)  # 输出:Hello, Alice! You are 25 years old.

  在上面的示例中,函数 greet 接受两个位置参数:nameage。当我们调用 greet("Alice", 25) 时,参数按照顺序传递给函数。

  1. 关键字参数:以key=value的形式,我们可以在调用函数时明确指定每个参数的值,而不必遵循位置顺序。这使得代码更具可读性,并避免了参数位置的混淆。
def greet(name, age):
    return "Hello, " + name + "! You are " + str(age) + " years old."

result = greet(age=30, name="Charlie")
print(result)  # 输出:Hello, Charlie! You are 30 years old.

在上面的示例中,我们使用关键字参数来明确指定了参数的值,而不受函数定义中的顺序影响。

  1. 默认参数:有时候,我们希望函数的某些参数拥有默认值,以便在调用函数时不必总是提供这些参数。我们可以通过为参数设置默认值来实现这一点:
def greet(name, age=18):
    return "Hello, " + name + "! You are " + str(age) + " years old."

result = greet("Bob")
print(result)  # 输出:Hello, Bob! You are 18 years old.

  在上面的示例中,参数 age 被设置为默认值 18。如果我们不传递 age 参数,函数将使用默认值。
4. 可变参数:有时候,你可能需要传递不确定数量的参数给函数。Python 提供了两种方式来实现这一点:

  • *args 接收任意数量的位置参数(元组形式)
  • **kwargs 接收任意数量的关键字参数(字典形式)
def print_items(*args):
    for item in args:
        print(item)

print_items("apple", "banana", "cherry")  # 输出:apple banana cherry
def print_info(**kwargs):
    for key, value in kwargs.items():
        print(key + ": " + value)

print_info(name="Alice", age="30", city="New York")
# 输出:
# name: Alice
# age: 30
# city: New York
  1. 特殊形参:限制了参数传递的方式的形参,可以增强代码的可读性,并防止参数的错误传递。
    • 仅限位置的形参(Position-Only Parameters):用 / 标识,只能通过位置传递值。
    • 仅限关键字的形参(Keyword-Only Parameters):用 * 标识,只能通过关键字参数的方式传递值。

示例:

def my_function(a, b, /):
    # 函数体
    # a 和 b 是仅限位置的形参,只能通过位置传递值。

def my_function(*, x, y):
    # 函数体
    # x 和 y 是仅限关键字的形参,只能通过关键字参数的方式传递值。

4.3.2 参数使用规则

函数定义如下:

def f(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2 ):
      -----------    ----------     ----------
        |             |                  |
        |        Positional or keyword   |
        |                                - Keyword only
         -- Positional only
  • 位置参数必须位于关键字参数之前。
  • 可变参数通常放在位置参数和关键字参数之后,以确保它们能够收集剩余的参数值。

假设你有这样一个函数定义:

def complex_function(a, b, c=0, *args, **kwargs):
    # 函数体

那么在调用这个函数时,可以按照上述顺序传递参数:

complex_function(1, 2, 3, 4, 5, x=6, y=7)

错误的调用示例:

  1. 位置参数放在关键字参数之后:
complex_function(a=1, b=2, 3, x=4)
  1. 关键字参数放在可变位置参数之后:
complex_function(1, 2, x=3, 4)
  1. 关键字参数放在可变关键字参数之后:
complex_function(1, 2, 3, x=4, 5)
  1. 重复传递相同参数:
complex_function(1, 2, 3, 4, 5, x=6, x=7)  # 重复的关键字参数 x

4.3.3 任意实参列表和解包实参列表

  1. 任意实参列表:使用 * 表示的任意实参列表,会将传递给函数的所有位置参数收集到一个元组中。这使得你可以在函数内部处理多个参数,而不需要提前知道有多少个参数会传递进来。
def concat(*args, sep="/"):
    return sep.join(args)

concat("earth", "mars", "venus")				# 输出'earth/mars/venus'
concat("earth", "mars", "venus", sep=".")		# 输出'earth.mars.venus'
  1. 解包实参列表:即使用 ***来解包一个可迭代对象(列表、元组、字典等),将其中的每个元素都当作一个位置参数传递给函数。
def add(a, b):
    return a + b

numbers = [3, 5]
result = add(*numbers)  # 等同于 add(3, 5)
print(r)

args = [3, 6]
list(range(*args))            # 等同于list(range(3, 6))
[3, 4, 5]

同样,字典可以用 ** 操作符传递关键字参数:

def parrot(voltage, state='a stiff', action='voom'):
    print("-- This parrot wouldn't", action, end=' ')
    print("if you put", voltage, "volts through it.", end=' ')
    print("E's", state, "!")

d = {
    
    "voltage": "four million", "state": "bleedin' demised", "action": "VOOM"}
parrot(**d)
-- This parrot wouldn't VOOM if you put four million volts through it. E's bleedin' demised !

总结:

  • 任意实参列表使用 * 来收集传递给函数的位置参数,使函数能够接收任意数量的参数。
  • 解包实参列表使用 * 来将一个可迭代对象解包为单独的参数,方便将元素传递给函数。

这两种技巧都能够提高函数的灵活性,让你可以更方便地处理不确定数量的参数。

4.4 匿名函数lambda

  lambda 函数是Python中的一种匿名函数,它可以在一行内定义简单的函数。它的语法非常简洁,通常用于一些简单的操作和表达式。lambda 函数的基本形式如下:

lambda arguments: expression

  其中,arguments 是参数列表,expression 是函数体的表达式。lambda 函数返回一个函数对象,你可以将其赋值给一个变量,然后通过这个变量调用这个匿名函数。以下是 lambda 函数的几种常见用法:

  1. 使用 lambda 函数作为简单的函数:
add = lambda x, y: x + y
result = add(5, 3)  										  # 结果为 8
  1. 在排序时使用 lambda 函数作为键函数:
data = [(1, 'apple'), (3, 'banana'), (2, 'cherry')]
sorted_data = sorted(data, key=lambda x: x[1])  			 # 按照水果名进行排序
  1. map()filter() 等函数中使用 lambda 函数:
numbers = [1, 2, 3, 4, 5]
squared_numbers = map(lambda x: x ** 2, numbers) 			 # 对每个数求平方
even_numbers = filter(lambda x: x % 2 == 0, numbers)  		 # 过滤出偶数
  1. 使用 lambda 函数创建某些回调函数或小规模的逻辑操作:
callbacks = [lambda x: x * 2, lambda x: x ** 2]
result1 = callbacks[0](5)  									 # 结果为 10
result2 = callbacks[1](3)  									 # 结果为 9

需要注意的是,虽然 lambda 函数在一些场景中很有用,但它的使用应该谨慎。对于较为复杂的逻辑,最好还是使用普通的命名函数,以便代码更易读和维护。

4.5 map函数和filter函数

  当你需要对一个可迭代对象(如列表、元组等)中的每个元素进行操作时,mapfilter 是两个非常有用的Python内置函数。

  1. map 函数: map 函数用于将一个函数应用于可迭代对象中的每个元素,返回一个新的可迭代对象,其中包含了应用函数后的结果。
def square(x):
    return x ** 2

numbers = [1, 2, 3, 4, 5]
squared_numbers = map(square, numbers)
# 返回一个 map 对象,可以使用 list() 函数将其转换为列表
result = list(squared_numbers)  # 结果为 [1, 4, 9, 16, 25]

也可以使用 lambda 函数来实现相同的功能:

numbers = [1, 2, 3, 4, 5]
squared_numbers = map(lambda x: x ** 2, numbers)
result = list(squared_numbers)  					# 结果为 [1, 4, 9, 16, 25]
  1. filter() 函数: filter() 函数用于从可迭代对象中筛选出满足某个条件的元素,返回一个新的可迭代对象,其中包含了满足条件的元素。
def is_even(x):
    return x % 2 == 0

numbers = [1, 2, 3, 4, 5]
even_numbers = filter(is_even, numbers)
# 返回一个 filter 对象,可以使用 list() 函数将其转换为列表
result = list(even_numbers)  					  # 结果为 [2, 4]

同样,也可以使用 lambda 函数来实现相同的功能:

numbers = [1, 2, 3, 4, 5]
even_numbers = filter(lambda x: x % 2 == 0, numbers)
result = list(even_numbers)  # 结果为 [2, 4]

   mapfilter函数都可以用于对可迭代对象中的每个元素应用一个函数,返回结果也都是可迭代对象。但是前者应用的函数类似一个计算式(例如x**2),后者是应用的函数是一个条件判断式(例如x % 2 == 0)。所以前者会返回所有元素的计算结果,而后者是条件筛选后的元素。

4.6 内置函数

Python 内置了很多函数和类型,详情可参考内置函数官方文档

  1. 类型相关函数

    • int(), float(), str(), list(), tuple(), dict(), set(): 用于创建相应类型的对象或将其他对象转换为这些类型。
    • type(): 用于获取对象的类型。
    • isinstance(): 用于检查对象是否是指定类型的实例。
  2. 迭代和序列相关函数

    • len(): 用于获取序列对象的长度。
    • sum(): 用于计算序列中的元素的总和。
    • max(), min(): 用于获取序列中的最大值和最小值。
    • enumerate(): 用于同时获取序列的索引和值。
    • zip(): 用于将多个序列的元素一一配对。
  3. 容器相关函数

    • len(): 用于获取容器对象的元素数量(例如列表、字典、集合等)。
    • sorted(): 用于对可迭代对象进行排序。
    • any(), all(): 用于检查可迭代对象中的元素是否为真(any() 至少有一个为真,all() 所有都为真)。
  4. 文件和输入/输出相关函数

    • open(): 用于打开文件。
    • input(): 用于从用户获取输入。
    • print(): 用于打印输出。
  5. 数学和数值相关函数

    • abs(): 用于获取绝对值。
    • round(): 用于四舍五入。
    • pow(): 用于幂运算。
    • divmod(): 用于返回除法的商和余数。
  6. 逻辑和比较函数

    • bool(): 用于将对象转换为布尔值。
    • all(), any(): 用于检查可迭代对象中的元素是否为真。
    • max(), min(): 用于获取最大值和最小值。
    • sorted(): 用于对可迭代对象进行排序。
  7. 其它常用函数

    • range(): 用于生成整数序列。
    • map(), filter(): 用于对可迭代对象的元素应用函数或进行筛选。
    • zip(): 用于将多个序列的元素一一配对。
    • getattr(), setattr(), delattr(): 用于对象属性的操作。
    • globals(), locals(): 用于获取全局和局部变量的字典。

4.6 文档字符串和函数注解

  文档字符串(Docstrings) 是位于函数、模块、类或方法定义的第一个语句,是用于描述它们用途和功能的说明性文本。文档字符串通常使用三重引号(单引号或双引号)来定义,可以跨越多行。你可以通过特殊的属性(如 __doc__)来访问它们。以下是编写文档字符串时的一些常见规则和惯例:

  • 文档字符串应该提供关于代码元素的清晰、简洁和详细的描述,包括以下内容:
    • 代码元素的目的和功能。
    • 参数的说明,包括参数名称、类型、默认值和含义。
    • 返回值的说明,包括返回值的类型和含义。
    • 举例和用法示例,以帮助用户理解如何使用该代码元素。
    • 可能的异常情况和错误处理方式。
  • 使用标准格式,以便能够被文档生成工具(如Sphinx)和阅读工具(如IDE)正确解析和渲染。
    • 以一行简要描述开头,概括代码元素的主要目的。
    • 使用段落或分节标题来组织文档,使其易于阅读。
    • 使用缩进或标点符号来突出重要信息。
    • 在需要时使用代码示例来说明使用方法。
def calculate_area(length, width):
    """
    Calculate the area of a rectangle.
    
    Args:
        length (float): The length of the rectangle.
        width (float): The width of the rectangle.
    
    Returns:
        float: The area of the rectangle.
        
    Example:
        >>> calculate_area(5, 3)
        15.0
    """
    return length * width

print(calculate_area.__doc__)

  总之,遵循一致的文档字符串书写规则和惯例有助于统一团队的文档风格,提高代码的可读性和可维护性,帮助其他开发者更好的理解和使用你的代码。

  函数注解(Function Annotations) 是Python中的一项特性,它允许你为函数的参数和返回值提供额外的元数据信息(详见 PEP 3107PEP 484 ),通常用于指定参数和返回值的数据类型或其他相关信息。函数注解不会影响函数的实际行为,但它们提供了有用的元数据,可以用于文档、类型检查和其他用途。下面是关于函数注解的详细介绍:

  1. 语法: 函数注解是在函数定义中的参数和返回值后面使用冒号(:)来指定的。语法如下:

    def function_name(param1: annotation1, param2: annotation2, ...) -> return_annotation:
        # 函数体
    
    • param1, param2, …: 这些是函数的参数名。
    • annotation1, annotation2, …: 这些是注解,通常用于指定参数的类型。注解可以是任何表达式,但通常是数据类型名称。
    • return_annotation: 这是函数的返回值的注解,通常用于指定返回值的类型。
  2. 类型提示: 最常见的用途是使用函数注解来提供参数和返回值的类型提示。这有助于代码的可读性,并允许一些类型检查工具(如静态类型检查器)进行类型验证,以减少潜在的类型错误。

  3. 注解可以是任何表达式: 虽然通常用于类型提示,但注解可以是任何合法的Python表达式,包括函数、类或常量的引用。这使得你可以将自定义对象用作注解,以提供更多元数据信息。

    示例:

    def process_data(data: DataObject) -> ProcessedData:
        # 函数体
    
  4. 不影响实际行为: 函数注解以字典的形式存放在函数的 __annotations__ 属性中,不会改变函数的实际行为,它们只是提供了元数据信息。Python解释器不会自动执行类型检查或强制类型转换。

以下是一个简单的示例:

def f(ham: str, eggs: str = 'eggs') -> str:
   print("Annotations:", f.__annotations__)
   print("Arguments:", ham, eggs)
   return ham + ' and ' + eggs

f('spam')
Annotations: {
    
    'ham': <class 'str'>, 'return': <class 'str'>, 'eggs': <class 'str'>}
Arguments: spam eggs
'spam and eggs'

4.7 编码风格

  编码风格(Coding Style)是指编程时采用的一套一致性规则和约定,用于指导代码的组织、格式、命名以及注释等方面。编码风格有助于提高代码的可读性、可维护性和可协作性,使不同开发者之间的代码具有一致的外观和结构。

   PEP 8(Python Enhancement Proposal 8)是一份被广泛接受的python编码风格指南,它推行的编码风格易于阅读、赏心悦目。以下是 PEP 8 中一些重要的编码风格规范:

  1. 缩进: 使用 4 个空格作为缩进。不要使用制表符进行缩进。
  2. 行长限制: 每行代码最好不要超过 79 个字符。对于注释和文档字符串,最好不要超过 72 个字符(这样换行的小屏阅读体验更好,还便于在大屏显示器上并排阅读多个代码文件)。
  3. 空格:
    • 在运算符周围使用空格,但不要在函数调用和索引的内部使用空格。例如:result = a + b
    • 逗号后要用空格:当在函数调用、列表、元组等数据结构中使用逗号分隔元素时,建议在逗号后面添加空格,以使代码更清晰,但是不要直接在括号内使用空格。
my_tuple = (1, 2, 3)    # 正确写法

my_tuple = ( 1, 2, 3 )  # 不推荐,在括号内部使用了空格
  1. 空行: 使用空行来分隔函数定义、类定义、以及较大的逻辑块。函数内部可以使用空行来分隔不同的逻辑部分。
  2. 导入: 每个导入语句应该单独占一行。导入应该按照标准库、第三方库、自己的模块的顺序排序。避免使用通配符导入(from module import *)。
  3. 命名规范:
    • 使用小写字母和下划线来命名变量和函数(snake_case)。
    • 使用首字母大写的驼峰命名法来命名类(CamelCase)。
    • 使用全部大写字母和下划线来命名常量(CONFIG_FILE_NAME = “config.txt”)
  4. 注释: 编写清晰、有意义的注释来解释代码的功能。注释应该使用英文,避免使用无意义的注释。
  5. 函数和方法: 函数和方法应该有简洁的、描述性的名称。函数定义后应该有两个空行。函数内部的代码块之间可以使用一个空行分隔。

猜你喜欢

转载自blog.csdn.net/qq_56591814/article/details/132574374
今日推荐