第3章 基础知识

1 阅读26分钟

第3章 基础知识

3.1 注释

3.1.1 什么是注释

注释是对代码的解释说明。

注释是给程序员看的,在代码执行的时候不起任何作用,不影响程序的结构。

3.1.2 注释的作用

  • 提高代码的可读性。
  • 屏蔽掉暂时不需要的代码。
  • 可以定位程序中出错的位置。

3.1.3 单行注释(行注释)

Python 中 # 后的一行内的内容会被视为注释:

# print("hello world")
print("hello world")  # 打印hello world

为了保持注释的整洁,Python 官方建议在 # 和注释的内容之间加一个空格,在语句和 # 之间加两个空格。

3.1.4 多行注释(块注释)

Python 中使用三个引号开始,三个引号结束(单引号或者双引号都可以),为多行注释。

多行注释在说明文字需要换行时使用,不能嵌套。

"""
Hello World
hello world
"""

但实际上它是一个多行字符串:

print(
    """
    Hello World
    hello world
    """
)

3.2 变量

3.2.1 什么是变量

变量是指在程序执行过程中,其值可以改变的量。在内存的数据区中,会为变量分配存储空间来存放变量的值,这个内存空间的地址对应着变量名称,所以在程序中可以通过变量名称来区分和使用这些内存空间。它的唯一目的是在内存中标记和存储数据,这些数据可以在整个程序中使用。

可以将变量理解为一个可以赋给值的标签,也可以说变量指向特定的值。

3.2.2 变量的创建

变量创建方式:变量名 = 变量值

Python 中的变量不需要声明。每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建。

等号(=)用来给变量赋值。等号(=)运算符左边是一个变量名,等号(=)运算符右边是存储在变量中的值。

var1 = 2  # 定义一个变量,变量名为var1,变量值为2
var2 = 3  # 定义一个变量,变量名为var2,变量值为3
result = var1 + var2  # 定义一个变量,变量名为result,变量值为var1和var2相加的结果
print(result)  # 打印result变量的值

name = "张三"
age = 18
weight = 1000.3

多个变量的创建:

var1 = var2 = var3 = 10  # 多个变量的值相同
var4, var5, var6 = 10, 20, 30  # 多个变量的值不同

3.2.3 标识符命名规则

1)标识符

程序中可以自己命名的地方。

2)命名规则

  • 只能包含字母、数字和下划线,且不能以数字开头。
  • 区分大小写,即 Namename 是两个不同的标识符。
  • 不要和关键字重复。
  • 应既简短又具有描述性。

注意:Python 源文件不遵循命名规范不影响程序的执行,但不建议。

3)关键字

Python 有一组关键字,这些关键字不能用作变量名、函数名或任何其他标识符。

Python 的标准库提供了一个 keyword 模块,可以输出当前版本的所有关键字。

4)标识符命名方法

常见的命名方法有三种:

  • 大驼峰命名法(upper camel case):每个单词首字母大写,例如 UpperCamelCase
  • 小驼峰命名法(lower camel case):第一个单词首字母小写,之后每个单词首字母大写,例如 lowerCamelCase
  • 蛇形命名法(snake case):单词间用下划线连接,例如 snake_case

3.2.4 变量的修改

在程序中可随时修改变量的值,而 Python 将始终记录变量的最新值。

message = "hello world"
print(message)
message = "hello world hello world"
print(message)

Python 还支持方便的对变量相互替换:

var1 = 2
var2 = 20
print(var1, var2)  # 2 20
var1, var2 = var2, var1
print(var1, var2)  # 20 2

3.2.5 常量

在程序中定义后就不再修改的值为常量,Python 中没有内置的常量类型。一般约定使用全大写变量名来表示常量。

PI = 3.1415926
E = 2.718282

3.3 进制以及转换

3.3.1 进制

计算机世界中只有二进制,所以计算机中存储和运算的所有数据都要转为二进制。包括数字、字符、图片、声音、视频等。常见的进制:

  1. 二进制:0、1,满2进1。
  2. 八进制:0-7,满8进1。
  3. 十进制:0-9,满10进1。
  4. 十六进制:0-9 及 A-F,满16进1。十六进制中,除了 0 到 9 十个数字外,还引入了字母,以便表示超过9的值。字母 A 对应十进制的10,字母 B 对应十进制的11,字母 C、D、E、F 分别对应十进制的 12、13、14、15。
