本文仅讲解 Python 基础语法。
Python
Python 是一种解释型、面向对象、动态数据类型的高级程序设计语言。
Python 由 Guido van Rossum 于 1989 年底发明,第一个公开发行版发行于 1991 年。
语言优点
人生苦短,我用 Python。
- 易于学习:Python 有相对较少的关键字,结构简单,和一个明确定义的语法,学习起来更加简单。
- 易于阅读:Python 代码定义的更清晰。
- 易于维护:Python 的成功在于它的源代码是相当容易维护的。
- 一个广泛的标准库:Python 的最大的优势之一是丰富的库,跨平台的,在 UNIX,Windows 和 Macintosh 兼容很好。
- 互动模式:互动模式的支持,您可以从终端输入执行代码并获得结果的语言,互动的测试和调试代码片断。
- 可移植:基于其开放源代码的特性,Python 已经被移植(也就是使其工作)到许多平台。
- 可扩展:如果你需要一段运行很快的关键代码,或者是想要编写一些不愿开放的算法,你可以使用 C 或 C++ 完成那部分程序,然后从你的 Python 程序中调用。
- 数据库:Python 提供所有主要的商业数据库的接口。
- GUI 编程:Python 支持 GUI 可以创建和移植到许多系统调用。
- 可嵌入: 你可以将 Python 嵌入到 C/C++ 程序,让你的程序的用户获得"脚本化"的能力。
语言缺点
- 运行效率较低。如果你对速度有要求的话,还是需要用 C++ 改写关键部分吧。
- 国内市场较小。
- 中文资料匮乏。尽管有一些优秀的教材已经被翻译了,但大多都是入门级教材,高级内容还是只能看英语版。
- 构架选择太多。
环境安装(Windows)
访问官方下载地址,下载并安装。
你可以开始菜单打开 Python3 IDLE,新建一个 .py
文件,在其中写下你的脚本,按 F5
运行。
你也可以使用编辑器先写好 xxx.py
,然后在命令行中输入 python xxx.py
运行该脚本。
基础语法
由于作者本人主要使用 C++,本文部分讲解可能更照顾 C++ 使用者,但并不妨碍其他语言使用者正常理解。
本文主要讲解 Python 3,部分代码可能无法在 Python 2 下运行。
原始数据类型和运算符
数字
Python 仅支持三种不同的数字类型:int
,float
,complex
,但是它们足以支持你将用到的所有计算。
10 # int (有符号整形)
15.20 # float (浮点型)
3.14j # complex (复数)
常规运算
加法、减法、乘法和模除并没有什么特别的。
1 + 1 # => 2
3 - 2 # => 1
4 * 5 # => 20
7 % 3 # => 1
3 * 2.0 # => 6.0 浮点数的运算结果也是浮点数
(1 + 3) * 2 # => 8
除法会自动转换成浮点数。
40 / 8 # => 5.0
2 / 3 # => 0.6666666666666667
整数除法的结果向下取整。
float
也可以参与整数除法运算。
5 // 3 # => 1
5.0 // 3.0 # => 1.0
-5 // 3 # => -2
-5.0 // 3.0 # => -2.0
还有 C++ 没有的乘方。
2**3 # => 8
逻辑运算
布尔值为 True
和 False
,注意开头大写。
not
取非。
not True # => False
not False # => True
逻辑运算使用 and
和 or
。
True and False # => False
False or True # => True
整数也可以当做布尔值。
0 and 2 #=> 0
-5 or 0 #=> -5
0 == False #=> True
2 == True #=> False
1 == True #=> True
用 ==
判断相等,用 !=
判断不等,这与 C++ 没有区别。
1 == 1 # => True
2 == 1 # => False
1 != 1 # => False
2 != 1 # => True
比较大小,这也没有什么特别的。
1 < 10 # => True
1 > 10 # => False
2 <= 2 # => True
2 >= 2 # => True
但是在 Python 中,大小比较是可以连起来的。
1 < 2 < 3 # => True
2 < 3 < 2 # => False
字符串
字符串用 '
或 "
都可以。
"这是个字符串"
'这也是个字符串'
字符串可以直接相加。
"Hello " + "world!" # => "Hello world!"
字符串可以被当做字符列表(与 C++ 的字符数组相似)。
"This is a string"[1] # => 'h'
使用 .format
格式化字符串。
用后面括号内的内容去替换前面字符串中 {}
的位置。
"{} can be {}".format("strings", "interpolated")
可以重复参数以节省时间。
即用后面括号内的第一项去替换前面 {0}
的位置,第二项去替换前面 {1}
的位置……
"{0} be nimble, {0} be quick, {0} jump over the {1}".format("Jack", "candle stick")
# => "Jack be nimble, Jack be quick, Jack jump over the candle stick"
如果你觉得参数并不好记,也可以用关键字。
"{name} wants to eat {food}".format(name="Bob", food="lasagna")
# => "Bob wants to eat lasagna"
特殊
None
是一个对象。
None # => None
当尝试与 None
进行比较时不应使用 ==
,要用 is
,is
用来比较两个变量是否指向同一个对象。
"etc" is None # => False
None is None # => True
注意 None
,0
,空字符串,空列表,空字典都算是 False
;除此以外的所有值都为 True
。
bool(0) # => False
bool("") # => False
bool([]) # => False
bool({}) # => False
变量和集合
变量
在给变量赋值前不用提前声明。
注意 Python 同样对大小写敏感。
(本文中所有变量名均采用骆驼式命名法命名。这种命名方法在许多新的函数库以及 Microsoft Windows 等环境中使用的相当多,本人较为推荐。)
someVar = 5
someVar # => 5
访问未赋值的变量会抛出异常。
someUnknownVar # 抛出异常 NameError
列表
在 Python 中使用列表(list)存储序列。
li = []
otherLi = [4, 5, 6]
用 append
在列表最后插入元素。
li.append(1) # li = [1]
li.append(2) # li = [1, 2]
li.append(4) # li = [1, 2, 4]
li.append(3) # li = [1, 2, 4, 3]
li.append(5) # li = [1, 2, 4, 3, 5]
用 pop
删除列表尾部的元素。
li.pop() # [1, 2, 4, 3]
列表存储与 C++ 的数组完全相同,特别的,下标 -1
表示最后一个元素。
li[0] # => 1
li[-1] # => 3
li[4] # 抛出 IndexError
列表有切割语法。
切割语法形如 list[l:r:step]
,即从 list[l]
开始,每隔 step
个元素取一个,一直取到 r
为止。
li[1:3] # => [2, 4] 取li[1]~li[3]
li[2:] # => [4, 3] 取最后面的2个元素
li[:3] # => [1, 2, 4] 取最前面的3个元素
li[::2] # => [1, 4] 每隔2个元素取一下
li[::-1] # => [3, 4, 2, 1] 倒过来(每隔-1个元素取一下)
用 del
可以删除列表中的任意元素。
del li[2] # => [1, 2, 3]
列表可以相加,规则与字符串类似。
li + otherLi # => [1, 2, 3, 4, 5, 6]
用 extend
拼接列表。
li.extend(otherLi) # li = [1, 2, 3, 4, 5, 6]
用 in
查找列表中是否含有某元素。
1 in li # => True
用 len
取列表长度。
len(li) # => 6
元组
元组是不可改变的序列。
除不可改变这一性质外,其余均与列表完全相同。
tup = (1, 2, 3)
tup[0] # => 1
tup[0] = 3 # 抛出 TypeError
len(tup) # => 3
tup + (4, 5, 6) # => (1, 2, 3, 4, 5, 6)
tup[:2] # => (1, 2)
2 in tup # => True
特别的,你可以对元组进行解包,赋值给变量。
元组周围的括号是可以省略的。
a, b, c = (1, 2, 3)
d, e, f = 4, 5, 6
e, d = d, e # 交换两个元素
字典
用字典存储映射关系,与 C++ 的 std::map
类似。
emptyDict = {}
filledDict = {"one": 1, "two": 2, "three": 3}
同样字典也可以使用 []
取值。
filledDict["one"] # => 1
filledDict["four"] # 抛出 KeyError
用 keys
可以一次性获得所有的键,用 values
可以一次性获得所有的值。
keys
和 values
将会返回一个可迭代对象,这里直接将其包在 list
中,就可以获得一个存有所有键/值的 list
。
注意上述函数返回键/值的顺序可能并不固定,你可能会得到各种不同的排列(可能与下面不同)。
list(filledDict.keys()) # => ["one", "two", "three"]
list(filledDict.values()) # => [1, 2, 3]
可以使用 in
查询字典中是否包含某个键。
"one" in filledDict # => True
1 in filledDict # => False
我们可以使用 get
来在字典中查找某个键对应的值。
与直接使用 []
不同的是,这个操作访问不存在的键时会返回 None
而不是抛出异常 KeyError
。
filledDict.get("one") # => 1
filledDict.get("four") # => None
# 可以在函数的第二项加入一个默认值,使得键不存在时返回该默认值
filledDict.get("one",4) # => 1
filledDict.get("four",r) # => 4
可以直接使用字典赋值的方式插入新值。
filledDict.update({"four": 4}) # filledDict = {"one": 1, "two": 2, "three": 3, "four": 4}
filledDict["four"] = 4 # 另一种赋值方法
可以使用 setdefault
在键不存在时插入新值。
filledDict.setdefault("five", 5) # filledDict["five"] = 5
filledDict.setdefault("five", 6) # filledDict["five"] = 5
用 del
删除一对键值。
del filled_dict["one"] # filledDict = {"two": 2, "three": 3, "four": 4}
集合
用 set
表示集合,与 C++ 的 std::set
类似,自动去重。
emptySet = set()
someSet = {1, 3, 2, 4, 3, 4} # someSet = {1, 2, 3, 4}
集合也可以直接赋值。
filledSet = someSet
使用 add
在集合中增加元素。
filledSet.add(5) # filledSet = {1, 2, 3, 4, 5}
使用 &
取交集,|
取并集,-
取补集。
otherSet = {3, 4, 5, 6}
filledSet & otherSet # => {3, 4, 5}
filledSet | otherSet # => {1, 2, 3, 4, 5, 6}
{1, 2, 3, 4} - {2, 3, 5} # => {1, 4}
同样也可以使用 in
来判断集合是否包含某元素。
2 in filledSet # => True
9 in filledSet # => False
流程控制与迭代器
请注意缩进在 Python 里是有含义的。
if
if
语句与 C++ 并没有大的区别。
其中 elif = else if
。
在 if
或 elif
与 :
之间的逻辑表达式即为 if
判断的标准。
var = 5
if var > 10:
print("var is bigger than 10")
elif var < 10:
print("var is smaller than 10")
else:
print("var is 10")
for
正常的 for
语句应该这样写。
其中 range(num)
返回 $[0,num)$ 区间内的所有数字。
也可以使用 range(l, r)
返回 $[l,r)$ 区间内的所有数字。
for number in range(4):
print("{} is a number".format(number))
遍历列表的写法则是这样。
for number in ["one", "two", "three"]:
print("{} is a number".format(number))
while
while
后的逻辑表达式与 if
相同。
这里展示的是前两例的 while
写法实现。
val = 0
while val < 4:
print("{} is a number".format(val))
val += 1 # 不要习惯性写 val++
pass
pass
语句本身无含义,仅作占位语句用。
比如如果你希望写一个空循环。
for i in range(1, 10):
但这样会显示编译错误,你应该写成这样。
for i in range(1, 10):
pass
这样就写出了一个空循环。
try/except
在下面这段脚本运行时你可以从控制台窗口上看到关于 KeyError
的报错提醒。
dict = {"one": 1}
dict["two"] # => KeyError
这是因为我们的字典访问到了不存在的键,抛出了 KeyError
,并让进程强制结束。
这时我们可以使用 try/except
块捕捉异常。
- 如果
try
后的语句执行时发生异常,python 就跳回到try
并执行第一个匹配该异常的except
子句,异常处理完毕,控制流就通过整个try
语句(除非在处理异常时又引发新的异常)。 - 如果在
try
后的语句里发生了异常,却没有匹配的except
子句,异常将被递交到上层的try
,或者到程序的最上层(这样将结束程序,并打印默认的报错信息)。 - 如果在
try
子句执行时没有发生异常,python 将执行else
语句后的语句(如果存在),然后控制流通过整个try
语句。
try:
dict["two"] # 抛出 KeyError
except KeyError: # 如果捕捉到 KeyError
print("KeyError")
except IndexError: # 如果捕捉到 IndexError
pass
else: # 如果没有捕捉到异常
print("all ok")
try
也可以同时对应多个 expect
。
并且每个 expect
语句也可同时捕捉多个异常。
try:
dict["two"]
except KeyError:
print("KeyError")
except IndexError:
pass
except (NameError, IOError): # 同时捕捉 NameError 和 IOError
print("Error")
else:
print("all ok")
try-finally
try-finally
语句无论是否发生异常都将执行最后的代码。
特别的,try-finally
语句并不会过滤掉异常,在该语句块结束后异常依旧会返回外层。
try:
fh = open("testfile", "w") # 尝试打开文件
try:
fh.write("这是一个测试文件,用于测试异常!!") # 尝试写入
finally: # 发生了异常,但是依旧执行下面的语句
print("关闭文件")
fh.close()
except IOError: # 第4行语句抛出的异常在此处被捕捉
print("Error: 没有找到文件或读取文件失败")
iterable
Python 提供可迭代对象,一个可迭代对象是可以被当作序列的对象。比如说上面range
返回的对象就是可迭代的。
filledDict = {"one": 1, "two": 2, "three": 3}
ourIterable = filledDict.keys()
print(ourIterable)
以下为输出。
dict_keys(['one', 'two', 'three'])
可迭代对象是可以遍历的。
for i in ourIterable:
print(i) # 打印 one two three
但是可迭代对象并不支持随机访问。
ourIterable[1] # 抛出 TypeError
iterator
我们可以使用可迭代对象生成迭代器。
ourIterator = iter(ourIterable)
此处的迭代器定义与 C++ 相似,类似于指针。
使用 __next__
可以取得下一个元素。
ourIterator.__next__() # => "one"
ourIterator.__next__() # => "two"
ourIterator.__next__() # => "three"
ourIterator.__next__() # 抛出 StopIteration
我们可以使用 list
一次性取出迭代器中的所有元素。
for i in list(ourIterator):
print(i)
函数
函数是这样定义的。
def add(a, b):
print("{} + {} = {}".format(a, b, a + b))
return a + b
我们可以通过关键字参数来调用函数。
add(5, 6)
add(b=3, a=2) # 等价于 add(2, 3)
我们可以通过 *
定义可变参函数。
def func(*a):
return a
print(func(3, 1, 2, 4))
输出
(3, 1, 2, 4)
我们可以通过 **
定义关键字可变参数函数。
def func(**a):
return a
print(func(a="1", b="2"))
输出
{'a': '1', 'b': '2'}
也可以把两个混起来用。
def func(*a, **b):
print(a)
print(b)
return
print(func(1, 2, 3, x=6, y=7))
输出
(1, 2, 3)
{'x': 6, 'y': 7}
None
调用可变参数函数是可以用与上面相同的符号展开序列、字典。
def func(*a, **b):
print(a)
print(b)
return
a = (1, 2, 3, 4)
b = {"x": 6, "y": 7}
func(*a)
func(**b)
func(*a, **b)
输出
(1, 2, 3, 4)
{}
()
{'x': 6, 'y': 7}
(1, 2, 3, 4)
{'x': 6, 'y': 7}
Python 的函数中也有局部变量一说。
x = 1
def func(y):
x = y
print(x)
return
func(3)
print(x)
输出
3
1
我们可以使用 global
关键字将全局变量作用域引入函数,类似于 C++ 的 ::
运算符。
x = 1
def func(y):
global x
x = y
print(x)
return
func(3)
print(x)
输出
3
3
在 Python 中,也可以使用类似于函数指针的方法传递函数。不过由于这里不需要申明变量类型,显得十分简洁。
def func(x, y):
def add(x, y):
return x + y
print(add(x, y))
return add
func2 = func(1, 2)
print(func2(3, 4))
输出
3
7
也有匿名函数,与 C++11 中的 lambda
表达式很相似。
print((lambda x, y: x + y)(1, 2))
合理使用匿名函数可以有效减短代码长度压行。
map(lambda x: x + 10, [1, 2, 3]) # => [11, 12, 13]
filter(lambda x: x > 5, [3, 4, 5, 6, 7]) # => [6, 7]
将函数带入列表推导式可以简化映射和过滤。
[(lambda i: i + 10)(i) for i in [1, 2, 3]] # => [11, 12, 13]
[x for x in [3, 4, 5, 6, 7] if x > 5] # => [6, 7]
高阶
如果你读到了这里,那么恭喜你已经掌握了 Python 的基础语法。你已经拥有用 Python 写常规小程序的能力了。
关于 Python 的高阶操作,可以看以下教程或是在网上参阅相关资料。
作者将会努力为大家提供更多的 Python 高阶教程。
CYaRon(咕)
CYaRon 是一个可以帮助你快速生成随机数据的工具库,目标是帮 OIer 在 5 分钟内快速生成一组测试数据。
如果你想要出题,想必 CYaRon 是你造数据的不二之选。
参考:
1. https://learnxinyminutes.com/docs/python/
2. https://www.runoob.com/python/python-tutorial.html
3. https://github.com/luogu-dev/cyaron/wiki/Python-30%E5%88%86%E9%92%9F%E5%85%A5%E9%97%A8%E6%8C%87%E5%8D%97
如果有人想看 CYaRon 的介绍的话可以评论,我可能会赶工写完。
Comments | 3 条评论
博主 youyukyc
该评论为私密评论
博主 youyukyc
相信大佬讲的CYaRon会更通俗易懂
(=・ω・=)
博主 Macesuted Kysic
@youyukyc 主要感觉 CYaRon 官方文档已经写得非常详细了,也不知道写些什么了