语法

注释

建议在编写代码时,尽可能添加注释来解释代码的用途和作用。这有助于提高代码的可读性和可维护性,使代码更易于理解和修改。

在Python中,注释用于解释代码的作用和用途,以及提供开发者有关代码的相关信息。

Python支持两种类型的注释:单行注释和多行注释。

单行注释

单行注释以井号(#)开头,用于在代码行的末尾添加注释。例如:

## 这是一个单行注释
print("Hello, world!")

多行注释

多行注释用三个单引号(’’’)或三个双引号(""")将注释括起来,用于添加多行注释。例如:

'''
这是一个多行注释
可以用于添加代码的说明信息
'''
print("Hello, world!")

转义符

\n

在Python中,\n是一个转义字符,它表示一个换行符。当Python解析一个字符串时,如果遇到\n,则会将其转换为一个换行符。

例如,我们可以使用\n来在字符串中表示一个换行符,例如:

s = "Hello,\nworld!"
print(s)  # Output: 
          # Hello,
          # world!

在这个例子中,\n表示一个换行符,当我们打印字符串s时,Python会自动将\n转换为一个换行符,并输出两行字符串。

\t

在Python中,\t是一个转义字符,它表示一个水平制表符(horizontal tab)。当Python解析一个字符串时,如果遇到\t,则会将其转换为一个水平制表符。

例如,我们可以使用\t来在字符串中表示一个水平制表符,例如:

s = "Name:\tJohn\tAge:\t30"
print(s)  # Output: Name:   John    Age:    30

在这个例子中,\t表示一个水平制表符,当我们打印字符串s时,Python会自动将\t转换为一个水平制表符,并输出四列数据。

\r

在Python中,\r是一个转义字符,它表示一个回车符(carriage return)。当Python解析一个字符串时,如果遇到\r,则会将其转换为一个回车符。

回车符通常与换行符\n一起使用,用于控制文本的格式和排版。在不同的操作系统和编程环境中,回车符和换行符的使用方式可能不同。

例如,我们可以使用\r来在字符串中表示一个回车符,例如:

s = "Hello\rworld"
print(s)  # Output: world

在这个例子中,\r表示一个回车符,当我们打印字符串s时,Python会将光标移动到行首,然后继续输出剩余的字符,因此最终只输出了world这个单词。

tab 和 空格 的区别

在计算机中,tab(制表符)和空格都是用于表示空白的字符。它们的主要区别在于它们在文本中的作用和用途。

  • 显示效果:Tab(制表符)通常会占用多个字符的宽度,并且在大多数文本编辑器和终端中默认为8个空格的宽度。这意味着,使用一个Tab字符可以在文本中创建一个等于8个空格宽度的空白区域。相比之下,空格字符只占用一个字符的宽度。

  • 用途:Tab(制表符)主要用于在文本中进行水平对齐,例如在程序代码中对齐代码块中的变量、函数参数等等。相比之下,空格则通常用于在文本中进行缩进和对齐,例如在排版和排版排版文档中,或者在编写程序中创建代码块缩进。

在编程中,使用tab还是空格是一种编码风格的选择,这通常是由语言或团队的编码规范决定的。在Python中,PEP 8规定使用4个空格作为代码块的缩进方式。

下面是一个使用制表符进行对齐的示例代码:

print("Name:\t\tJohn")
print("Age:\t\t30")
print("Occupation:\tDeveloper")
  • 输出结果如下所示:
Name:           John
Age:            30
Occupation:     Developer

在这个例子中,我们使用了两个制表符\t来使“Name”和“John”之间的距离与“Age”和“30”之间的距离相等,使用了一个制表符\t来使“Occupation”和“Developer”之间的距离与前面的距离相等。

下面是一个使用空格进行缩进的示例代码:

def print_list(lst):
    for item in lst:
        print("  *", item)

在这个例子中,我们使用了两个空格来对代码进行缩进,这符合PEP 8中推荐的缩进方式。

数字类型

在Python中,数字类型包括整数(int)、浮点数(float)、复数(complex)和布尔值(bool)。

Python还支持基本的数学运算,如加减乘除、取余、幂等操作。

注意事项:

  • 在Python中数字类型是动态类型的,即在定义时不需要指定类型,Python解释器会自动根据值来确定类型。

整数(int)

整数是没有小数部分的数字。在Python中,整数类型表示为int。例如:x = 5。

Python的整数类型可以表示任意大小的整数,不像其他语言一样受限于固定的数据类型大小。

范例

  • 整数类型表示为int,可以通过直接赋值或函数调用来创建整数变量。
a = 10  # 直接赋值创建整数变量a

b = int("20")  # 通过函数调用创建整数变量b
  • Python中支持常用的整数运算,包括加、减、乘、除、取余、幂等操作。
x = 5
y = 2

print(x + y)  # 加法运算,输出7
print(x - y)  # 减法运算,输出3
print(x * y)  # 乘法运算,输出10
print(x / y)  # 除法运算,输出2.5
print(x % y)  # 取余运算,输出1
print(x ** y)  # 幂运算,输出25
  • Python支持使用下划线对长整数进行分组,以提高可读性。
a = 1_000_000_000_000  # 使用下划线对长整数进行分组

print(a) # 输出为1000000000000
  • Python中整数类型支持二进制、八进制和十六进制表示法。
a = 0b1010  # 二进制表示,等同于10
b = 0o16    # 八进制表示,等同于14
c = 0x0A    # 十六进制表示,等同于10
  • Python中整数类型还支持各种常见的数学函数和方法,如abs()、round()、divmod()、bit_length()等等。
x = -5
print(abs(x))  # abs()函数返回绝对值,输出5

y = 3.1415
print(round(y, 2))  # round()函数返回四舍五入的值,输出3.14

q, r = divmod(10, 3)  # divmod()函数返回商和余数,q=3, r=1

z = 255
print(z.bit_length())  # bit_length()方法返回二进制表示的位数,输出8

注意事项

  • 在Python中整数类型可以表示任意大小的整数,但在进行大型计算时需要注意性能问题和溢出问题。

  • Python中整数类型是不可变的,即一旦创建就不能更改。

x = 5
x += 2  # 修改x的值会创建一个新的整数对象
print(x) # 输出为7

浮点数(float)

浮点数是带有小数部分的数字。在Python中,浮点数类型表示为float。例如:x = 3.14。

在Python中,浮点数是一种基本的数据类型,表示带有小数部分的数字。Python的浮点数类型可以表示很大或很小的实数,不像其他语言一样受限于固定的数据类型大小。

注意事项:

  • 需要注意的是,在Python中浮点数类型的运算可能会产生舍入误差,这是由于计算机内部表示方式的限制所导致的。在进行精度要求高的计算时,需要使用decimal模块等高精度计算工具。

范例

下面是Python中浮点数类型的一些特点和用法:

  • 浮点数类型表示为float,可以通过直接赋值或函数调用来创建浮点数变量。
a = 3.14  # 直接赋值创建浮点数变量a

b = float("2.718")  # 通过函数调用创建浮点数变量b
  • Python中支持常用的浮点数运算,包括加、减、乘、除、取余、幂等操作。
x = 3.0
y = 2.0

print(x + y)  # 加法运算,输出5.0
print(x - y)  # 减法运算,输出1.0
print(x * y)  # 乘法运算,输出6.0
print(x / y)  # 除法运算,输出1.5
print(x % y)  # 取余运算,输出1.0
print(x ** y)  # 幂运算,输出9.0
  • Python中浮点数类型是不精确的,即由于内部表示方式的限制,浮点数的运算可能会产生舍入误差。
print(0.1 + 0.2)  # 输出0.30000000000000004
  • Python中浮点数类型支持各种常见的数学函数和方法,如abs()、round()、math模块等等。
x = -3.14
print(abs(x))  # abs()函数返回绝对值,输出3.14

y = 3.1415
print(round(y, 2))  # round()函数返回四舍五入的值,输出3.14

import math
print(math.sin(math.pi / 2))  # math模块中的函数,输出1.0

复数(complex)

复数由实数部分和虚数部分组成。在Python中,复数类型表示为complex。例如:x = 2 + 3j。

在Python中,复数(complex)是一种基本的数据类型,表示具有实部和虚部的数值。复数可以通过在实数后添加“j”或“J”来创建,例如2+3j。

注意事项:

  • 需要注意的是,Python中的复数类型和一些其他语言中的实现可能存在一些差异。在使用复数类型时,需要了解具体的实现方式和特点。
  • 在Python中复数类型不支持取余运算。

范例

下面是Python中复数类型的一些特点和用法:

  • 复数类型表示为complex,可以通过直接赋值或函数调用来创建复数变量。
a = 2 + 3j  # 直接赋值创建复数变量a

b = complex(3, -4)  # 通过函数调用创建复数变量b
  • Python中支持常用的复数运算,包括加、减、乘、除、取余、幂等操作。
    • 需要注意的是,在Python中复数类型不支持取余运算。
z1 = 2 + 3j
z2 = 4 - 5j

print(z1 + z2)  # 加法运算,输出6 - 2j
print(z1 - z2)  # 减法运算,输出-2 + 8j
print(z1 * z2)  # 乘法运算,输出23 - 2j
print(z1 / z2)  # 除法运算,输出-0.4117647058823529 + 0.6470588235294118j
print(z1 % z2)  # 取余运算,TypeError: can't mod complex numbers.
print(z1 ** z2)  # 幂运算,输出(0.01461187026612095+0.08678114660469974j)
  • Python中复数类型支持各种常见的数学函数和方法,如abs()、real()、imag()等等。
z = 3 - 4j

print(abs(z))  # abs()函数返回模长,输出5.0
print(z.real)  # real()方法返回实部,输出3.0
print(z.imag)  # imag()方法返回虚部,输出-4.0
  • 复数类型还可以用于表示一些物理量,例如电阻的复阻抗、电感的复阻抗等等。

布尔值(bool)

在Python中,布尔值(bool)是一种基本数据类型,只有两个取值:True和False;

布尔值通常用于条件判断、循环控制、逻辑运算等方面,是编程中非常常见和重要的概念之一;

在所有数值中,0 为 False,非 0 为 True(包括复数);

bool 是 int 的子类。

范例

x = 0
if x:
    print("x is True")
else:
    print("x is False")

y = 3.14
if y:
    print("y is True")
else:
    print("y is False")
    
z = -5+2j
if z:
    print("z is True")
else:
    print("z is False")

## 运行上述代码会输出以下结果:
x is False
y is True
z is True
  • 因为0为False,所以第一个if语句输出了"x is False"。由于3.14和-5+2j都是非0的,因此第二个和第三个if语句都输出了"y/z is True"。
## 空集合
empty_set = set()
if empty_set:
    print("empty_set is True")
else:
    print("empty_set is False")

## 空字典
empty_dict = {}
if empty_dict:
    print("empty_dict is True")
else:
    print("empty_dict is False")

## 空列表
empty_list = []
if empty_list:
    print("empty_list is True")
else:
    print("empty_list is False")

## 空元组
empty_tuple = ()
if empty_tuple:
    print("empty_tuple is True")
else:
    print("empty_tuple is False")

## None
none_value = None
if none_value:
    print("none_value is True")
else:
    print("none_value is False")


## 运行上述代码会输出以下结果:
empty_set is False
empty_dict is False
empty_list is False
empty_tuple is False
none_value is False
  • 空集合 set、空字典 dict、空列表 list、空元组 tuple,以及 None 都为 False
a = True  # 直接赋值创建布尔变量a
b = False  # 直接赋值创建布尔变量b
c = 3 > 5  # 逻辑运算创建布尔变量c,结果为False
  • 可以使用直接赋值或逻辑运算符来创建布尔变量。
a = True
b = False

print(a and b)  # and运算,输出False
print(a or b)  # or运算,输出True
print(not a)  # not运算,输出False
  • 布尔类型支持逻辑运算符,包括与(and)、或(or)和非(not)。
x = 10
if x > 5 and x < 15:
    print("x is between 5 and 15")
else:
    print("x is not between 5 and 15")
  • 布尔类型通常用于条件判断、循环控制等方面,例如在if语句、while语句、for语句等中使用。
a = True
b = 0

print(a > b)  # 输出True,True被当做1处理
print(a == 1)  # 输出True,True被当做1处理
print(a > 1.5)  # 输出False,True被当做1处理
  • 布尔类型可以和其他数据类型进行比较运算,例如和整数、浮点数、字符串等进行比较运算。

bool & int

  • 在Python中,True和False是bool类型的两个预定义常量,它们是int类型的子类。
print(isinstance(True, bool))  # True
print(isinstance(False, bool))  # True

print(isinstance(True, int))  # True
print(isinstance(False, int))  # True
  • 可以使用内置的isinstance()函数来验证这个关系,上述代码中:
    • 第一个和第二个isinstance()函数检查True和False是否为bool类型。结果显示它们确实是bool类型。
    • 第三个和第四个isinstance()函数检查True和False是否为int类型的实例。结果显示它们也是int类型的实例。
    • 因此,bool是int的子类,True和False都是int类型的实例。这也意味着可以将True和False作为整数使用,例如可以将True视为1,False视为0。

缩进

在Python中,缩进是一种非常重要的语法结构。

缩进用于表示代码块之间的层次关系,比如函数、条件语句、循环等等。Python使用缩进来代替其他语言中的大括号或关键字来表示代码块的开始和结束。

注意事项:

  • 缩进必须是空格或制表符的组合。通常情况下,建议使用四个空格作为一个缩进层次。这是Python官方推荐的缩进方式,也符合PEP 8的规范。
    • 在不同的编辑器和操作系统中,制表符的宽度可能不同,导致缩进出现问题。使用空格则可以避免这个问题。
  • 注意,Python中的缩进是强制性的,如果缩进不正确,将会导致语法错误。例如,在下面的示例中,如果else语句的缩进多了一个空格,就会导致语法错误,因为else语句与if语句不再是同一个缩进层次。

范例

下面是一个使用缩进表示代码块的示例:

def greet(name):
    if len(name) > 10:
        print("Wow, your name is really long!")
    else:
        print(f"Hi {name}! Nice to meet you.")

在这个示例中,函数定义的第一行以及条件语句的两个分支都是一个代码块。这些代码块的开始和结束通过缩进来表示。

在这个示例中,函数定义和if语句的缩进层次是一样的,它们属于同一个缩进层次。而else语句则与if语句同级,因此缩进层次也要相同。

续行

在Python中,一行代码通常应该在一行内写完,但是有时候一行代码太长,无法在一个屏幕内显示完整,这时候可以使用续行符(line continuation character)将一行代码分成多行来写。

Python中有两个续行符可以使用,它们分别是反斜杠符号\ 和 圆括号()

\

使用反斜杠符号进行续行:

long_string = "This is a very long string that " \
              "spans across multiple lines using " \
              "a backslash character."

在这个例子中,反斜杠符号被用来将一行代码分成了三行。注意,反斜杠符号要写在行尾,并且反斜杠符号和下一行代码之间不能有空格。

(…)

使用圆括号进行续行:

long_string = ("This is a very long string that "
               "spans across multiple lines using "
               "parentheses.")

在这个例子中,圆括号被用来将一行代码分成了三行。使用圆括号进行续行时,需要注意以下几点:

  • 圆括号内的代码必须是一条语句。
  • 圆括号前后不能有空格。
  • 如果需要将多个变量赋值给同一个元组,可以使用逗号进行分隔。

标识符

在Python中,标识符(identifier)是用来标识变量、函数、类、模块等对象的名称。

下面是Python中标识符的命名规则:

  • 标识符可以由字母、数字和下划线组成,但是不能以数字开头。
  • 标识符是区分大小写的,即大小写字母是不同的标识符。
  • Python中有一些关键字(keyword)不能用作标识符,例如if、else、while、for等等。Python中共有35个关键字,不能用作标识符。
  • 标识符的长度没有限制,但是建议不要使用过长的标识符,一般不超过80个字符。
  • 标识符应该具有描述性,能够清晰地表达其所表示的意义,同时要避免使用和Python内置函数或模块同名的标识符。
  • 标识符中的下划线有特殊含义。单个下划线(_)表示一个临时的占位符,而双下划线(__)开头的标识符具有特殊的含义,称为魔术方法(magic method),通常用于实现类的特殊行为。

下面是一些Python中的命名规范:

  • 以单个下划线开头的标识符表示该标识符是私有的,外部不应该直接访问它。
  • 以双下划线开头,但不以双下划线结尾的标识符是类的属性,它会被Python解释器自动修改名称,以避免与子类中的属性名称冲突。
  • 以双下划线开头和结尾的标识符是特殊的,称为Python魔术方法,它们提供了一些特殊的行为和语法。
  • 标识符应该使用小写字母,如果需要用到多个单词,可以使用下划线进行分隔,例如my_variable、my_function等等。
  • 对于常量,建议使用全大写字母来命名,例如PI、E等等。

总之,良好的命名规范可以提高代码的可读性和可维护性。

变量 & 常量

变量与常量的区别:

  • 变量是用来存储数据的容器,其值可以被修改,也可以在其生命周期内被多次赋值。
  • 常量是一种固定不变的数据,其值在定义之后不能被修改
  • 通常情况下,常量的值在程序的不同部分都是相同的,而变量的值可能会随着程序的运行而发生变化。

变量

在Python中,变量是用于存储数据的容器,可以用来存储各种类型的数据,如数字、字符串、列表等。

Python中的变量不需要声明,可以直接使用。变量在首次被赋值时会被创建,并且在变量的生命周期中可以被多次赋值。

Python中的变量名是标识符,标识符是用来标识变量、函数、类、模块等命名实体的名称。Python中的标识符有以下规则:

  • 只能包含数字、字母和下划线。
  • 不能以数字开头。
  • 区分大小写。
  • 不能使用Python中的保留字作为标识符(例如,ifelsefor等)。

变量赋值

在Python中,变量赋值使用等号(=)操作符。例如:

x = 42
y = "hello"

变量在被赋值之前不需要声明类型。Python是一种动态类型语言,它会在运行时自动推断变量的类型。这意味着同一个变量可以在不同的时间包含不同类型的值。例如:

x = 42
print(x)  # 输出 42

x = "hello"
print(x)  # 输出 "hello"

在Python中,变量的作用域由它们的赋值位置决定。

  • 如果变量在函数内部定义,那么它就是局部变量;
  • 如果在函数外部定义,它就是全局变量。

在Python中,可以使用global关键字来在函数内部访问全局变量。例如:

x = 42

def func():
    global x
    x = 10

func()

print(x)  # 输出 10

最后,Python还支持多个变量同时赋值的语法。例如:

x, y, z = 1, 2, 3

这个语法等价于以下代码:

x = 1
y = 2
z = 3

常量

Python没有显式的常量定义语法,但是可以通过约定来实现常量的定义。

通常,Python中使用全大写字母的标识符来表示常量,例如:

PI = 3.1415926
E = 2.71828

虽然这些标识符仍然可以被修改,但是在实践中,约定俗成的规范使得程序员尽量避免修改这些标识符的值,从而实现了类似于常量的功能。如果程序中违反了这个约定,Python也不会有编译错误或运行时错误。但是,可以使用第三方库(例如constantly库)来实现真正的常量。

golang 有常量定义吗

是的,Go语言提供了常量定义的语法。常量的定义可以使用const关键字,如下所示:

const PI float64 = 3.1415926
const E = 2.71828

Go语言中的常量是无类型的,可以通过上下文自动推断类型。因此,在第二个例子中,常量E的类型会被推断为float64类型。

与Python不同,Go语言中的常量是不可修改的。一旦常量被定义,它的值就不能被修改。这可以帮助程序员避免一些常见的错误,并提高代码的可维护性和可读性。

进制表达

在Python中,您可以使用以下前缀来表示不同的数字进制:

  • 0b或0B:二进制(binary),如0b1010表示十进制数10
  • 0o或0O:八进制(octal),如0o12表示十进制数10
  • 0x或0X:十六进制(hexadecimal),如0xA表示十进制数10

以下是一个示例,展示如何在Python中使用不同的进制:

## 十进制
dec_num = 10
print(dec_num)  # 输出10

## 二进制
bin_num = 0b1010
print(bin_num)  # 输出10

## 八进制
oct_num = 0o12
print(oct_num)  # 输出10

## 十六进制
hex_num = 0xA
print(hex_num)  # 输出10

在Python中,您可以使用int()函数将字符串转换为整数。如果字符串以0b、0o或0x开头,则会根据前缀自动解释为相应的数字进制。例如:

## 字符串转换为整数
bin_str = "1010"
bin_num = int(bin_str, 2)
print(bin_num)  # 输出10

oct_str = "12"
oct_num = int(oct_str, 8)
print(oct_num)  # 输出10

hex_str = "A"
hex_num = int(hex_str, 16)
print(hex_num)  # 输出10

以上示例中,int()函数的第二个参数指定了要将字符串解释为的数字进制。

运算符

以下是 Python 常用的运算符,可以帮助你进行数学运算、逻辑运算、赋值等操作。

算术运算符

+

-

*

/

% 取模(取余数)

** 幂运算

// 整除(向下取整)

范例

  • 下面的代码中使用了 Python 中的整除运算符 //,它的作用是将两个数相除并向下取整,得到一个整数。
  • 第一行代码中,分别对 1、3、5、7 进行整除 2 的运算,结果分别是 0、1、2、3。
  • 第二行代码中,分别对 1、-3、5、-7 进行整除 -2 的运算,注意这里是整数除以负整数,得到的结果是负数,且需要向下取整,结果分别是 -1、-2、-3、-4
print(1//2, 3//2, 5//2, 7//2) # 0 1 2 3
print(1//-2, -3//2, 5//-2, -7//2) # -1 -2 -3 -4
  • // 运算符可以用于向下取整,所以可以替代 math.floor() 函数。但是,// 运算符不能用于向上取整,所以不能完全替代 math.ceil() 函数。
  • 例如,如果我们需要将一个浮点数向上取整,就需要使用 math.ceil() 函数。例如:
import math

x = 3.7
y = math.ceil(x) # 向上取整,结果为 4
print(y)
  • 而使用 // 运算符进行整除操作只能得到向下取整的结果:
x = 3.7
y = x // 1 # 向下取整,结果为 3.0
print(y)
  • 因此,虽然 // 运算符可以替代 math.floor() 函数,但是不能完全替代 math.ceil() 函数。

比较运算符

== 等于

范例 - 1

使用for循环遍历一个字符串,跳过某些字符:

s = 'hello, world!'
for ch in s:
    if ch == 'o':  # 如果字符是'o',则跳过本次循环
        continue
    print(ch)

运行结果:

h
e
l
l
,
 
w
r
l
d
!

!= 不等于

> 大于

< 小于

>= 大于等于

<= 小于等于

位运算符

位运算符(Bitwise operators)用于对二进制位进行操作,这些运算符将二进制数的每一位作为一个独立的单元进行操作。

位运算符适用于整数类型(int)和布尔类型(bool)。Python中的位运算符包括:

& 按位与

  • 两个二进制数中对应位都为1时,结果为1,否则为0(乘法)。

| 按位或

  • 两个二进制数中对应位都为0时,结果为0,否则为1(加法)。

^ 按位异或

  • 两个二进制数中对应位相同则为0,不同则为1。

  • 相异出1

0000 0101 # 8421算出得5
0000 0011 # 8421算出得3
---------
0000 0110 # 相异出1,也就是两者不同则为1,相同则为0

~ 按位取反

  • 对二进制数进行取反操作,将0变成1,将1变成0。
  • 按位取反,正12等于负13,因为
    • 在 Python 中,按位取反操作符是 “~",它会对一个整数的二进制表示进行按位取反操作,即将二进制表示中的每个 0 替换成 1,将每个 1 替换成 0。由于 Python 中采用的是二进制补码表示法,按位取反操作实际上是将原数取反后再减去 1,即按照以下公式进行计算:
    • ~x = -(x+1)
    • 例如,对于正整数 12,它的二进制表示为 1100,按位取反后变成 0011,也就是 3,再取相反数就是 -3。因此,在 Python 中,正数 12 的按位取反结果为 -13。
    • 需要注意的是,Python 中整数类型的大小是有限制的,如果按位取反的结果超出了这个范围,就会抛出 OverflowError 异常。例如,在 32 位 Python 中,对于正整数 2147483647(二进制表示为 0b1111111111111111111111111111111),按位取反后的结果是 -2147483648,这是因为 Python 中的整数类型的大小是 32 位有符号整数的范围,而这个数的二进制表示是 10000000000000000000000000000000,是一个负数。因此,按位取反的结果会溢出,导致出现 OverflowError 异常。

« 左移

  • 将二进制数向左移动指定的位数。相当于将数乘以2的移动位数次方。

>>右移

  • 将二进制数向右移动指定的位数。相当于将数除以2的移动位数次方。

逻辑运算符

逻辑运算符(Logical operators)用于对逻辑值进行操作,这些运算符根据两个或多个逻辑表达式的值,返回一个逻辑结果。

逻辑运算符适用于布尔类型(bool)。

Python中的逻辑运算符包括:and 逻辑与、or 逻辑或、not 逻辑非

注意事项:

  • and 如果前面的表达式等价为 False,后面就没有必要计算了,这个逻辑表达式最终一定等价为 False

    • 1 and ‘2’ and 0,没必要,因为最终一定等价为 False
    • 0 and ‘abc’ and 1,这样才算优化
  • or 如果前面的表达式等价为 True,后面就没有必要计算了,这个逻辑表达式最终一定等价为 True

    • 1 or False or None,一定为 True 了
  • 把最频繁使用的,最少计算就可以知道结果的条件放到最前面,如果它能短路,将大大减少计算量(能短路一定要短路

    • 在写逻辑表达式时,要注意先后顺序。如果一个表达式中,先出现的表达式的值可以决定整个表达式的值,那么就应该将它放在前面。这样可以避免不必要的计算,提高程序的效率。

    • 在Python中,逻辑运算符andor都是短路运算符。这意味着,当计算表达式时,如果最终结果已经可以确定,那么就不会再计算剩余部分的表达式。这是一种优化,可以提高程序的效率。

      • 举个例子,对于一个逻辑表达式A and B,如果A的值为False,那么整个表达式的结果就已经可以确定为False,这时候Python解释器就不会再去计算B的值。
      • 同样地,对于一个逻辑表达式A or B,如果A的值为True,那么整个表达式的结果就已经可以确定为True,这时候Python解释器就不会再去计算B的值。
  • 特别注意,逻辑运算符的返回值不一定为 bool 型

    • 在 Python 中,逻辑运算符 “and”、“or” 和 “not” 的返回值不一定是布尔型,而是根据其操作数的值和类型来决定返回值。具体来说,Python 中的逻辑运算符遵循以下规则:

      1. “and” 返回第一个为假的操作数,如果所有操作数都为真,则返回最后一个操作数。
      2. “or” 返回第一个为真的操作数,如果所有操作数都为假,则返回最后一个操作数。
      3. “not” 返回布尔型,其值为操作数的真值取反。
    • 在 Python 中,任何值都可以被解释为布尔型的 True 或 False,这是因为 Python 中有一个概念叫做“真值测试”,即 Python 会根据对象的值和类型来确定其真值,将其转换成布尔型 True 或 False。对于大多数对象来说,其真值测试的结果都可以被解释为布尔型的 True 或 False。

    • 在进行逻辑运算时,Python 会先将操作数的真值测试的结果转换成布尔型,然后再进行运算。因此,如果逻辑运算的操作数是一个非布尔型的对象,Python 会先将其真值测试的结果转换成布尔型,然后再进行运算。在这种情况下,逻辑运算的返回值也可能是非布尔型的对象,而是被转换成布尔型之后的结果。

      • 例如,对于逻辑运算 “and”,如果其操作数都是整数,那么返回的值可能是整数,而不是布尔型。
      • 具体来说,如果第一个操作数为 0,则返回 0,否则返回第二个操作数。
      • 同理,对于逻辑运算 “or”,如果其操作数都是整数,那么返回的值也可能是整数,而不是布尔型。如果第一个操作数不为 0,则返回第一个操作数,否则返回第二个操作数。

and 逻辑与

  • 如果所有表达式都为True,则结果为True。如果至少有一个表达式为False,则结果为False。

  • 可以理解为乘法运算

A    B    F
0    0    0
0    1    0
1    0    0
1    1    1
  • 这个表格展示了一个逻辑运算的真值表(Truth Table),其中 A, B 和 F 分别代表输入变量和输出变量:

    • A 和 B 是两个二进制数的位值,每个数只能是 0 或 1,它们代表逻辑运算的输入变量。

    • F 代表逻辑运算的输出变量,它的值为逻辑运算的结果。

  • 这个逻辑运算可以写成布尔表达式 F = A AND B,它表示当 A 和 B 都为 1 时,F 的值为 1,否则 F 的值为 0。

  • 这个逻辑运算称为“与运算”,也叫做“逻辑乘法”,其真值表中的每一行都对应着运算中的一个可能的输入组合和输出结果。

and 是Python中的逻辑运算符之一,用于表示逻辑“与”操作。and 运算符用于连接两个条件,只有当两个条件都为True时,整个表达式才为True。

下面是一个简单的例子:

x = 5
y = 10

## 如果 x 等于 5,且 y 等于 10,则输出 True
if x == 5 and y == 10:
    print(True)
else:
    print(False)

在这个例子中,由于 x 等于 5 且 y 等于 10,因此整个条件表达式为True,所以输出为True。

and 运算符也可以用于连接多个条件,例如:

x = 5
y = 10
z = 15

## 如果 x 等于 5,且 y 等于 10,且 z 等于 15,则输出 True
if x == 5 and y == 10 and z == 15:
    print(True)
else:
    print(False)

在这个例子中,由于所有条件都为True,因此整个条件表达式为True,所以输出为True。

or 逻辑或

  • 如果至少有一个表达式为True,则结果为True。如果所有表达式都为False,则结果为False。

  • 可以理解为加法运算,但 1 or 1 还是等于 1(因为真真还是真)

A    B    F
0    0    0
0    1    1
1    0    1
1    1    1
  • 这个表格展示了一个逻辑运算的真值表(Truth Table),其中 A, B 和 F 分别代表输入变量和输出变量:

    • A 和 B 是两个二进制数的位值,每个数只能是 0 或 1,它们代表逻辑运算的输入变量。

    • F 代表逻辑运算的输出变量,它的值为逻辑运算的结果。

  • 这个逻辑运算可以写成布尔表达式 F = A OR B,它表示当 A 和 B 中至少有一个为 1 时,F 的值为 1,否则 F 的值为 0。

  • 这个逻辑运算称为“或运算”,也叫做“逻辑加法”,其真值表中的每一行都对应着运算中的一个可能的输入组合和输出结果。

or 是Python中的逻辑运算符之一,用于表示逻辑“或”操作。or 运算符用于连接两个条件,只要其中一个条件为True,整个表达式就为True。

下面是一个简单的例子:

x = 5
y = 10

## 如果 x 等于 5,或者 y 等于 10,则输出 True
if x == 5 or y == 10:
    print(True)
else:
    print(False)

在这个例子中,由于 x 等于 5,因此整个条件表达式为True,所以输出为True。

or 运算符也可以用于连接多个条件,例如:

x = 5
y = 10
z = 15

## 如果 x 等于 5,或者 y 等于 10,或者 z 等于 15,则输出 True
if x == 5 or y == 10 or z == 15:
    print(True)
else:
    print(False)

在这个例子中,由于 x 等于 5,因此整个条件表达式为True,所以输出为True。

not 逻辑非

在Python中,not 是逻辑运算符之一,用于对一个布尔值进行取反操作。not 运算符只有一个操作数,即将其右侧的表达式的布尔值取反。

下面是一个简单的例子:

x = True
y = not x
print(y)  # 输出:False

在上面的例子中,not xx 的布尔值取反,所以 y 的值为 False

not 运算符通常用于与其他逻辑运算符一起构建复杂的条件表达式,例如:

x = 5
y = 10
z = 15

## 如果 x 不等于 5,且 y 大于 8,则输出 True
if not (x == 5 and y > 8):
    print(True)
else:
    print(False)

在这个例子中,not 用于取反整个条件表达式 (x == 5 and y > 8) 的结果。

赋值运算符

= 赋值

+= 加等于

-= 减等于

*= 乘等于

/= 除等于

%= 取模等于

  • xxx

范例:

给定一个不超过5位的正整数 (不转换为字符串),判断该数的位数,依次打印出万位、千位、百位、十位、个位的数字**

可以使用数学运算和整数除法运算来实现。

num = int(input("请输入一个不超过5位的正整数:"))

if num < 0 or num > 99999:
    print("输入的数不合法")
else:
    if num >= 10000:
        print("万位数字为:", num // 10000)
        num %= 10000
    if num >= 1000:
        print("千位数字为:", num // 1000)
        num %= 1000
    if num >= 100:
        print("百位数字为:", num // 100)
        num %= 100
    if num >= 10:
        print("十位数字为:", num // 10)
        num %= 10
    if num >= 0:
        print("个位数字为:", num)
  • 这段代码首先读取一个不超过5位的正整数,然后使用 if 语句来逐个判断它的位数,依次输出万位、千位、百位、十位、个位上的数字。可以通过取整除法运算 // 和求余运算 % 来实现这一功能。
  • num %= x 详解:
    • num %= x 是一种简写形式,等价于 num = num % x,即取 num 除以 x 的余数,并将结果赋值给 num 变量。
    • 例如,如果 num 的值为 10,执行 num %= 3 后,num 的值将变为 1,因为 10 除以 3 的余数为 1
    • 这种写法可以简化代码,尤其在需要多次对同一个变量执行取余操作时。例如,要将一个数限制在某一范围内,可以使用 num %= max_num,其中 max_num 表示所需的最大值。这样,num 的值就会被限制在 0max_num - 1 之间。
    • 需要注意的是,%= 是一个赋值运算符,因此它会改变原始变量的值

**= 幂运算等于

//= 整除等于

in

  • 判断元素是否在序列中

not in

  • 判断元素是否不在序列中

is

is 判断两个对象是否是同一个对象

is 是一个对象身份运算符,用于比较两个对象是否引用了内存中的同一个对象(是否具有相同的内存地址)。它不仅比较对象的值是否相等,还比较对象的标识。

x = [1, 2, 3]
y = [1, 2, 3]

if x is y:
    # x 和 y 引用同一对象的内存地址
    pass
else:
    # x 和 y 引用不同对象的内存地址
    pass

is 运算符与 == 的区别在于:

  • is 用于检查两个对象是否是同一个对象(是否具有相同的内存地址)。
  • == 用于检查两个对象的值是否相等。

在 Python 中,对于小整数和短字符串等常用对象,由于内存管理的优化,它们可能会被缓存并重用相同的内存地址,但这并不是始终适用于所有对象。因此,在使用 is 运算符时,应该谨慎考虑对象的身份,而不仅仅是其值。通常情况下,用 == 来比较值更为合适。

总体而言,if 语句是用于条件执行的控制结构,而 is 运算符是用于比较两个对象的标识(内存地址)是否相同。

is not

  • 判断两个对象是否不是同一个对象

运算符优先级

以下是Python中所有常用运算符的优先级,按照从高到低的顺序列出:

  1. 括号:()
  2. 幂运算:**
  3. 正负号:+x-x
  4. 乘除取模运算:*///%
  5. 加减运算:+-
  6. 按位运算:&|^<<>>
  7. 比较运算:<<=>>===!=
  8. 逻辑运算:notandor。(not最先做,or最后做)

注意:在实际编写代码时,为了增强代码的可读性,也可以使用括号来明确优先级。例如,可以使用括号来明确乘除法的优先级,例如(a + b) * c

速记:算数 > 比较 > 逻辑

  • 是的,这个速记法非常实用。在Python中,算术运算符的优先级最高,其次是比较运算符,最后是逻辑运算符。
  • 如果在表达式中同时使用这三种类型的运算符,那么根据这个速记法,我们可以快速确定运算的优先级。
  • 同时,如果存在优先级的不确定性,我们也可以使用括号来明确优先级。
  • 其他高级语言的优先级和python的优先级几乎是一样的

范例

  • 2 * 2 ** 3 因为幂**比乘*优先级高,因此先算2 ** 3,所以最后结果为16
    • 为了让代码更便于阅读,可以将上面的写法改为下面的写法2 * (2 ** 3)
  • 按位运算符的优先级低于加减运算符,例如1 + 2 & 3,等价于(1 + 2) & 3,结果为3
  • 逻辑运算符的优先级低于比较运算符,例如1 < 2 and 2 < 3,等价于(1 < 2) and (2 < 3),结果为True
  • 比较运算符的优先级低于算术运算符,例如1 + 2 < 3 * 4,等价于(1 + 2) < (3 * 4),结果为True
  • 不同类型的运算符之间也存在优先级的差异。例如,对于字符串,*的优先级高于+,例如"hello" + "world" * 3,等价于"hello" + ("world" * 3),结果为"helloworldworldworld"
  • 在混合使用不同类型的运算符时,为了避免优先级混淆,可以使用括号来明确优先级。例如,(1 + 2) * 3,等价于3 * (1 + 2),结果为9

特殊语句

pass

在Python中,pass是一个空语句,用于在语法上需要语句的位置中占位,但程序不需要执行任何操作的情况下使用。pass的作用是让程序继续执行而不发生任何操作。

以下是pass的使用情况:

  • 空循环:
while True:
    pass

在这种情况下,pass语句被用作占位符,使循环无限运行,但实际上不执行任何操作。

  • 空函数:
def function_name():
    pass

在这种情况下,pass语句被用作占位符,表示函数的主体部分为空,但是函数的定义是必须的。

  • 空类:
class MyClass:
    pass

在这种情况下,pass语句被用作占位符,表示类的主体部分为空,但是类的定义是必须的。

  • 临时占位:
if condition:
    pass
else:
    # do something

在这种情况下,pass语句被用作临时占位符,表示在条件为真时不执行任何操作,而在条件为假时执行其他操作。

总之,pass是一个空语句,用于在语法上需要语句的位置中占位,但程序不需要执行任何操作的情况下使用。

assert

assert 语句用于在调试过程中检查某个条件是否成立,如果不成立,则触发一个 AssertionError 异常。例如:

x = 10
assert x > 0, "x must be positive"

在这个例子中,如果 x 不大于 0,那么 assert 语句就会触发一个 AssertionError 异常。

属性访问符

在Python中,属性访问符用于访问对象的属性。Python中的属性访问符主要有两种形式:点号(.)和getattr()函数。让我们详细了解一下它们的用法和特点。

点号(.)

点号是最常用的属性访问符号,用于访问对象的属性和方法。

class MyClass:
    def __init__(self):
        self.my_attribute = 42
    
    def my_method(self):
        return "Hello, world!"

obj = MyClass()

## 访问属性
print(obj.my_attribute)  # 输出: 42

## 调用方法
print(obj.my_method())   # 输出: Hello, world!

getattr() 函数

getattr() 函数允许你以字符串的形式动态访问对象的属性和方法。它接受一个对象和一个属性名作为参数,并返回该属性的值。

class MyClass:
    def __init__(self):
        self.my_attribute = 42
    
    def my_method(self):
        return "Hello, world!"

obj = MyClass()

## 使用 getattr() 访问属性和方法
attr_name = "my_attribute"
method_name = "my_method"

print(getattr(obj, attr_name))           # 输出: 42
print(getattr(obj, method_name)())       # 输出: Hello, world!

需要注意的是,如果使用 getattr() 访问一个对象上不存在的属性或方法时,会引发 AttributeError 异常。你可以通过提供第三个参数作为默认值来避免这种情况:

default_value = "Not found"
print(getattr(obj, "non_existent_attribute", default_value))  # 输出: Not found

总结

  • 点号是常见的属性访问方式,适用于已知属性名和方法名的情况。
  • getattr() 函数允许以字符串形式访问属性和方法,适用于需要动态操作的情况,但要注意处理属性不存在的情况。

无论使用哪种属性访问方式,都要确保遵循Python的面向对象编程原则,避免直接操作对象的私有属性和方法。

生成器 & 生成器表达式

生成器是一种特殊的迭代器,可以通过迭代一次次地产生值,而不需要一次性将所有值存储在内存中,这对于处理大量数据或者需要惰性计算的场景非常有用。

yield

yield 是 Python 中用于生成迭代器的关键字,它用于在函数中创建一个生成器(generator)。

yield 关键字用于将函数转换为生成器。当函数包含 yield 语句时,调用该函数不会立即执行函数体,而是返回一个生成器对象。

yield的作用是将函数的执行暂停,并返回一个值给调用者,同时保留了函数的状态,以便下次调用时可以从暂停的地方继续执行。

每次调用生成器的 __next__() 方法(或者在迭代器上使用 for 循环)时,函数会从上一次暂停的地方继续执行,直到遇到下一个 yield 语句,然后将 yield 后面的值返回给调用者,并再次暂停。这样,生成器会记住上一次执行的状态,每次调用生成器时都会从上一次暂停的地方继续执行。

通过 yield,我们可以轻松地编写可以按需生成数据的函数,这些函数在处理大数据集或者需要逐步生成结果时非常有用。

示例1

使用 next() 方法迭代生成器:

def simple_generator():
    yield 1
    yield 2
    yield 3

## 调用生成器函数,得到一个生成器对象
gen = simple_generator()

## 使用生成器对象迭代生成值
print(next(gen))  # 输出: 1
print(next(gen))  # 输出: 2
print(next(gen))  # 输出: 3
  • 在这个示例中,simple_generator() 函数包含三个 yield 语句,分别产生了整数 1、2、3。每次调用 next(gen) 方法时,生成器会从上一次暂停的地方继续执行,直到遇到下一个 yield 语句,然后返回 yield 后面的值给调用者。

使用 for 循环迭代生成器:

def generator_function():
    yield 1
    yield 2
    yield 3

## 使用 for 循环迭代生成器
for value in generator_function():
    print(value)
## 输出:
## 1
## 2
## 3

示例2

def my_range(n):
    i = 0
    while i < n:
        yield i
        i += 1

for x in my_range(10):
    print(x)

在这个例子中,my_range 函数使用 yield 语句来定义生成器,将一个普通的函数变成了一个迭代器。

示例3

def generator_function():
    print(123)
    yield 1
    yield 2
    yield 3

generator_function() # 无任何输出,因为函数以被转换为生成器

生成器表达式

除了使用def关键字定义生成器函数外,还可以使用生成器表达式创建生成器。生成器表达式类似于列表推导式,但使用圆括号而不是方括号。

generator = (x for x in range(3))
for value in generator:
    print(value)
## 输出:
## 0
## 1
## 2

总结

  • 生成器是使用yield关键字定义的特殊函数,用于按需生成值,以避免一次性加载所有数据。
  • 生成器表达式是一种使用圆括号的构造,类似于列表推导式,用于创建生成器对象。
  • 这两者都在需要逐个生成值时,提供了更高效地使用内存的方法。

PS:

生成器的优点

  • 节省内存: 生成器一次只生成一个值,并在需要时产生下一个值,因此可以节省大量内存,特别是当处理大型数据集时。
  • 惰性计算: 生成器是惰性计算的,只有在需要时才会生成值,这样可以提高效率。
  • 无限序列: 生成器可以用来表示无限序列,因为它们是按需生成的。

与列表推导式相比,生成器表达式通常更加高效,因为它们不需要一次性存储所有值。

生成器的状态

生成器函数在执行过程中会保存其状态,包括局部变量的值以及位置等信息。每次调用生成器函数时,它都会从上一次暂停的地方继续执行。

应用场景

生成器在处理大型数据集、惰性计算、无限序列等场景下非常有用。它们可以大大提高程序的性能和内存效率,并且使得代码更加简洁和易读。

总的来说,yield关键字是Python中非常重要的特性之一,它使得生成器成为可能,从而带来了很多便利和效率上的提升。

None

None 是 Python 中表示空值或缺失值的特殊对象。在 Python 中,它是一个唯一的对象,通常用来表示函数没有显式返回任何值或变量尚未赋值。

以下是关于 None 的一些重要信息:

1. 表示空值

None 表示什么都没有,类似其他语言中的 nullnil。当函数没有明确返回值时,Python 会隐式地返回 None

def my_function():
    # 没有明确返回值,默认返回 None
    pass

result = my_function()
print(result)  # 输出 None

2. 与布尔值的关系

None 在布尔上下文中被视为假(False):

value = None
if value:
    print("这个值是真的")
else:
    print("这个值是假的")  # 输出 "这个值是假的"

3. 赋值和比较

用于检查变量是否为 None 的标准方法是使用 is 运算符而不是 == 运算符。is 检查对象标识(identity),而 == 检查对象值是否相等。

a = None
b = None
print(a is b)  # 输出 True

## 使用 == 检查值
print(a == b)  # 输出 True

4. 函数的默认参数

通常在定义函数时,可以使用 None 作为默认参数的值,以便在调用函数时判断是否提供了特定参数的值。

def greet(name=None):
    if name is None:
        print("Hello, guest!")
    else:
        print(f"Hello, {name}!")

greet()         # 输出 "Hello, guest!"
greet("Alice")  # 输出 "Hello, Alice!"

5. 避免与空字符串混淆

None 表示空值,不同于空字符串 ''。空字符串是一个具有长度为零的字符串,而 None 是一个特殊的对象。

empty_string = ''
none_value = None

print(empty_string is None)  # 输出 False
print(empty_string == '')    # 输出 True

print(none_value is None)    # 输出 True

总体来说,None 是一个在 Python 中用于表示缺失值、空值或默认情况的特殊对象,可以帮助在代码中清晰地处理未定义的情况。

关键字

del

在Python中,del关键字用于删除对象的引用。它可以删除列表中的元素,字典中的键值对,或者从命名空间中删除变量。当你不再需要一个对象时,使用del可以释放对象所占用的内存,并允许Python的垃圾回收机制在适当的时候销毁该对象。

例如,你可以使用del从列表中删除一个元素:

my_list = [1, 2, 3, 4]
del my_list[2]  # 删除索引为2的元素,即第三个元素
print(my_list)  # 输出:[1, 2, 4]

你也可以使用del删除字典中的键值对:

my_dict = {'a': 1, 'b': 2, 'c': 3}
del my_dict['b']  # 删除键为'b'的键值对
print(my_dict)  # 输出:{'a': 1, 'c': 3}

最后,你可以使用del从命名空间中删除变量:

x = 5
print(x)  # 输出:5
del x  # 删除变量x
print(x)  # 这将会引发NameError,因为变量x已经被删除了

解构

Python中的解构是指将一个可迭代对象(如列表、元组、集合等)或字典中的元素分解并赋值给变量。这样的操作使得代码更加简洁和易读。让我们来详细了解一下解构在Python中的用法:

元组解构

tuple_example = (1, 2, 3)
a, b, c = tuple_example
print(a)  # 输出: 1
print(b)  # 输出: 2
print(c)  # 输出: 3

列表解构

list_example = [4, 5, 6]
x, y, z = list_example
print(x)  # 输出: 4
print(y)  # 输出: 5
print(z)  # 输出: 6

字典解构

dict_example = {'name': 'Alice', 'age': 30}
name, age = dict_example.values()
print(name)  # 输出: Alice
print(age)   # 输出: 30

在字典解构中,dict_example.values()返回的是字典的值的视图。如果你想要通过键解构字典,可以这样做:

dict_example = {'name': 'Alice', 'age': 30}
name, age = dict_example['name'], dict_example['age']
print(name)  # 输出: Alice
print(age)   # 输出: 30

使用*进行扩展解构

在Python中,你还可以使用*运算符来收集剩余的元素,这对于处理可变长度的数据结构尤其有用。

first, *rest = [1, 2, 3, 4, 5]
print(first)  # 输出: 1
print(rest)   # 输出: [2, 3, 4, 5]

*beginning, last = [1, 2, 3, 4, 5]
print(beginning)  # 输出: [1, 2, 3, 4]
print(last)       # 输出: 5

这种技术在处理不确定数量的元素时非常方便。

示例:

## 定义一个列表
numbers = [1, 2, 3, 4, 5]

## 使用 map() 将 Lambda 函数应用于列表中的每个元素,求每个元素的平方
squared_numbers = map(lambda x: x**2, numbers)

print("原始列表:", numbers)
## 解构前:
print("平方后的列表:", squared_numbers) # 平方后的列表: <map object at 0x000001B59464CF10>
## 解构后:
print("平方后的列表:", *squared_numbers) # 平方后的列表: 1 4 9 16 25

解构时的命名规则

解构中的变量名不一定要与被解构的对象中的元素名相同。例如:

tuple_example = (1, 2, 3)
x, y, z = tuple_example
print(x)  # 输出: 1
print(y)  # 输出: 2
print(z)  # 输出: 3

这里,被解构的元组中的元素没有名称,但是我们可以将它们分配给任意命名的变量。

解构的注意事项

  • 解构时左边的变量数量必须与右边的元素数量相匹配,否则会引发 ValueError 错误。
  • 如果不需要某个元素,可以使用下划线 _ 来代替。
  • 解构不仅可以用于基本数据结构,还可以用于自定义对象,只要对象是可迭代的。

解构是Python中非常强大和常用的特性之一,能够使得代码更加简洁、优雅和易读。

判断

正常代码执行时是按照先后顺序依次执行的,例如:

  • 先洗手,再吃饭,再洗碗

还可以通过分支的方式对不同的情况进行判断,条件满足,则执行某条件下的语句,例如:

  • 先洗手;
    • 如果饭没有做好,则玩游戏
    • 如果饭做好了,则吃饭
    • 如果饭没有做,则叫外卖

单分支

if condition: # if关键字和条件
    # 语句块
  • 单分支语句以 if 关键字开头,表示要执行的操作需要满足一定的条件。
  • 条件:条件是一个布尔表达式,它通常由比较运算符(如 <><=>===!=)和逻辑运算符(如 andornot)组成。
    • 如果条件为真,那么执行语句块;否则,跳过语句块。(返回为false则跳过语句块,非0 = true,0 = false)
  • 语句块:在单分支语句中,语句块是由一个或多个语句组成的代码块。如果条件为真,那么语句块中的语句将被执行;否则,语句块将被跳过。在 Python 中,语句块使用缩进来表示。

示例1:

x = 10

if x > 5:
    print("x is greater than 5")
  • 如果变量 x 的值大于 5,那么 print() 函数将会执行,打印出字符串 “x is greater than 5”。

注意,如果语句块中只有一个语句,那么可以将其与 if 语句放在同一行中,例如:

## 这种写法在一些简单的场合下可以提高代码的可读性和简洁性。
if x > 5: print("x is greater than 5")

示例2:

a = 10

if a:
    print("aaa") # aaa
  • 输出结果为 aaa,因为非0都是True,因此if语句块成立,所以print中的内容将被打印
a = 0

if a:
    print("aaa")
  • 没有输出结果,因为a的值为0,if语句块将被视为False,因此print语句不会被执行。
a = 10

if a - 10:
    print("aaa")
  • 没有输出结果,因为 10 - 10 = 0

多分支

if condition1:
    # do something
elif condition2:
    # do something else
elif condition3:
    # do another thing
...
else:
    # do default thing
  • 在这个语句中,第一个条件是 if 语句的条件。如果条件为真,则执行第一个代码块。如果条件为假,则测试第二个条件(使用 elif 关键字)。
  • 如果第二个条件为真,则执行第二个代码块。如果第二个条件为假,则测试第三个条件,以此类推。
  • 如果没有任何条件为真,则执行 else 代码块。else 相当于缺省分支

示例:if-else

a = 10

if a > 10:
    print("a大于10")
else:
    print("a不大于10")
  • 如果成立(True),则执行if中的语句块;如果不成立(False),则执行else中的语句块

示例:if-elif-else

x = 10

if x < 0:
    print("x is negative")
elif x == 0:
    print("x is zero")
else: # 隐含说明了 x>0
    print("x is positive")
  • 如果 x 小于 0,则打印 “x is negative”;如果 x 等于 0,则打印 “x is zero”;否则打印 “x is positive”。

  • 嵌套写法:

a = -100

if a > 0:
    print('positive')
else: # 隐含条件为 a <= 100
    if a == 0: 
        print('zero')
    else:
        print('negative')

示例:if-elif-else

a = 10
b = []
c = None

if a:
    print("a is True") # 输出:a is True

if b:
    print("b is True")
else:
    print("b is False") # 输出:b is False

if c:
    print("c is True")
else:
    print("c is False") # 输出:c is False
  • 变量a的值为非零整数10,因此if语句中的条件被解释为True,输出’a is True’。
  • 变量b的值为空列表,因此if语句中的条件被解释为False,执行else语句块中的代码,输出’b is False’。
  • 变量c的值为None,因此if语句中的条件被解释为False,执行else语句块中的代码,输出’c is False’。

if - is

if-is 用于检查对象的内存地址是否相同

x = [1, 2, 3]
y = [1, 2, 3]

if x is y:
    print("x and y reference the same object")
else:
    print("x and y reference different objects")  # 输出 "x and y reference different objects"

在这个例子中,xy 是两个相同值的列表,但它们实际上指向内存中的不同对象。

if - in

in 关键字用于检查一个值是否存在于某个容器对象(例如列表、元组、集合、字典等)中。

numbers = [1, 2, 3, 4, 5]

if 3 in numbers:
    print("3 is in the list") # 输出 "3 is in the list"
else:
    print("3 is not in the list") 

在这个例子中,if 3 in numbers 检查数字 3 是否存在于 numbers 列表中。

if ()

在Python中,if语句后面的括号()通常用于包含条件表达式。这是一种将条件表达式放在括号中的常见做法,但它不是强制性的。例如:

x = 5

if (x > 0):
    print("x是正数")

在这个例子中,(x > 0) 是条件表达式,它在括号中。但是,你也可以写成:

if x > 0:
    print("x是正数")

这两种写法是等效的。添加括号通常用于增加可读性,尤其是在复杂的条件表达式时。

注意事项

  • if 语句是必须的,而 elifelse 部分是可选的。
    • 如果只有 if,则为单分支;如果不只有if,则为多分支
  • 如果为多分支,匹配成功后直接输出结果,而不再向下匹配。
  • 您可以使用任意数量的 elif 语句来测试多个条件,但只能有一个 else 代码块。

循环

循环概述

满足条件就反复执行,不满足就不执行或不再执行,例如:

  • 先洗手,看饭好了没有,没有好,一会来看一次是否好了,一会来看一次,直到饭好了,才可以吃饭
    • 这里的循环条件是饭没有好,饭没有好,就循环的来看饭好了没有

注意事项:

  • continue 和 break 是循环的控制语句,只影响当前循环,包括 while、for 循环

  • 如果循环嵌套,continue 和 break 也只影响语句所在的那一层循环

  • continue 和 break 只影响循环,所以 if cond: break 不是跳出 if,而是终止 if 外的 break 所在的循环

  • for 循环、while 循环都可以互相嵌套,形成多层循环,但循环嵌套层级不易过深

    • 循环嵌套是Python中常见的控制流结构之一,可以用于处理一些需要多层循环嵌套的问题。例如,遍历多维数组、搜索树等。虽然for循环和while循环都可以嵌套使用,但是如果循环嵌套层级过深,会导致代码难以理解和维护,也会影响代码的性能,因此应该尽量避免循环嵌套层级过深。
    • 通常来说,如果循环嵌套的层级超过3层,就会使代码变得难以理解和维护。因此,建议在编写代码时,尽量避免过度嵌套循环。如果需要处理多个嵌套的循环,可以使用其他控制流结构(例如函数递归、迭代器、生成器等)来代替嵌套循环。
    • 当然,循环嵌套层级是否过深,也需要根据具体情况而定。在某些特殊情况下,可能需要嵌套多层循环才能解决问题。但是,在这种情况下,需要仔细考虑循环的设计,并使用一些优化技巧,例如将内层循环的计算结果缓存起来、避免重复计算等,以提高代码的性能。

while 循环

Python中的while循环是在满足条件时执行一段代码块的一种循环结构,它通常用于需要反复执行某个代码块,直到满足某个条件时停止的场景。

while 循环语法

  • 条件表示要满足的条件,只有当条件满足时,while循环才会执行代码块
  • 代码块表示需要重复执行的一段代码,当代码块执行完毕后,会再次判断条件是否满足,如果满足则继续执行,否则结束循环。
while 条件:
    代码块

while 循环注意事项

  • 需要注意的是,在使用while循环时要避免出现死循环。如果条件一直满足,循环就会一直执行下去,程序将无法继续执行。常见的出现死循环的原因有:

    • 条件不变。如果条件不变,循环将一直在执行,例如while True

    • 条件始终为True。如果条件表达式恒为True,循环将永远不会停止。

    • 没有对计数器进行递增或递减操作。如果计数器没有递增或递减,循环将无法终止,例如while i < 10,但是没有对i进行递增或递减操作。

    • 因此,在使用while循环时,需要仔细检查条件和计数器,并确保它们的变化符合预期,以避免出现死循环。

除了上面提到的死循环问题之外,使用while循环时还需要注意以下几点:

  • 注意循环条件的设置。在使用while循环时,需要仔细考虑循环条件的设置,以确保循环能够正常终止。如果循环条件不当,循环可能会一直执行下去,导致程序无法继续运行。
  • 注意循环内部的代码逻辑。在使用while循环时,需要注意循环内部的代码逻辑是否符合预期。循环内部的代码应该能够正确地处理每一次迭代,否则可能会导致循环出现异常或无限循环。
  • 不要忘记设置计数器。在使用while循环时,需要设置一个计数器来记录循环的次数。计数器的初始值、递增或递减的步长,以及终止循环的条件都需要进行正确的设置,否则可能会导致循环出现异常或无限循环。
  • 注意使用break和continue语句。和for循环一样,while循环中也可以使用break和continue语句来提前结束循环或跳过某次循环。这些语句可以提高程序的效率,避免不必要的计算和操作。
  • 注意循环内存占用问题。在使用while循环时,需要注意循环内存占用问题。如果循环内部的操作需要大量的内存空间,可能会导致程序出现内存不足的问题,从而使程序崩溃。因此,需要在编写代码时仔细考虑循环内存占用问题,尽可能地避免出现内存泄漏等问题。

范例 - 1

使用while循环打印出1到5的整数:

i = 1
while i <= 5:
    print(i)
    i += 1

运行结果为:

1
2
3
4
5

范例 - 2

使用while循环遍历一个列表中的元素并打印出来,如果遇到字符串"banana"则跳过当前迭代,如果遇到字符串"orange"则终止整个循环:

fruits = ['apple', 'banana', 'orange', 'cherry']
i = 0
while i < len(fruits):
    if fruits[i] == 'banana':
        i += 1
        continue
    elif fruits[i] == 'orange':
        break
    print(fruits[i])
    i += 1

运行结果为:

apple

范例 - 4

使用while循环找到100以内的所有质数,并打印出来:

i = 2
while i < 100:
    j = 2
    while j <= i // j:
        if i % j == 0:
            break
        j += 1
    else:
        print(i, 'is a prime number')
    i += 1

运行结果为:

2 is a prime number
3 is a prime number
5 is a prime number
7 is a prime number
11 is a prime number
13 is a prime number
17 is a prime number
19 is a prime number
23 is a prime number
29 is a prime number
31 is a prime number
37 is a prime number
41 is a prime number
43 is a prime number
47 is a prime number
53 is a prime number
59 is a prime number
61 is a prime number
67 is a prime number
71 is a prime number
73 is a prime number
79 is a prime number
83 is a prime number
89 is a prime number
97 is a prime number

上面的示例中,内层while循环用于判断当前数是否为质数,如果是质数则打印出来,否则继续下一个循环。如果整个循环正常结束,则会执行else语句块中的代码,这里只是打印出了一个结束的提示信息。

  • 质数:
    • 质数是指除了1和本身之外,没有其他正整数可以整除它的自然数。
    • 质数是指只能被1和本身整除的自然数,比如2、3、5、7等等,而不是可以被其他自然数整除的数,比如4、6、8、9等等。
    • 举个例子:
      • 2是质数,因为它只能被1和2整除,而3也是质数,因为它只能被1和3整除。
      • 但4不是质数,因为它可以被2整除。

范例 - while 死循环

  • 实现方式一
a = 100
while True:
    print(a)
  • 实现方式二
a = 100
while 123: # 因为非0都为true
    print(a)

while not

在Python中,while not 结构是一种循环结构,用于重复执行一段代码,直到指定的条件变为真。当使用 while not 时,后面跟随的条件通常是一个布尔表达式,如果这个条件为假,代码块就会一直执行。

让我们看一个更具体的例子:

count = 0

## 使用 while not 循环来打印 0 到 4 之间的数字
while not count == 5:
    print(count)
    count += 1

在这个例子中,count 初始值为0。while not count == 5: 这个条件检查了 count 是否等于5,如果不等于5,就会执行循环体内的代码。循环体内的代码是打印 count 的值,并将 count 值加1。这个过程会一直重复,直到 count 的值等于5,此时条件变为真,循环停止执行。

换句话说,while not 结构允许我们在条件变为真之前持续执行特定的代码块。在上面的例子中,当 count 等于5时,条件变为真,循环停止执行。这种结构在处理需要持续执行某些操作直到满足特定条件的情况下非常有用。

while notwhile 是Python中用于创建循环的两种不同形式。它们的区别在于条件的表达方式。

  1. while 循环:这是最基本的循环结构之一,它在循环开始前检查条件,如果条件为真,则执行循环体内的代码,然后再次检查条件。如果条件仍然为真,则继续执行循环。当条件变为假时,循环停止执行。

    例如:

    count = 0
    while count < 5:
        print(count)
        count += 1
  2. while not 循环:这是一种使用逻辑否定操作符(not)的特殊形式,它在循环开始前对条件进行取反。换句话说,只有在条件为假时才执行循环体内的代码。当条件为真时,循环停止执行。

    例如:

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

1

在Python中,while not 是一个循环结构,用于执行一段代码块,直到某个条件变为真。具体而言,while not 后面通常跟着一个条件表达式,当这个条件为假时,代码块会一直执行。当条件变为真时,循环停止执行。这种结构可以用于需要在条件变为真之前一直执行某个操作的情况。

下面是一个简单的示例,展示了如何使用 while not 循环:

## 一个简单的示例:计算输入数字的阶乘
num = int(input("请输入一个正整数:"))
factorial = 1

## 使用 while not 循环计算阶乘
while not num <= 0:
    factorial *= num
    num -= 1

print("结果是:", factorial)

在这个示例中,while not 循环用于检查 num 是否大于0。只要 num 不小于等于0,代码块中的内容就会一直执行。在每次循环中,我们将 num 乘以 factorial,然后将 num 减1。当 num 减少到0或负数时,循环停止执行,并打印出计算得到的阶乘值。

总的来说,while not 循环在Python中是一个常用的控制结构,允许你根据特定的条件持续执行某段代码,直到条件变为真。在实际应用中,你可以根据具体需求使用不同的条件表达式,以便控制循环的执行。

for 循环

Python的for循环是用来遍历可迭代对象(iterable)中的元素的,其中可迭代对象包括字符串、列表、元组、字典、集合、生成器等。

for 循环语法

for 变量 in 可迭代对象:
    代码块
  • 可迭代对象可以是字符串、列表、元组、字典、集合、生成器等。
  • 变量表示可迭代对象中的每个元素,在循环中逐个取出并赋值给变量。
  • 代码块表示在每次循环时执行的代码,通常使用缩进来表示代码块。当可迭代对象中的所有元素都被遍历完毕后,for循环自动结束。

for 循环注意事项

  • 注意迭代对象的类型。for循环可以迭代许多不同类型的对象,包括列表、元组、字符串、字典、集合、生成器等。但是,不同类型的对象在迭代时有不同的规则和限制,例如字符串是不可变的,而字典和集合是无序的。因此,在使用for循环时,需要根据迭代对象的类型来选择合适的方法和技巧。
  • 不要在循环内部修改迭代对象。在使用for循环迭代一个列表、元组、字符串等可迭代对象时,不要在循环内部修改该对象,否则会导致迭代过程出现异常,例如删除、添加、修改元素等操作。如果需要修改迭代对象,可以先将其转换为可变类型,例如列表。
  • 注意循环中的变量作用域。在for循环中定义的变量只在循环内部有效,如果需要在循环外部使用该变量的值,需要将其定义在循环外部或使用其他方法。
  • 注意循环嵌套的效率问题。当需要多层循环时,for循环可以使用嵌套的方式实现。但是,循环嵌套层级不要过深,否则会导致程序效率低下。此外,还可以使用其他方法来优化多层循环,例如使用列表推导式、生成器表达式等。
  • 不要忘记使用break和continue语句。在for循环中,可以使用break和continue语句来提前结束循环或跳过某次循环。这些语句可以提高程序的效率,避免不必要的计算和操作。

范例 - 1

使用for循环遍历一个列表中的元素并打印出来:

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

运行结果为:

apple
banana
cherry

范例 - 2

下面是一个示例,使用for循环遍历一个列表中的元素并打印出来,如果遇到字符串"banana"则跳过当前迭代,如果遇到字符串"orange"则终止整个循环:

fruits = ['apple', 'banana', 'orange', 'cherry']
for fruit in fruits:
    if fruit == 'banana':
        continue
    elif fruit == 'orange':
        break
    print(fruit)

运行结果为:

apple

范例 - for + range()

在for循环中,可以使用range()函数来生成一个指定范围内的整数序列,用于控制循环的次数。range()函数的语法格式如下:

range(start, stop, step)

其中,start表示起始位置,默认为0;stop表示结束位置,但不包括结束位置;step表示步长,默认为1。

下面是一个示例,使用range()函数生成一个整数序列,并使用for循环遍历该序列中的元素并打印出来:

for i in range(0, 10, 2):
    print(i)

运行结果为:

0
2
4
6
8

需要注意的是,range()函数生成的整数序列不包括结束位置,因此在循环中通常使用stop+1来表示需要遍历的元素个数。

范例 - for + enumerate()

除了使用range()函数生成整数序列外,还可以使用enumerate()函数来同时获取列表或元组中的索引和对应的元素。enumerate()函数的语法格式如下:

enumerate(sequence, start=0)
  • sequence:表示要遍历的列表或元组
  • start=0:表示下标起始位置,默认为0

enumerate()函数是Python内置函数之一,用于将一个可迭代对象转换为枚举对象,同时列出数据和数据下标。

使用enumerate()函数时,可以在for循环中遍历列表或元组,同时获取每个元素对应的索引。

下面是一个简单的示例:

fruits = ['apple', 'banana', 'orange']
for index, fruit in enumerate(fruits):
    print(index, fruit)

输出结果为:

0 apple
1 banana
2 orange

在这个示例中,我们使用enumerate()函数将列表fruits转换为枚举对象,并在for循环中遍历该对象。每次循环迭代时,都会同时获取当前元素的索引和值,并将它们分别赋值给indexfruit变量。然后,我们将它们打印出来。

使用enumerate()函数时,还可以指定起始位置,如下面这个示例所示:

fruits = ['apple', 'banana', 'orange']
for index, fruit in enumerate(fruits, start=1):
    print(index, fruit)

输出结果为:

1 apple
2 banana
3 orange

在这个示例中,我们将start参数设置为1,因此索引的起始位置为1。

范例:多层循环嵌套

要实现仅列出各个子列表中某个时间点的数值总和,你可以遍历每个子列表,对应时间点的数值进行累加,然后生成包含时间点和总和的新列表。以下是一个示例代码:

result_data = [
    [[1704016800, '4.602887419543591'], [1704016810, '4.602887419543591']],
    [[1704016800, '84.41952319517209'], [1704016810, '84.4195231951721']],
    [[1704016800, '205.7041149378242'], [1704016810, '205.7041149378242']]
]

time_sum_dict = {}

## 遍历每个子列表,对应时间点的数值进行累加
for sublist in result_data:
    for point in sublist:
        timestamp = point[0]
        value = float(point[1])
        
        if timestamp not in time_sum_dict:
            time_sum_dict[timestamp] = value
        else:
            time_sum_dict[timestamp] += value

## 将时间点和总和构建成新的列表
final_result = [[timestamp, str(total)] for timestamp, total in time_sum_dict.items()]

print(final_result)

这段代码首先创建了一个空字典 time_sum_dict 用于存储每个时间点的数值总和。然后,通过嵌套的循环遍历每个子列表中的时间点和数值,并将数值累加到对应时间点的总和中。最后,利用字典中的数据构建了包含时间点和总和的新列表 final_result

需要注意的是,由于最终要求列表中的数值为字符串类型,因此在构建 final_result 时,将总和的数值转换为字符串类型。

范例:使用 _ 占位符

当我们在循环中不需要使用迭代变量的值时,可以使用下划线 _ 作为占位符,表示一个值被接收但并不会被使用。

例如,如果我们只是想简单地循环执行某个操作 num_cores 次而不需要使用迭代变量,可以这样写:

num_cores = 5  # 假设要循环执行 5 次

for _ in range(num_cores):
    # 在这里执行循环体内的操作,但不使用迭代变量的值
    print("Performing operation...")

## 这个循环将会执行 num_cores 次,但没有使用迭代变量的值

这段代码将会执行一个包含了 5 次循环的操作,但是在循环体内并没有使用 _ 这个迭代变量的值。

else 子句

Python 中的循环语句中可以使用 else 子句,其作用是在循环结束后(不是 break 跳出循环),执行一些额外的操作。

具体来说,else 子句可以与 forwhile 循环一起使用。

注意事项

  • forwhile 循环中使用 else 子句时,如果循环中使用了 return 语句,则 else 子句也不会被执行。因为 return 语句会立即终止函数并返回值,从而跳过 else 子句的执行。

范例 - for-else

for 循环中,else 子句会在循环完整执行完成后被执行,但是如果循环中出现了 break 语句,else 子句不会被执行。

for i in range(5):
    print(i)
else:
    print("循环完毕")

输出结果为:

0
1
2
3
4
循环完毕

在上述例子中,循环完整执行完毕后,else 子句被执行。

for i in range(1, 10):
    if i % 2:
        continue
    print(i)
else:
    print("else ~~~")
  • if i % 2: 表示如果 i 除以 2 的余数不为零,即 i 是奇数,则执行 continue
    • continue 是一个控制语句,它会跳过当前循环中的剩余代码,并继续下一次迭代。
  • 因此,当 i 是奇数时,continue 语句将跳过打印语句 print(i),直接进入下一次循环,即不执行接下来的语句。
  • i 是偶数时,if i % 2: 的条件为假(例如6%3余数为0,因此为false),所以不会执行 continue,而会打印出 i 的值。
  • 最后,当循环结束时,将执行 else 语句块中的代码,即打印出 “else ~~~"。

输出结果为:

2
4
6
8
else ~~~

范例 - for-else-break

如果循环中出现了 break 语句,else 子句不会被执行。

for i in range(1, 10):
    print(i)
    if i > 6:
        break
else:
    print("else ~~~")

输出结果为:

1
2
3
4
5
6
7

范例 - while-else - 1

while 循环中,else 子句也会在循环完整执行完成后被执行,但是如果循环中出现了 break 语句,else 子句不会被执行。以下是一个例子:

i = 0
while i < 5:
    print(i)
    i += 1
else:
    print("循环完毕")

输出结果为:

0
1
2
3
4
循环完毕

在上述例子中,循环完整执行完毕后,else 子句被执行。

范例 - while-else - 2

count = 0
while count < 3:
    print("The count is:", count)
    count += 1
else:
    print("The count has reached the maximum value.")

上面的代码中,我们使用while循环打印出count的值,并在count的值达到3时停止循环。由于循环正常结束,而不是通过break语句中断循环,因此程序会执行else语句中的代码块,输出"The count has reached the maximum value."。

需要注意的是,如果在while循环中使用了break语句,那么else语句中的代码块就不会执行。

循环控制语句

可以使用continuebreak语句,以确保循环的条件可以正确地终止循环,避免出现死循环等问题。

continue

continue是Python中的一个控制流语句,用于跳过循环中的某些代码,进入下一次循环

范例 - for - 1

在for循环中,continue语句可以用来跳过当前循环中的某些元素,直接进入下一次循环。

使用for循环输出1~10之间的奇数:

for i in range(1, 11):
    if i % 2 == 0:  # 如果i是偶数,则跳过本次循环(i的值对2取模后,如果结果为0)
        continue
    print(i)
'''
运行结果:
1
3
5
7
9
'''

使用for循环输出1~10之间的偶数:

for i in range(1, 11):
    if i % 2 == 1:  # 如果i是奇数,则跳过本次循环
        continue
    print(i)
'''
运行结果:
2
4
6
8
10
'''

范例 - for - 2

使用for循环遍历一个字符串,跳过某些字符:

s = 'hello, world!'
for ch in s:
    if ch == 'o':  # 如果字符是'o',则跳过本次循环
        continue
    print(ch)

运行结果:

h
e
l
l
,
 
w
r
l
d
!

范例 - while -1

在while循环中,continue语句的用法和在for循环中是一样的。当条件满足时,跳过当前循环,直接进入下一次循环。

使用while循环输出1~10之间的偶数:

i = 1
while i <= 10:
    if i % 2 == 1:  # 如果i是奇数,则跳过本次循环
        i += 1
        continue
    print(i)
    i += 1

运行结果:

2
4
6
8
10

范例 - while -2

使用while循环遍历一个列表,跳过某些元素。

lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
i = 0
while i < len(lst):
    if lst[i] % 3 == 0:  # 如果元素能够被3整除,则跳过本次循环
        i += 1
        continue
    print(lst[i])
    i += 1

运行结果:

1
2
4
5
7
8
10

在上面的示例中,我们使用了continue语句来跳过一些元素,只输出符合条件的元素。

break

break语句可以用于终止整个循环

break是Python中的一个控制流语句,用于跳出循环。当程序执行到break语句时,循环会立即停止,并且程序将跳出循环,执行下一条语句。

范例 - for - 1

在for循环中,break语句可以用于跳出整个循环,不再执行后续的循环语句。

使用for循环输出1~10之间的所有数字,当数字为5时停止循环:

for i in range(1, 11):
    if i == 5:  # 如果数字为5,则跳出循环
        break
    print(i)

运行结果:

1
2
3
4

范例 - for - 2

使用for循环遍历一个字符串,当字符为’o’时停止循环:

s = 'hello, world!'
for ch in s:
    if ch == 'o':  # 如果字符为'o',则跳出循环
        break
    print(ch)

运行结果:

h
e
l
l

范例 - while -1

在while循环中,break语句也可以用于跳出整个循环。

使用while循环输出1~10之间的数字,当数字为7时停止循环:

i = 1
while i <= 10:
    if i == 7:  # 如果数字为7,则跳出循环
        break
    print(i)
    i += 1

运行结果:

1
2
3
4
5
6

范例 - while -2

使用while循环遍历一个列表,当元素为’end’时停止循环:

lst = ['apple', 'banana', 'cherry', 'end', 'durian', 'elderberry']
i = 0
while i < len(lst):
    if lst[i] == 'end':  # 如果元素为'end',则跳出循环
        break
    print(lst[i])
    i += 1

运行结果:

apple
banana
cherry

在上面的示例中,我们使用了break语句来跳出循环,当满足某个条件时,立即停止循环。

with 语句

在 Python 中,with 语句用于简化异常处理和资源管理,通常用于处理文件、网络连接和锁等需要确保资源在使用后被正确释放的情况。with 语句依赖于上下文管理协议(context management protocol),由 __enter____exit__ 方法组成。

基本语法如下:

with expression as variable:
    # code block

其中,expression 必须返回一个实现了上下文管理协议的对象。__enter__ 方法在代码块执行前被调用,而 __exit__ 方法在代码块执行后被调用,无论代码块是正常结束还是由于异常结束。

以下是一些常见的使用场景:

文件操作

with open('example.txt', 'r') as file:
    content = file.read()
    print(content)
## 文件会在with语句块结束后自动关闭

自定义上下文管理器

你可以使用 contextlib 模块中的 contextmanager 装饰器来创建自己的上下文管理器。

from contextlib import contextmanager

@contextmanager
def my_context():
    print("Entering the context")
    try:
        yield
    finally:
        print("Exiting the context")

with my_context():
    print("Inside the context")

数据库连接

import sqlite3

with sqlite3.connect('example.db') as conn:
    cursor = conn.cursor()
    cursor.execute('SELECT * FROM example_table')
    results = cursor.fetchall()
    print(results)
## 数据库连接会在with语句块结束后自动关闭

__enter____exit__ 方法

自定义一个支持 with 语句的类需要实现 __enter____exit__ 方法。

class MyContext:
    def __enter__(self):
        print("Entering the context")
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        print("Exiting the context")

with MyContext() as context:
    print("Inside the context")

在使用 with 语句时,即使代码块中发生了异常,__exit__ 方法也会被调用,从而保证资源得到正确释放。

线程锁

在 Python 中,threading.Lock 是一个用于线程间同步的锁对象,可以确保在多线程环境中一次只有一个线程访问某些资源,从而避免竞争条件(race conditions)。使用 with 语句可以简化锁的获取和释放过程,确保锁在使用后始终被释放,即使在发生异常时也是如此。

使用 threading.Lock 的例子:

import threading

lock = threading.Lock()

def critical_section():
    with lock:
        # 进入临界区
        print("Thread is in the critical section")
        # 在这里执行需要同步的操作
        # 一旦离开 with 语句块,锁会被自动释放
        print("Thread is leaving the critical section")

## 创建多个线程来测试锁
threads = []
for i in range(5):
    thread = threading.Thread(target=critical_section)
    threads.append(thread)
    thread.start()

## 等待所有线程完成
for thread in threads:
    thread.join()

print("All threads have finished execution")

在这个示例中:

  1. 创建了一个 threading.Lock 对象 lock
  2. 定义了一个函数 critical_section,它使用 with lock: 进入临界区。
  3. 使用 threading.Thread 创建多个线程,每个线程都运行 critical_section 函数。
  4. 启动并等待所有线程完成。

critical_section 函数中,with lock: 确保每个线程进入和离开临界区时锁被正确获取和释放,从而避免竞争条件。这样,只有一个线程可以在同一时间进入临界区,确保线程安全。