二进制八进制十进制十六进制
0000
1111
10222
11333
100444
101555
110666
111777
10001088
10011199
10101210A
10111311B
11001412C
11011513D
11101614E
11111715F
10000201610
10001211711

3.3.2 不同进制表示整数

  1. 二进制:以 0b0B 开头表示。
  2. 八进制:以 0o 开头表示。
  3. 十进制:正常数字表示。
  4. 十六进制:以 0x0X 开头表示,此处的 A-F 不区分大小写。
# 十进制
dec = 10
# 二进制 以0b开头
binary_number = 0b1010
# 八进制 以0o开头
octal_number = 0o12
# 十六进制 以0x开头
hex_number = 0xA

print(dec)
print(binary_number)
print(octal_number)
print(hex_number)
print("~~~~~~~~~~~~~~~~")
print("十进制数为:", dec)
print("转换为二进制为:", bin(dec))
print("转换为八进制为:", oct(dec))
print("转换为十六进制为:", hex(dec))

输出:

10
10
10
10
~~~~~~~~~~~~~~~~
十进制数为: 10
转换为二进制为: 0b1010
转换为八进制为: 0o12
转换为十六进制为: 0xa

3.3.3 二进制转换成十进制

规则:从最低位开始,将每个位上的数提取出来,乘以2的(位数-1)次方,然后求和。

案例:请将二进制 1011 转成十进制的数。

第4位第3位第2位第1位
二进制数字1011
计算1×2³0×2²1×2¹1×2⁰
结果8021

对应十进制数字:8 + 0 + 2 + 1 = 11

3.3.4 十进制转换成二进制

规则:将该数不断除以2,直到商为0为止,然后将每步得到的余数倒过来,就是对应的二进制。

案例:请将 56 转成二进制。

步骤除以2余数
56 ÷ 2280
28 ÷ 2140
14 ÷ 270
7 ÷ 231
3 ÷ 211
1 ÷ 201

56 对应的二进制数字为:111000

3.3.5 十六进制转换成十进制

规则:从最低位开始,将每个位上的数提取出来,乘以16的(位数-1)次方,然后求和。

案例:请将 0x34A 转成十进制的数。

十六进制数字34A
计算3×16²4×16¹10×16⁰
结果7686410

对应十进制数字:768 + 64 + 10 = 842

如果是8进制转换为10进制,就乘以8的(位数-1)次方,然后求和。

3.3.6 十进制转换成十六进制

规则:将该数不断除以16,直到商为0为止,然后将每步得到的余数倒过来,就是对应的十六进制。

案例:请将 356 转成十六进制。

步骤余数
356 ÷ 16224
22 ÷ 1616
1 ÷ 1601

356 对应的十六进制数字为:164

如果将十进制转换为八进制,将该数不断除以8,直到商为0为止,然后将每步得到的余数倒过来。

3.3.7 二进制转换成十六进制

规则:低位开始,将二进制数每四位一组,转成对应的十六进制数即可。

因为2的4次方等于16,所以将二进制数从右向左每4位分成一组。如果二进制数的位数不是4的倍数,则在最左边补零,使其成为4的倍数。

案例:请将 1001011 转成十六进制。

二进制数字:0100 1011
              ↓    ↓
             4     B

十六进制数字:4B

如果二进制转换为八进制,3位分一组。

3.3.8 十六进制转换成二进制

规则:将十六进制数每1位,转成对应的4位的一个二进制数即可。

案例:请将 0x23B 转成二进制。

十六进制数字:  2       3       B(=11)
                             
二进制数字:  0010    0011    1011

对应的二进制数字:001000111011(去掉前导零为 1000111011

如果八进制转换为二进制,1位八进制转成3位二进制数。

3.4 数据类型

在 Python 中,变量就是变量,它没有类型,我们所说的"类型"是变量所指的内存中对象的类型。Python 3 中常见的数据类型分类如下,主要类型有六种:

基本数据类型:

  • 数值:整数(int)、浮点数(float)、复数(complex)、布尔(bool)
  • 字符串(str)

容器数据类型:

  • 列表(list)
  • 元组(tuple)
  • 集合(set)
  • 字典(dict)

特殊数据类型:

  • None:表示空值或缺失值,只有一个值 None。常用于函数没有返回值时,或者表示变量没有被赋值。
  • 不可变数据(3个):Number(数字)、String(字符串)、Tuple(元组)。
  • 可变数据(3个):List(列表)、Dictionary(字典)、Set(集合)。

3.4.1 int 整型

Python 可以处理任意大小的整数,包括负整数。

1)整数分隔符

