第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)命名规则
- 只能包含字母、数字和下划线,且不能以数字开头。
- 区分大小写,即
Name和name是两个不同的标识符。 - 不要和关键字重复。
- 应既简短又具有描述性。
注意: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 进制
计算机世界中只有二进制,所以计算机中存储和运算的所有数据都要转为二进制。包括数字、字符、图片、声音、视频等。常见的进制:
- 二进制:0、1,满2进1。
- 八进制:0-7,满8进1。
- 十进制:0-9,满10进1。
- 十六进制:0-9 及 A-F,满16进1。十六进制中,除了 0 到 9 十个数字外,还引入了字母,以便表示超过9的值。字母 A 对应十进制的10,字母 B 对应十进制的11,字母 C、D、E、F 分别对应十进制的 12、13、14、15。
| 二进制 | 八进制 | 十进制 | 十六进制 |
|---|---|---|---|
| 0 | 0 | 0 | 0 |
| 1 | 1 | 1 | 1 |
| 10 | 2 | 2 | 2 |
| 11 | 3 | 3 | 3 |
| 100 | 4 | 4 | 4 |
| 101 | 5 | 5 | 5 |
| 110 | 6 | 6 | 6 |
| 111 | 7 | 7 | 7 |
| 1000 | 10 | 8 | 8 |
| 1001 | 11 | 9 | 9 |
| 1010 | 12 | 10 | A |
| 1011 | 13 | 11 | B |
| 1100 | 14 | 12 | C |
| 1101 | 15 | 13 | D |
| 1110 | 16 | 14 | E |
| 1111 | 17 | 15 | F |
| 10000 | 20 | 16 | 10 |
| 10001 | 21 | 17 | 11 |
3.3.2 不同进制表示整数
- 二进制:以
0b或0B开头表示。 - 八进制:以
0o开头表示。 - 十进制:正常数字表示。
- 十六进制:以
0x或0X开头表示,此处的 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位 |
|---|---|---|---|---|
| 二进制数字 | 1 | 0 | 1 | 1 |
| 计算 | 1×2³ | 0×2² | 1×2¹ | 1×2⁰ |
| 结果 | 8 | 0 | 2 | 1 |
对应十进制数字:8 + 0 + 2 + 1 = 11
3.3.4 十进制转换成二进制
规则:将该数不断除以2,直到商为0为止,然后将每步得到的余数倒过来,就是对应的二进制。
案例:请将 56 转成二进制。
| 步骤 | 除以2 | 商 | 余数 |
|---|---|---|---|
| 56 ÷ 2 | 28 | 0 | |
| 28 ÷ 2 | 14 | 0 | |
| 14 ÷ 2 | 7 | 0 | |
| 7 ÷ 2 | 3 | 1 | |
| 3 ÷ 2 | 1 | 1 | |
| 1 ÷ 2 | 0 | 1 |
56 对应的二进制数字为:111000
3.3.5 十六进制转换成十进制
规则:从最低位开始,将每个位上的数提取出来,乘以16的(位数-1)次方,然后求和。
案例:请将 0x34A 转成十进制的数。
| 十六进制数字 | 3 | 4 | A |
|---|---|---|---|
| 计算 | 3×16² | 4×16¹ | 10×16⁰ |
| 结果 | 768 | 64 | 10 |
对应十进制数字:768 + 64 + 10 = 842
如果是8进制转换为10进制,就乘以8的(位数-1)次方,然后求和。
3.3.6 十进制转换成十六进制
规则:将该数不断除以16,直到商为0为止,然后将每步得到的余数倒过来,就是对应的十六进制。
案例:请将 356 转成十六进制。
| 步骤 | 商 | 余数 |
|---|---|---|
| 356 ÷ 16 | 22 | 4 |
| 22 ÷ 16 | 1 | 6 |
| 1 ÷ 16 | 0 | 1 |
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_000 与 1000000000000000 没什么不同。这种表示法适用于整数和浮点数,但只有 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 布尔型
布尔型变量只有 True 和 False,用于真假的判断。
bool1 = True
bool2 = False
print(bool1, bool2) # True False
Python3 中,bool 是 int 的子类,True 和 False 可以和数字相加。True==1、False==0 会返回 True。
is 运算符用于比较两个对象的身份(即它们是否是同一个对象,是否在内存中占据相同的位置),而不是比较它们的值。
print(True == 1) # True
print(False == 0) # True
print(True is 1) # False
print(False is 0) # False
在 Python 中,能够解释为假的值不只有 False,还有:
None00.0False- 所有的空容器(空列表、空元组、空字典、空集合、空字符串)
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,否则返回 False | a in ['a', 'b', 'c'] |
not in | 在指定的序列中没有找到值返回 True,否则返回 False | a 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 | =、+=、-=、*=、/=、//=、%=、**= | 赋值运算符 |
| 11 | is、is not | 身份运算符 |
| 12 | in、not in | 成员运算符 |
| 13 | not | 逻辑非 |
| 14 | and | 逻辑与 |
| 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 不以空格结束一行代码
在任何地方都不要以空格结束本行代码,因为行末的空格不可见,这可能会闹出问题:比如反斜杠(连字符)如果后面接空白字符就不再能够当连字符使用。很多编辑器不允许以空格作为行结束符。