Python语言的语法相当强大,表现力强。因此,用Python来表达算法是很简洁的。也许这就是它在机器学习中受欢迎的原因,因为我们在开发机器学习模型时需要做很多实验。
如果你是Python的新手,但有其他编程语言的经验,你有时会发现Python的语法可以理解,但很奇怪。如果你以前是用C++或Java写的,而现在过渡到Python,很可能你的程序不是Pythonic。
在本教程中,我们将介绍Python中几个常见的语言特征,它们区别于其他编程语言。
教程概述
本教程分为两部分;它们是:
- 操作员
- 内置数据结构
- 特殊变量
- 内置函数
操作符
在Python中使用的大多数运算符与其他语言相同。优先级表如下,
| 操作符 | 说明 | |
|---|---|---|
| (expressions...), [expressions...], {key: value...}, {expressions...} | 绑定或括号内的表达式,列表显示,字典显示,集合显示 | |
| x[index], x[index:index], x(arguments...), x.属性 | 订阅,分片,调用,属性引用 | |
| 等待x | 等待表达式 | |
| ** | 指数化 | |
| +x, -x, ~x | 正数、负数、位数 NOT | |
| *, @, /, //, % | 乘法、矩阵乘法、除法、底层除法、余数 | |
| +, - | 加法和减法 | |
| <<, >> | 移位 | |
| & | 位数和 | |
| 位数XOR | ||
| 位法OR | ||
| in, not in, is, is not, <, <=, >, >=, !=, == | 比较,包括成员测试和身份测试 | |
| 非X | 布尔型非 | |
| 和 | 布尔和 | |
| 或 | 布尔型或 | |
| if - else | 条件性表达式 | |
| lambda | 兰姆达表达式 | |
| := | 赋值表达式 |
与其他语言的一些关键区别。
- 布尔运算符是拼出来的,而位运算符是字符
&,^和| - 指数使用
2**3 - 整数除法使用
//,除法/,总是给你浮点值。 - 的运算符。如果你熟悉C语言中的表达式
(x)?a:b,我们在Python中写成a if x else b - 比较两个东西是否相等,可以使用
==或is。==运算符与其他语言中的相等相同,但is更为严格,保留给两个变量是否指向同一个对象。
在Python中,我们允许在比较运算符中进行连接。例如,要测试一个值是否在-1和+1之间,我们可以做
if value > -1 and value < 1:
...
但我们也可以做
if -1 < value < 1:
...
内置数据结构
和其他许多语言一样,在Python中我们有整数和浮点数据类型。但也有复数 (例如:3+1j)、作为常量的布尔类型 (True 和False)、字符串,以及一个虚拟类型。None
但是Python作为一种语言的力量在于它有内置的容器类型:Python数组被称为 "list",它会自动展开,关联数组(或哈希表)被称为 "dict"。我们还有作为只读列表的 "元组",以及作为唯一项目容器的 "集合"。以C++为例,你将需要STL来给你提供这些功能。
在Python中,"dict "数据结构可能是最强大的,它给我们编写代码带来了一些便利。例如,在狗和猫的图像分类问题中,我们的机器学习模型可能只给你一个0或1的值,如果你想打印名字,我们可以做到。
value = 0 # This is obtained from a model
value_to_name = {0: "cat", 1: "dog"}
print("Result is %s" % value_to_name[value])
Result is cat
在这种情况下,我们利用dictvalue_to_name 作为查询表。同样地,我们也可以利用dict来建立一个计数器。
sentence = "Portez ce vieux whisky au juge blond qui fume"
counter = {}
for char in sentence:
if char not in counter:
counter[char] = 0
counter[char] += 1
print(counter)
{'P': 1, 'o': 2, 'r': 1, 't': 1, 'e': 5, 'z': 1, ' ': 8, 'c': 1, 'v': 1, 'i': 3, 'u': 5, 'x': 1, 'w': 1, 'h': 1, 's': 1, 'k': 1, 'y': 1, 'a': 1, 'j': 1, 'g': 1, 'b': 1, 'l': 1, 'n': 1, 'd': 1, 'q': 1, 'f': 1, 'm': 1}
这将建立一个名为counter 的 dict,将每个字符映射到句子中的出现次数。
Python list 也有强大的语法。与其它一些语言不同,我们可以把任何东西放入一个列表中。
A = [1, 2, "fizz", 4, "buzz", "fizz", 7]
A += [8, "fizz", "buzz", 11, "fizz", 13, 14, "fizzbuzz"]
print(A)
[1, 2, 'fizz', 4, 'buzz', 'fizz', 7, 8, 'fizz', 'buzz', 11, 'fizz', 13, 14, 'fizzbuzz']
并且我们可以使用+ 来连接列表。在上面的例子中,我们使用+= 来扩展列表A 。
Python 列表有切片语法。例如上面的A ,我们可以让A[1:3] 表示元素 1 和 2,即[2, "fizz"] 和A[1:1] 是一个空列表。事实上,我们可以给一个片断分配一些东西来插入或删除一些元素。例如。
...
A[2:2] = [2.1, 2.2]
print(A)
[1, 2, 2.1, 2.2, 'fizz', 4, 'buzz', 'fizz', 7, 8, 'fizz', 'buzz', 11, 'fizz', 13, 14, 'fizzbuzz']
而后
...
A[0:2] = []
print(A)
[2.1, 2.2, 'fizz', 4, 'buzz', 'fizz', 7, 8, 'fizz', 'buzz', 11, 'fizz', 13, 14, 'fizzbuzz']
Tuple的语法与list相似,只是它是用小括号定义的。
A = ("foo", "bar")
Tuple是不可变的。这意味着一旦它被定义,你就不能修改它。在 Python 中,如果你把几个东西放在一起,用逗号互相分开,就可以认为是一个元组。这样做的意义在于,我们可以用一种非常简洁的语法交换两个变量。
a = 42
b = "foo"
print("a is %s; b is %s" % (a,b))
a, b = b, a # swap
print("After swap, a is %s; b is %s" % (a,b))
a is 42; b is foo
After swap, a is foo; b is 42
最后,正如你在上面的例子中所看到的,Python 字符串支持即时的替换。通过与C语言中printf() 函数类似的模板语法,我们可以用%s 来替换一个字符串,或者用%d 来替换一个整数。我们还可以使用%.3f 来替换一个有3位小数的浮点数。下面是一个例子。
template = "Square root of %d is %.3f"
n = 10
answer = template % (n, n**0.5)
print(answer)
Square root of 10 is 3.162
但这只是众多方法中的一种。上述情况也可以用f-string和format()方法实现。
特殊变量
Python 有几个预定义的 "特殊变量"。__name__ 告诉你当前的名字空间,__file__ 告诉你脚本的文件名。更多的变量将在对象中找到,但几乎所有的变量都不应该被直接正常使用。作为一种惯例(也就是说,只是一种习惯,但没有人阻止你这样做),我们用下划线或双下划线作为前缀来命名内部变量(顺便说一下,双下划线被一些人读作 "dunder")。如果你来自C++或Java,这些相当于一个类的私有成员,尽管它们在技术上不是私有的。
有一个值得注意的 "特殊 "变量,你可能经常在 Python 代码中看到_ ,只是一个下划线字符。按照惯例,它是指一个我们不关心的变量。如果你不关心,为什么还需要一个变量呢?这是因为有时你持有一个函数的返回值。例如,在pandas中,我们可以扫描一个数据框架的每一行。
import pandas as pd
A = pd.DataFrame([[1,2,3],[2,3,4],[3,4,5],[5,6,7]], columns=["x","y","z"])
print(A)
for _, row in A.iterrows():
print(row["z"])
x y z
0 1 2 3
1 2 3 4
2 3 4 5
3 5 6 7
3
4
5
7
在上面,我们可以看到数据框架有三列 "x"、"y "和 "z",行的索引是0到3。如果我们调用A.iterrows() ,它会给我们一个索引和一个行,但是我们并不关心索引的问题。我们可以直接创建一个新的变量来保存它,但不使用它。为了明确我们不打算使用它,我们使用_ 作为保存索引的变量,而行则存储在变量row 。
内置函数
在Python中,有一小部分函数被定义为内置函数,而其他功能则在其他软件包中提供。
abs()
aiter()
all()
any()
anext()
ascii()
bin()
bool()
breakpoint()
bytearray()
bytes()
callable()
chr()
classmethod()
compile()
complex()
delattr()
dict()
dir()
divmod()
enumerate()
eval()
exec()
filter()
float()
format()
frozenset()
getattr()
globals()
hasattr()
hash()
help()
hex()
id()
input()
int()
isinstance()
issubclass()
iter()
len()
list()
locals()
map()
max()
memoryview()
min()
next()
object()
oct()
open()
ord()
pow()
print()
property()
range()
repr()
reversed()
round()
set()
setattr()
slice()
sorted()
staticmethod()
str()
sum()
super()
tuple()
type()
vars()
zip()
__import__()
并非所有的函数都是每天使用的,但有些是特别值得注意的。
zip() 允许你将多个列表组合在一起。例如
a = ["x", "y", "z"]
b = [3, 5, 7, 9]
c = [2.1, 2.5, 2.9]
for x in zip(a, b, c):
print(x)
('x', 3, 2.1)
('y', 5, 2.5)
('z', 7, 2.9)
如果你想 "透视 "一个列表,它是很方便的,例如
a = [['x', 3, 2.1], ['y', 5, 2.5], ['z', 7, 2.9]]
p,q,r = zip(*a)
print(p)
print(q)
print(r)
('x', 'y', 'z')
(3, 5, 7)
(2.1, 2.5, 2.9)
enumerate() 是很方便的,让你对一个列表中的项目进行编号,例如。
a = ["quick", "brown", "fox", "jumps", "over"]
for num, item in enumerate(a):
print("item %d is %s" % (num, item))
item 0 is quick
item 1 is brown
item 2 is fox
item 3 is jumps
item 4 is over
如果你不使用enumerate ,这就相当于下面的情况。
a = ["quick", "brown", "fox", "jumps", "over"]
for num in range(len(a)):
print("item %d is %s" % (num, a[num]))
与其他语言相比,Python 中的 for 循环是在一个预定义的范围内迭代,而不是在每次迭代中计算数值。换句话说,与下面的 C for 循环不存在直接的等价关系。
for (i=0; i<100; ++i) {
...
}
而在 Python 中,我们必须使用range() 来做同样的事情。
for i in range(100):
...
在类似的意义上,有一些函数可以操作列表(或类似列表的数据结构,Python称之为 "iterables")。
max(a):要找到列表中的最大值amin(a):寻找列表中的最小值asum(a):找出列表中的数值之和areverse(a):从列表中迭代a,从后面迭代。sorted(a):返回 list 的副本a,其中的元素按排序顺序排列。
总结
在本教程中,你发现了Python的一些与众不同的特点。具体来说,你学到了
- Python 所提供的运算符
- 一些内置数据结构的使用
- 一些经常使用的内置函数,以及为什么它们是有用的