书写很大的数时,可使用下划线将其中的数字分组,使其更清晰易读。

num1 = 1_000_000_000_000_000
print(num1)  # 1000000000000000

存储这种数时,Python 会忽略其中的下划线。在 Python 看来,1_000_000_000_000_0001000000000000000 没什么不同。这种表示法适用于整数和浮点数,但只有 Python 3.6 及以上版本支持。

2)type 与 isinstance 类型判断

可以使用 type() 来查看变量类型,使用 isinstance() 来判断变量类型。

type()isinstance() 的区别在于 type() 不会认为子类是一种父类类型,isinstance() 会认为子类是一种父类类型。

num1 = True
num2 = 10
print(type(num1))  # <class 'bool'>
print(type(num2))  # <class 'int'>
print(type(num1) == type(num2))  # False
print(isinstance(num1, bool))  # True
print(isinstance(num1, int))  # True,Python3中,bool是int的子类
print(isinstance(num2, int))  # True

3)小整数池

Python 将 [-5, 256] 的整数维护在小整数对象池中。这些整数提前创建好且不会被垃圾回收,避免了为整数频繁申请和销毁内存空间。不管在程序的什么位置,使用的位于这个范围内的整数都是同一个对象。

4)大整数池

一开始大整数池为空,每创建一个大整数就会向池中存储一个。

注意事项:

  • 不同的 Python 实现:小整数池的范围和实现细节可能因 Python 的不同实现(如 CPython、Jython、IronPython 等)而有所不同。上述提到的 [-5, 256] 范围是 CPython 的默认实现。
  • 有时连续赋值的相同大整数也可能指向同一对象,这是因为 Python 环境的优化机制,但是这个优化不是绝对的,也取决于解释器以及交互式以及脚本环境。

3.4.2 float 浮点型

Python 将所有带小数点的数称为浮点数。要注意在使用浮点数进行计算时可能会存在微小误差,可以通过导入 decimal 解决:

num1 = 0.1
num2 = 0.2
print(num1 + num2)  # 0.30000000000000004

from decimal import Decimal
num3 = Decimal('1.0')
num4 = Decimal('0.9')
print(num3 - num4)

也可以使用科学计数法表示浮点数:

num1 = 1.3e7
print(num1)  # 13000000.0

3.4.3 bool 布尔型

布尔型变量只有 TrueFalse,用于真假的判断。

bool1 = True
bool2 = False
print(bool1, bool2)  # True False

Python3 中,boolint 的子类,TrueFalse 可以和数字相加。True==1False==0 会返回 True

is 运算符用于比较两个对象的身份(即它们是否是同一个对象,是否在内存中占据相同的位置),而不是比较它们的值。

print(True == 1)   # True
print(False == 0)  # True
print(True is 1)   # False
print(False is 0)  # False

在 Python 中,能够解释为假的值不只有 False,还有:

  • None
  • 0
  • 0.0
  • False
  • 所有的空容器(空列表、空元组、空字典、空集合、空字符串)

3.4.4 String 字符串初识

字符串就是一系列字符。在 Python 中,用引号括起的都是字符串,其中的引号可以是单引号,也可以是双引号。可使用反斜杠 \ 转义特殊字符。

str1 = 'This is a "string"'
str2 = "This is a 'string' too"
print(str1)  # This is a "string"
print(str2)  # This is a 'string' too

也可以方便的在字符串中包含单引号或双引号:

str1 = "This is a 'string'"
str2 = 'This is a "string" too'
print(str1)  # This is a 'string'
print(str2)  # This is a "string" too

也可以使用三个引号表示多行字符串。三引号允许一个字符串跨多行,字符串中可以包含换行符、制表符以及其他特殊字符。

str1 = """hello world
HELLO WORLD"""
print(str1)

在字符中使用特殊字符时,Python 用反斜杠 \ 转义字符:

转义字符说明
\在行尾作为续行符
\\反斜杠符号
\'单引号
\"双引号
\b退格
\n换行
\t横向制表符
\r回车,回到行首

1)intern 机制

