- 0.预备知识
- 1.常见数据类型
- NOTICE
- 1.1数值运算
- NOTICE
- 1.2字符串
- 1.3索引和切片
- 1.4列表
- 1.5元组
- 1.6字典
- 1.7集合
- 2.流程控制
- 2.1 if
- 2.2 while
- 2.3 for与range/zip/enumerate
- 3. 函数
- 4. 输入输出(指标准输入和输出)
- 5. 文件操作
- 6. 包
- 7. 类
- 8. 异常处理
- 理解Python中的变量都是指针/引用
0.预备知识
-
Python中的语句可以直接执行,不需要像C/C++一样写在main函数里。 -
用 #
表示从此开始到行尾都是注释,类似于C/C++中的//
的用法。 -
Python中的数据都是保存在对象中,像123这样的数字也是对象。 -
变量赋值不用事先声明、不用写类型,例如 a = 123
。 -
按C/C++理解,变量都是 object*
类型的指针,所以可以指向任意的对象。 -
数组都是 object*[]
类型,所以可以混着存任意的对象。 -
用 type(x)
函数获取对象类型,用dir(x)
函数获取对象的方法,用id(x)
函数获取对象的ID,其实是对象的地址,类似(size_t)&x
。
1.常见数据类型
|
|
|
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
NOTICE
-
int没有大小限制,可以做任意大的整数运算。 -
float是64位浮点数,相当于C/C++中的double类型。 -
bool类型只有首字母大写的True和False。 -
NoneType是特殊的类型,它只有None这一个值/对象实例,通常被用来表示空值,类似于C++中的nullptr。
1.1数值运算
-
//
是向下取整(负数也是向下取整)。 -
round(-3.9)
就近取整(四舍五入)。 -
=
是基于值做判断的,is
是基于id(地址)判断的。 -
判断不相同一般写作 a is not b
,而不是not a is b
。 -
比较运算可以串联,并且可以串联任意多个: 1<2<3
等价于1<2 and 2<3
。
NOTICE
关于None的判断是用is
和is not
实现的,而非==
和!=
,因为None这个对象是唯一的,只需要根据id判断是否相等,而不是根据值判等。
1.2字符串
-
可以用单引号或者双引号。 -
单引号中的单引号(或者双引号中的双引号)都需要转义,但单引号中的双引号(或者反过来)不需要转义操作。 -
三个单/双引号的字符串可以跨行。 -
字符串操作:(字符串不可变,任何操作都会返回新的字符串对象) -
" ".join(["1", "2", "3"])
,结果是'1 2 3'
,实现了用空格连接上面字符串序列的三个元素。 -
拼接: 'ab' + 'cd' -> 'abcd'
-
重复: 'ab' * 3 -> 'ababab'
-
分割: a.split(b)
,以字符串b为界分割a -
连接: a.join(b)
,以字符串来将字符串序列b中元素连接起来: -
替换: a.replace(b,c)
将字符串a中的b全部替换成c,例如"1,2,3".replace(",","@")
,结果是"1@2@3"
。 -
大小写转化: upper()
和lower()
。 -
字符串转换: -
str(a)
:将a转化为字符串 -
hex(a)
,oct(a)
,bin(a)
:将整数a转化为16、8、2进制字符串 -
int(str,b)
:将字符串str转化为b进制整数 -
float(str)
:将字符串str转化为浮点数 -
Raw字符串:在引号前加上r,表示不将视为转义,在处理windows路径和正则表达式时非常方便。 -
模板字符串:前面加f,在需要用到变量值是非常方便,只需要将变量用 {}
括起来,而且{}
中除了变量名还可以是其他表达式。 -
示例1:
a = 1
b = 2
f"a 的值是 {a},b 的值是 {b}"
# 结果是 'a 的值是 1,b 的值是 2'
- 示例2:
a = 1.2345678
f"a ≈ {a:.3f}"# 保留3位小数(PS:左边字符串里面就是一个普通的约等于号≈)
# 结果是 'a=1.235'
- 示例3:如果想要用到单纯的`{`或`}`字符,需要写两遍标识转义,类似于printf中的`%%`
a = "b"
f" {{ a }} vs {a}"
# 结果是 '{a} vs b'
1.3索引和切片
索引
对于一个有序序列,可以通过索引的方法来访问对应位置的值。字符串便是一个有序序列的例子,Python使用[]
来对有序序列进行索引。索引是从0开始的,索引0对应与序列的第1个元素,当索引值大于最大值时,就会报错。python中还有负索引值,其为从后向前计数。
切片
可以从序列中取出想要的子序列,其用法为:var[lower:upper:step]
,左闭右开,即包括lower,不包括upper;step表示取值的步长。这三个参数可以省略一部分,例如:
-
a[:]
:从头到尾,即创建副本 -
a[1:]
:从1到结尾 -
a[:3]
、a[:-2]
:从0到3、从0到倒数第二 -
a[::-1]
:逆序
1.4列表
在Python中,列表是一个有序的序列。列表用一对[]
生成,中间的元素用,
隔开,其中的元素不需要是同一类型,同时列表的长度也不固定。也可以利用list()
或[]
来生成空的列表。列表的操作同字符串类似,如下:
-
len()
:输出列表的长度 -
+
:拼接 -
*
:重复 -
数组的索引和切片可以读取也可以赋值,用切片赋值自动扩充了列表的长度。
a = [1, 2, 3, 4, 5, 6, 7, 8, 9]
a[5:7] = ["a", "b", "c", "d"] # 把两个元素替换为4个元素
# 结果是[1, 2, 3, 4, 5, 'a', 'b', 'c', 'd', 8, 9]
-
还可以用 del
删除
a = [1, 2, 3, 4, 5, 6, 7, 8, 9]
del a[0:3]
print(a)
# 结果是[4, 5, 6, 7, 8, 9]
-
列表操作 -
l.append(a)
在列表最后加入a,会把任何类型的数据都当成一个整体插入 -
l.extend(a)
如果a是一个序列,相当于将序列中的每个元素依次append -
l.insert(idx,a)
在列表的idx索引处插入a -
l.remove(a)
移除第一次出现的a,不存在会报错 -
测试从属关系: in
-
计数和索引: l.count(a)
返回列表l中a的个数;l.index(a)
返回列表l中a第一次出现的索引位置,不存在会报错(一个AttributeError) -
添加,插入和移除: -
排序和反向: a.sort()
对a原地排序,会改变a中的值;sorted(a)
返回一个新的已经排好序的列表,不改变原有值;a.reverse()
和reversed(a)
表示反向,二者的区别和上面类似。
1.5元组
与列表相似,元组也是个有序序列,可以索引和切片,但是其是不可变的。
-
空元组: ()
或tuple()
-
注意:单元素元组应该写为 (1,)
,以避免和普通括号表达式产生歧义。 -
一般的,元组可以用来作为函数的多返回值,同时也可以用来对多变量进行赋值。元组的计数函数 count()
和查找元素第一次出现的位置index()
。
t = (1, 3, 4, 6, 7, 56, 83, 3)
print(t.count(3), t.index(56))
# 结果是 2 5
w, x, y, z = 1, 2, 3, 4# 1,2,3,4是一个元组,此处括号可以省略
x = 1, 2, 3, 4
print(x, type(x))
print(type((1, 2, 3, 4)))
# 结果是:
# (1, 2, 3, 4) <class 'tuple'>
# <class 'tuple'>
1.6字典
字典是一种由键值对组成的数据结构,可以通过键来访问对应的值。字典是无序的,所以没有索引和切片。
基本操作
-
创建字典:可以通过 {}
或者dict()
来创建空字典,同样也可以在创建时使用key:value
这样的结构来初始化。dict()
函数需要用二元组组成的列表作为参数,比如a = dict([ ("1","a1") , ("2","b2") ])
就是构建了一个键值对为("1"->"a1"
、"2"->"b2")
的字典(也就是字符串“1”(键)对应字符串“a1”(值),另一个同理)。 -
注意: -
字典的键必须是不可变的类型,比如整数,字符串,元组等,而值可以是任意的python对象。 -
一般不使用浮点数来作为键,因为其存在存储精度问题。
a = {"blue": 1, "red": 2}
b = {"white": 3, "black": 4}
c = {"color1": a, "color2": b}
print(c) # 字典的嵌套
a = {1.1: "a", 2.2: "b", 3.3: "c"}
print(a[3.3])
print(a[2.2 + 1.1])
# 上面一个可以输出c但是下面那个出错了,因为2.2+1.1不是3.3(近似是3.3但不是完全相等)
字典方法
-
取值: d.get(key)
,相比于使用d[key]
,其在字典中键不存在是不会报错,而是返回None
。 -
删除元素: d.pop(key)
,删除并返回键为key的键值对,如果没有返回None
。同样可以使用del d[key]
来进行删除。 -
更新字典: d.update(d')
,将字典d'中元素更新到d中。 -
查询字典: a in d
,查询键a是否在字典d中。注意:“不在”一般写作a not in d
而不是not a in d
-
keys
方法:d.keys()
,返回所有键构成的序列。 -
values
方法:d.values()
,返回所有值构成的序列。 -
items
方法:d.items()
,返回所有键值对元组构成的序列。
1.7集合
集合set
是一种无序的序列,故当其中有两个相同的元素,只会保留一个;并且为了保证其中不包含相同元素,放入集合中元素只能是确定性对象。因为无序,所以也没有索引和切片。集合的生成可以通过{}
或者set()
进行创建,但是在创建空集合,只能通过set()
创建,因为{}
表示空字典。
集合操作
-
并: a.union(b)
或者a | b
-
交: a.intersection(b)
或者a & b
-
差: a.difference(b)
或者a - b
;在a中不在b中的元素 -
对称差: a.symmetric_difference(b)
或者a ^ b
;在a或b中,但是不同时在a,b中的元素 -
包含关系: -
判断a是否是b的子集: a.issuperset(b)
或者a <= b
-
判断a是否是b的真子集: a < b
集合方法
-
添加单个元素: s.add(a)
,将a加入集合s -
添加多个元素: s.update(seq)
,将seq中元素都加入集合s -
移除单个元素: s.remove(b)
,将b从集合s中移除,没有即报错
2.流程控制
2.1 if
-
基本结构是 if <条件>:
-
不像C语言一样需要 {}
,而是用缩进来区分层级。 -
elif
是else if
的含义。 -
False
、None
、0
、空字符串、空列表、空字典、空集合,都会被当做False
。 -
因为缩进是必须的,而缩进后的内容又不能为空,所以我们通常写个 pass
,它不会做任何事。在编写代码时,想要暂时先不写某个分支,可以用pass
临时占位。
ifTrue:
pass
2.2 while
基本格式是while <条件>:
,可以用break
跳出,用continue
进入下一次循环。
2.3 for与range/zip/enumerate
-
基本格式是 for <变量> in <可迭代对象>
,可迭代对象如列表、字符串、range
、打开的文件等。 -
range
: -
range(3) -> 0, 1, 2
-
range(1, 5) -> 1, 2, 3, 4
-
range(1, 10, 2) -> 1, 3, 5, 7, 9
,从1开始到10,步长为2 -
range(n)
自动生成从0到n - 1(不包括n)的步长为1的等差数列 -
range
用于创建一串等差数列range(begin,end,step)
,其中部分参数可以省略。 -
同样可以用 break
和continue
。 -
python中的一个编程习惯是用 _
变量表示不使用的值,比如我们想循环3次但不需要循环变量,可以写成下面这样。可选:可以接else
,当循环正常退出而非break
退出时会执行。
a = [1, 2, 3]
for i in a:
if i == 1:
print("a里有1")
break
else:
print("a里没有1")
for _ in range(3):
print(233)
-
zip
: -
zip
用于同时迭代多个可迭代对象(比如列表、元组),迭代次数以最短的为准。 -
假设现在有两个列表 names = ['Alice', 'Bob', 'Candy']
和num = [1,2,3]
,利用zip(names,num)
得到的就是三个二元组组成的一个迭代器,二元组中的第一个位置是names
列表中对应的元素,第二个元素是num
列表中对应位置的元素。
names = ['Alice', 'Bob', 'Charlie']
scores = [80, 90, 75]
for name, score in zip(names, scores):
print(name, score)
-
enumerate
: -
用于同时迭代下标和值。 -
enumerate()
函数会返回一个迭代器,包含每个字符及其对应的索引。
a = "abcdefg"
for i, j in enumerate(a):
print(i, j)
-
列表生成式: -
比for循环更加简洁易懂,并且效率更高。
a = []
for i in range(10):
a.append(i * i)
# 等价于
a = [i * i for i in range(10)] #快速生成需要的列表
- 还可以在列表生成式中加入条件语句。
a = []
for i in range(10):
if i % 2 == 0:
a.append(i * i)
# 等价于
a = [i * i for i in range(10) if i
该文档主要是Python基本知识讲解,涵盖了函数、输入输出、文件操作、包、类、异常处理以及变量引用等多方面内容。以下是转换为Markdown格式后的内容:
3. 函数
-
格式: def 函数名(参数列表):
-
参数列表:直接写变量名称,无需写类型。 -
默认参数:用 =
给定参数默认值,和C++中的默认参数类似。 -
返回值:用 return
返回,返回值可以是任意类型。 -
三种传参模式 -
位置参数(positional arguments):按照函数定义中参数的位置顺序传递参数值。 -
关键字参数(keyword arguments):通过参数的名称来传递参数值,不依赖于参数的位置。 -
按位置或关键字传递参数(positional or keyword arguments):在函数调用时,既可以按照参数在函数定义中的位置传递参数值,也可以使用关键字来传递参数值。 -
假设定义了 complex
函数,参数为real
和imag
,位置是complex(real,imag)
,传递方式complex(3,4)
和complex(real=3,imag=4)
效果相同。 -
在自定义函数时,可用 /
和*
声明参数传递方式。正斜杠/
之前的参数是位置参数;/
和星号*
之间的参数位置或关键字传递均可;星号*
之后的参数必须按关键字传递。例如def fcn_name(a, b, /, c, d, *, e, f)
,a
和b
是位置参数,c
和d
位置或关键字传递都行,e
和f
是关键字参数。 -
设定参数默认值:在函数定义时可给参数设定默认值,调用时可省略有默认值的参数。
defquad(x, a=1, b=0, c=0):
return a * x**2 + b * x + c
print(quad(2.0))
print(quad(2.0, c=3))
# 结果是 4.0 7.0
-
接收不定长参数 -
*args
表示将多余的位置参数作为元组传给args
。
defadd(x, *args):
total = x
for arg in args:
total += arg
return total
print(add(1, 2, 3, 4))
print(add(1, 2))
print(add(1))
# 结果是10 3 1
- `**kwargs`表示将多余的关键字参数作为字典传给`kwargs` 。
defadd(x, **kwargs):
total = x
for arg, value in kwargs.items():
print("adding ", arg)
total += value
return total
print(add(10, y=11, z=12, w=13))
# 结果是:
# adding y
# adding z
# adding w
# 46
-
返回多个值:函数可返回多个值,这些值会自动变成一个元组。通过元组和数组的赋值方式,可将元组中的值对应赋值给各个变量,但两边数目要对应,否则会报错。
deff():
return1, 2, 3
a, b, c = f()
print(a, b, c)
# 结果是 1 2 3
a, b = 1, 2
a, b = (1, 2)
a, b = [1, 2]
a,b,c = 1,2
# 会报错
a = 1,2,3
x,y,z = a
4. 输入输出(指标准输入和输出)
用input
函数获取输入。
a = input("请输入:")
print
格式化输出可使用前面提到的模版字符串,格式化输入可考虑用正则表达式。
5. 文件操作
-
写文本文件:第一个参数是文件路径,第二个参数是打开模式( 'w'
模式覆盖,'a'
模式追加),encoding
参数指定文件编码(常用'utf8'
,中文Windows系统上有时会用'gb2312'
)。
with open("123.txt", "w", encoding="utf8") as f:
f.write("这是一行n")
f.write("这是另一行n")
with open("123.txt", "a", encoding="utf8") as f:
f.write("再给你加一行n")
-
读取文本文件:用 'r'
模式,用encoding
指定文件编码。
with open("123.txt", "r", encoding="utf8") as f:
for i in f:
print(i)
with open("123.txt", "r", encoding="utf8") as f:
a = f.read()
print(a)
f.read()
把文件整体作为一个字符串返回;f.readlines()
返回每一行的字符串的列表。
6. 包
-
导入整个包:
import math
math.sin(math.pi / 4)
可以把导入的包换个名字:
import math as mt
mt.sin(mt.pi/4)
-
导入部分函数:
from math import sin
sin(1)
-
导入多个函数:
from math import sin
from math import cos
或者
from math import sin, cos
cos(1)
-
给导入的函数换个名字:
from math import sin as math_sin
math_sin(1)
-
导入包中的全部内容(不推荐):
from math import *
7. 类
-
基本格式:
classA:
def__init__(self):
self.a = 1
deff(self, x):
self.b = 1
return self.a + x
-
以 __
开头和结尾的是特殊的函数或变量,__init__
函数会在对象创建时执行,类似构造函数。 -
不以 _
或__
开头的函数一般认为是public
的;以下划线开头的函数,一个下划线的是protected
,两个下划线的是private
(有待进一步确认)。 -
非静态类成员函数被调用时,会将类对象作为第一个参数传入,一般用 self
作为参数名。 -
继承:在任何函数中,可通过 self.xxx = xxx
的方式给对象添加新属性。
classA:
def__init__(self, x):
self.x = x
defprint_x(self):
print(self.x)
classB(A):
def__init__(self, y):
super().__init__(233)
self.y = y
defprint_y(self):
print(self.y)
b = B(3)
b.print_y()
super()
会返回所继承的父类,super().__init__()
表示调用父类的__init__
函数。self
指该类构建的对象,自动传入,调用时无需写出。type(x)
可获取对象类型,isinstance(obj,cls)
可判断对象是否继承自某个类。
8. 异常处理
try:
pass
except...:
pass
else:
pass
finally:
pass
-
try
后面接可能会出错的代码。 -
except
后面接要捕获的错误类型,不接等价于except Exception
,能捕获大部分错误类型,里面写错误发生后要执行的代码。 -
else
后面是不出错时执行的代码(可省略)。 -
finally
后面是无论出不出错都会执行的代码(可省略)。 -
用 raise
抛出一个指定类型的错误,还可指定报错反馈信息。
raise ValueError ("报错信息")
-
用 assert
在断言为假时抛出一个AssertionError
类型的错误。
assert1 + 1 == 3, "一加一难道不等于三吗?"
理解Python中的变量都是指针/引用
a = [1, 2, 3]
b = a
deff(b):
b[1] = 100
f(b)
print(b,a)
b[0] = 4
print(a, b)
b = a[:]
或者
b = list(a)
a = [1, 2, 3]
b = a[:]
b[0] = 4
print(a, b)
若列表中包含列表,上述是“浅层”复制,不会复制内部列表。想要深层复制任意对象,用deepcopy
。
from copy import deepcopy
b = deepcopy(a)
原文始发于微信公众号(土拨鼠的安全屋):Python入门基础知识小结
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论