每个字符串(不夹杂空格或者特殊符号),默认开启 intern 机制,共享内存,靠引用计数决定是否销毁。相同的字符串默认只保留一份,当创建一个字符串,它会先检查内存里有没有这个字符串,如果有就不再创建新的了。

2)字符串缓冲池

单个字母,长度为1的 ASCII 字符会被 interned,包括空字符。

3.4.5 数据类型转换

1)自动类型转换(隐式转换)

对两种不同类型的数据进行运算,较小的数据类型(整数)就会转换为较大的数据类型(浮点数)以避免数据丢失,计算结果为浮点型:

num1 = 2
num2 = 3.0
print(num1 + num2)  # 5.0

特别的,两个整型进行除法运算结果也是浮点型:

num1 = 9
num2 = 1
print(num1 / num2)  # 9.0

而整型和字符串相加会报错,此时 Python 无法进行隐式转换完成计算:

num1 = 123
str1 = "456"
print(num1 + str1)  # 报错

2)强制类型转换(显式转换)

可以通过函数对数据类型进行转换:

函数说明
int(x [,base])将 x 转换为一个整数,x 若为字符串可用 base 指定进制
float(x)将 x 转换为一个浮点数
complex(real[,imag])创建一个实部为 real,虚部为 imag 的复数
str(x)将对象 x 转换为一个字符串
repr(x)将对象 x 转换为一个字符串,可以转义字符串中的特殊字符
eval(x)执行 x 字符串表达式,并返回表达式的值
bin(x)将一个整数转换为一个二进制字符串
oct(x)将一个整数转换为一个八进制字符串
hex(x)将一个整数转换为一个十六进制字符串
ord(x)将一个字符转换为它的 ASCII 整数值
chr(x)将一个整数转换为一个 Unicode 字符
tuple(s)将序列 s 转换为一个元组
list(s)将序列 s 转换为一个列表
set(s)转换 s 为可变集合
num_int = 123
num_str = "456"
print("num_int 数据类型为:", type(num_int))
print("类型转换前,num_str 数据类型为:", type(num_str))

num_str = int(num_str)    # 强制转换为整型
print("类型转换后,num_str 数据类型为:", type(num_str))

num_sum = num_int + num_str
print("num_int 与 num_str 相加结果为:", num_sum)
print("sum 数据类型为:", type(num_sum))

输出:

num_int 数据类型为: <class 'int'>
类型转换前,num_str 数据类型为: <class 'str'>
类型转换后,num_str 数据类型为: <class 'int'>
num_int 与 num_str 相加结果为: 579
sum 数据类型为: <class 'int'>

3.4.6 字符的编码和解码

# 创建一个字符串类型数据
str1 = '你好中国'
print(str1)
print(type(str1))

# 将字符串数据类型转换为字节型数据的过程称为编码 encode,需要指定编码类型
byte1 = str1.encode(encoding='utf8')
# 4个字符转换为了12个字节,所以一个汉字占用3个字节
print(byte1)  # b'\xe4\xbd\xa0\xe5\xa5\xbd\xe4\xb8\xad\xe5\x9b\xbd'
print(type(byte1))  # <class 'bytes'>

# 在进行编码集使用时,一定要注意,使用什么编码集编码,就要使用它解码,否则报错

# 将字节型数据转换为字符型数据的过程称为解码 decode
str2 = byte1.decode(encoding='utf8')
print(str2)  # 你好中国
print(type(str2))  # <class 'str'>

3.5 输入与输出

3.5.1 输入

如果接收用户在键盘上输入一些字符,Python 提供了一个 input() 函数,可以让用户输入字符串,并存放到一个字符串变量里。

语法:字符串变量 = input("提示信息")

# Python 开始等待你的输入。这时,你可以输入任意字符,然后按回车后完成输入。
input_str = input("请输入:")
# 输入完成后,不会有任何提示,刚才输入的内容存放到input_str变量里了
print("input_str 数据类型为:", type(input_str))
# 输出input_str查看变量内容
print(input_str)

3.5.2 输出

1)普通输出

使用 print() 可将内容打印。

print("Hello Python")

多个内容之间可以使用逗号隔开:

print("Hello", " Python")

可以使用 end= 来控制 print() 以什么结尾:

print("使用\\n 结尾", end="\n")  # 用\n结尾,等同于print("使用\\n 结尾")
print('使用""结尾', end="")  # 用空字符串结尾
print("Hello")

2)格式化输出

(1) 字符串中使用 % 占位

int1 = 10
float1 = 3.14159
str1 = "int1 = %d, float1 = %f" % (int1, float1)
print(str1)  # int1 = 10, float1 = 3.141590

格式符号列表:

格式符号说明
%d十进制整数
%f浮点数,%.nf 可指定显示小数点后 n 位
%s字符串
%o八进制整数
%x十六进制整数
%e科学计数法

(2) 字符串.format()

方式1:不设置指定位置,按默认顺序

int1 = 10
float1 = 3.14159
bool1 = True
str2 = "int1 = {}, float1 = {}, bool1 = {}".format(int1, float1, bool1)
print(str2)  # int1 = 10, float1 = 3.14159, bool1 = True

方式2:设置指定位置,不能和方式1混合使用

int1 = 10
float1 = 3.14159
bool1 = True
str2 = "int1 = {0}, float1 = {1}, bool1 = {2}".format(int1, float1, bool1)
print(str2)  # int1 = 10, float1 = 3.14159, bool1 = True

方式3:设置参数

int1 = 10
float1 = 3.14159
bool1 = True
str2 = "int1 = {i1}, float1 = {f1}, bool1 = {b1}".format(i1=int1, f1=float1, b1=bool1)
print(str2)  # int1 = 10, float1 = 3.14159, bool1 = True

(3) 数字格式化

float1 = 31415.9
str2 = "{:*^20,.2f}".format(float1)
print(str2)  # *****31,415.90******

: 后可以添加多个参数对数字格式化:

  • *:以 * 填充空白,不写则默认以空格填充。
  • ^:可选 <^>,分别是左对齐、居中、右对齐。
  • 20:数字宽度为20,数字长度不足20则进行填充。
  • ,:可选 ,_,每3位进行分隔。
  • .2f:小数点后保留2位。

(4) 使用大括号 {} 来转义大括号

print("{0} 对应的位置是 {0}".format("hello"))   # hello 对应的位置是 hello
print("{} 对应的位置是 {{0}}".format("hello"))   # hello 对应的位置是 {0}

(5) f-字符串

字符串前加上一个 f,字符串中的 {} 内写入变量名。

int1 = 10
float1 = 3.14159
str3 = f"int1 = {int1}, float1 = {float1}"
print(str3)  # int1 = 10, float1 = 3.14159

{} 内变量名后可以加上 =,打印时会在变量值前加上 变量名=

int1 = 10
float1 = 3.14159
str3 = f"{int1 = }, {float1 = }"
print(str3)  # int1 = 10, float1 = 3.14159

{} 外再套一层 {},即 {{}},会转义:

int1 = 10
float1 = 3.14159
str3 = f"{{int1 = }}, {{float1 = }}"
print(str3)  # {int1 = }, {float1 = }

3.6 运算符

3.6.1 算数运算符

运算符说明实例
+a + b
-减、或取负a - b-a
*a * b
/a / b
//整除,除后向下取整a // b
%模,返回除法的余数a % b
**a ** b
# -------------算术运算符---------------
a = 20
b = 10
c = a + b
print(a, "+", b, "的结果为", c)
c = a - b
print(a, "-", b, "的结果为", c)
c = a * b
print(a, "*", b, "的结果为", c)
c = a / b  # 注意:结果为浮点类型
print(a, "/", b, "的结果为", c)
c = a % b
print(a, "%", b, "的结果为", c)

a = 2
b = 3
c = a ** b
print(a, "的", b, "次方结果为", c)

a = 10
b = 3
c = a // b
print(a, "//", b, "的结果为", c)
print("-" * 30)  # 输出30次-

输出结果:

20 + 10 的结果为 30
20 - 10 的结果为 10
20 * 10 的结果为 200
20 / 10 的结果为 2.0
20 % 10 的结果为 0
2 的 3 次方结果为 8
10 // 3 的结果为 3
------------------------------

3.6.2 赋值运算符

运算符说明实例
=赋值a = 1
+=加法赋值a += 2,等同于 a = a + 2
-=减法赋值a -= 2,等同于 a = a - 2
*=乘法赋值a *= 2,等同于 a = a * 2
/=除法赋值a /= 2,等同于 a = a / 2
//=整除赋值a //= 2,等同于 a = a // 2
%=模赋值a %= 2,等同于 a = a % 2
**=幂赋值a **= 2,等同于 a = a ** 2
:=海象运算符,在表达式中同时进行赋值和返回赋值的值(Python3.8 版本新增)num1 = 20; print((num2 := 3**2) > num1)
# -------------赋值运算符---------------
num3 = 30
num4 = 40
num5 = num3 + num4
print(num5)

num3 += 50  # num3 = num3 + 50
print(num3)

输出结果:

70
80

3.6.3 比较运算符

运算符说明实例
==相等,比较两者的值a == b
!=不相等a != b
>大于a > b
<小于a < b
>=大于等于a >= b
<=小于等于a <= b

注意:不同数据类型的数据不能比较大小。

# -------------比较运算符---------------
num1 = 10
num2 = 20
print(num1 == num2)  # False
print(num1 != num2)  # True
print(num1 > num2)   # False
print(num1 < num2)   # True
print(num1 >= num2)  # False
print(num1 <= num2)  # True

num3 = 'abc'
# 注意:不同的数据类型之间不能进行大小的比较
# print(num1 > num3)  # 报错

# 如果是字符串比较大小,是从最左边开始逐个比较字符串中相应位置的字符的ASCII码
print('5' > '6')   # False
print('15' > '6')  # False

3.6.4 逻辑运算符

运算符说明
and与,x and y,若 x 为 False 返回 x 的值,否则返回 y 的值
or或,x or y,若 x 为 True 返回 x 的值,否则返回 y 的值
not非,not x,若 x 为 True 返回 False,若 x 为 False 返回 True
# -------------逻辑运算符---------------
b1 = False
b2 = True
print(b1 and b2)  # False
print(b1 or b2)   # True
print(not(b1))    # True

print(5 and 8)  # 8  非0表示True,0表示False
print(0 and 8)  # 0
print(5 or 8)   # 5
print(0 or 8)   # 8
print(not(5))   # False

3.6.5 位运算符

运算符说明实例
&按位与a & b
按位或a | b
^按位异或a ^ b
~按位取反~a
<<按位左移a << 1
>>按位右移a >> 1

1)原码反码补码

一个数在计算机中的二进制表示形式,叫做这个数的机器数。机器数是带符号的,在计算机用一个数的最高位存放符号,正数为0,负数为1。

正数7负数-7
原码符号位加上真值的绝对值:00000111符号位加上真值的绝对值:10000111
反码等于原码:00000111原码符号位不变,其余位取反:11111000
补码等于原码:00000111反码的基础上+1:11111001

位运算时,以补码形式进行计算。

2)正数的与、或、异或、非运算

num1 = 17
num2 = 13
print(f"正数与运算: {num1} & {num2}: {num1 & num2:08b}")
print(f"正数或运算: {num1} | {num2}: {num1 | num2:08b}")
print(f"正数异或运算: {num1} ^ {num2}: {num1 ^ num2:08b}")
print(f"非运算: ~{num1}: {~num1:08b}")

3)有负数的与、或运算

num1 = 17
num2 = 13
num3 = -12
print(f"有负数的与运算: {num3} & {num1}: {num1 & num3:08b}")
print(f"有负数的或运算: {num3} | {num1}: {num1 | num3:08b}")

4)按位左移、右移运算

num1 = 17
num2 = -12
offset = 1
print(f"左移运算: {num1} << {offset}: {num1 << offset:08b}")

offset = 2
print(f"左移运算: {num2} << {offset}: {num2 << offset:08b}")

offset = 3
print(f"右移运算: {num1} >> {offset}: {num1 >> offset:08b}")

# 负数右移结果需要向负无穷取整(即"向下取整"),而非简单截断
offset = 3
print(f"右移运算: {num2} >> {offset}: {num2 >> offset:08b}")

3.6.6 成员运算符

运算符说明实例
in在指定的序列中找到值返回 True,否则返回 Falsea in ['a', 'b', 'c']
not in在指定的序列中没有找到值返回 True,否则返回 Falsea not in ['a', 'b', 'c']
# -------------成员运算符---------------
num6 = 1
num7 = 20
test_list = [1, 2, 3, 4, 5]
print(test_list)
print(num6 in test_list)      # True  判断1是不是列表中的成员
print(num7 not in test_list)  # True

3.6.7 身份运算符

运算符说明实例
is判断两个标识符是不是引用自相同对象a is b,类似 id(a) == id(b)。如果引用的是同一个对象则返回 True,否则返回 False
is not判断两个标识符是不是引用自不同对象a is not b,类似 id(a) != id(b)。如果引用的不是同一个对象则返回 True,否则返回 False
# -------------身份运算符---------------
m = 20
n = 20
q = 30
print(m is n)      # True  判断m和n在内存中是否指向同一个地址
print(n is q)      # False
print(n is not q)  # True

# id() 用于获取对象在内存中的地址
print(id(m) == id(n))  # True
print("-" * 30)

# -------------is 和 == 的区别---------------
a = [1, 2, 3]
b = a
print(b is a)   # True
print(b == a)   # True

b = a[:]
print(b)
print(b is a)   # False
print(b == a)   # True

3.6.8 运算符优先级

运算符优先级决定了表达式中运算的先后顺序,优先级高的运算符先执行。以下按从高到低的顺序列出:

优先级运算符说明
1(最高)**幂运算
2~+-按位取反、正号、负号(一元运算符)
3*/%//乘、除、取模、整除
4+-加、减
5>><<右移、左移
6&按位与
7^|按位异或、按位或
8<=<>>=比较运算符
9==!=等于、不等于
10=+=-=*=/=//=%=**=赋值运算符
11isis not身份运算符
12innot in成员运算符
13not逻辑非
14and逻辑与
15(最低)or逻辑或

在实际编程中,建议使用括号来明确运算顺序,提高代码可读性。

3.7 Python 编码规范

随着你编写的程序越来越长,有必要了解一些代码格式设置约定。为确保所有人编写的代码的结构都大致一致,Python 程序员都遵循一些格式设置约定。

PEP 8(Python Enhancement Proposal,PEP)是最古老的 PEP 之一,它向 Python 程序员提供了代码格式设置指南。python.org/dev/peps/pe…

3.7.1 缩进

在 Python 中,代码块的结束不像其他一些编程语言(如 C、Java 等)使用大括号 {} 来明确界定,而是通过缩进来表示。PEP 8 建议每级缩进都使用四个空格,这既可提高可读性,又留下了足够的多级缩进空间。

在文本处理文档中,大家常常使用制表符而不是空格来缩进。对于文本处理文档来说,这样做的效果很好,但混合使用制表符和空格会让 Python 解释器感到迷惑。每款文本编辑器都提供了一种设置,可将输入的制表符转换为指定数量的空格。你在编写代码时应该使用制表符键,但一定要对编辑器进行设置,使其在文档中插入空格而不是制表符。

在程序中混合使用制表符和空格可能导致极难解决的问题。如果你混合使用了制表符和空格,可将文件中所有的制表符转换为空格,大多数编辑器都提供了这样的功能。

3.7.2 行长

很多 Python 程序员都建议每行不超过 80 字符。PEP 8 还建议注释的行长都不超过 72 字符,因为有些工具为大型项目自动生成文档时,会在每行注释开头添加格式化字符。

PEP 8 中有关行长的指南并非不可逾越的红线,有些小组将最大行长设置为 99 字符。在学习期间,你不用过多地考虑代码的行长,但别忘了,协作编写程序时,大家几乎都遵守 PEP 8 指南。

3.7.3 空行

要将程序的不同部分分开,可使用空行。你应该使用空行来组织程序文件,但也不能滥用。空行不会影响代码的运行,但会影响代码的可读性。Python 解释器根据水平缩进情况来解读代码,但不关心垂直间距。

3.7.4 同一行显示多条语句

Python 可以在某些时候同一行中可以使用多条语句,语句之间使用分号 ; 分割,但并不是所有情况都可以,所以不推荐这种写法。

import sys; print(sys.path)  # 没有问题

'''
import sys
for i in sys.path:
    print(i)  # 没有问题
'''

import sys; for i in sys.path:; print(i)  # 报错

3.7.5 分号

建议不要在行尾加分号,也不要使用分号将多条命令放在同一行。

3.7.6 源文件编码

Python 源码请使用 UTF-8 编码(Python2 中可以使用 ASCII 编码)。

文件采用 ASCII(Python2)或者 UTF-8(Python 3)。

3.7.7 不以空格结束一行代码

在任何地方都不要以空格结束本行代码,因为行末的空格不可见,这可能会闹出问题:比如反斜杠(连字符)如果后面接空白字符就不再能够当连字符使用。很多编辑器不允许以空格作为行结束符。