python编程语言

基本数据类型

除法/总是得到浮点数

1
8 / 5 # 1.6

除法//去掉小数部分

1
8 // 5 # 1

幂次运算使用**

1
5 ** 2 # 25

字符串使用单引号或者双引号标注,反斜杠\用于转义。如果不希望前置 \ 的字符转义成特殊字符,可以使用 原始字符串,在引号前添加 r 即可

1
2
3
"doesn't"
'"Yes," they said.'
r'C:\some\name'

字符串字面值可以实现跨行连续输入。实现方式是用三引号:”””…””” 或 ‘’’…’’’,字符串行尾会自动加上回车换行,如果不需要回车换行,在行尾添加 \ 即可。

1
2
3
4
5
print("""\
Usage: thingy [OPTIONS]
-h Display this usage message
-H hostname Hostname to connect to\
""")

字符串可以用 + 合并(粘到一起),也可以用 * 重复

1
3 * 'un' + 'ium'

相邻的两个或多个 字符串字面值 (引号标注的字符)会自动合并

1
'Py' 'thon'

字符串支持 索引 (下标访问),第一个字符的索引是 0。单字符没有专用的类型,就是长度为一的字符串

1
2
3
word = 'Python'
word[0] # 'P'
word[5] # 'n'

索引还支持负数,用负数索引时,从右边开始计数

1
2
3
word = 'Python'
word[-1] # 'n'
word[-2] # 'o'

除了索引,字符串还支持 切片。索引可以提取单个字符,切片则提取子字符串。输出结果包含切片开始,但不包含切片结束。因此,s[:i] + s[i:] 总是等于 s

1
2
3
word = 'Python'
word[:2] # 'Py'从开始到位置2(不包括)
word[4:] # 'on'从位置4(包括)到结束

流程控制

Python 的 for 语句不迭代算术递增数值,或是给予用户定义迭代步骤和暂停条件的能力,而是迭代列表或字符串等任意序列,元素的迭代顺序与在序列中出现的顺序一致。

1
2
3
words = ['cat', 'window', 'defenestrate']
for w in words:
print(w, len(w))

内置函数 range() 常用于遍历数字序列,该函数可以生成算术级数,生成的序列不包含给定的终止数值;range(10) 生成 10 个值,这是一个长度为 10 的序列,其中的元素索引都是合法的。range 可以不从 0 开始,还可以按指定幅度递增(递增幅度称为 ‘步进’,支持负数)

1
2
3
list(range(5, 10)) # [5, 6, 7, 8, 9]
list(range(0, 10, 3)) # [0, 3, 6, 9]
list(range(-10, -100, -30)) # [-10, -40, -70]

range() 返回对象的操作和列表很像,但其实这两种对象不是一回事。迭代时,该对象基于所需序列返回连续项,并没有生成真正的列表,从而节省了空间。这种对象称为可迭代对象 iterable,函数或程序结构可通过该对象获取连续项,直到所有元素全部迭代完毕。for 语句就是这样的架构,sum() 是一种把可迭代对象作为参数的函数

1
sum(range(4)) # 6

pass 语句不执行任何操作。语法上需要一个语句,但程序不实际执行任何动作时,可以使用该语句

1
2
3
4
5
6
while True:
pass
class EmptyClass:
pass
def EmptyFunc:
pass

函数

定义函数使用关键字 def,后跟函数名与括号内的形参列表。函数语句从下一行开始,并且必须缩进。函数内的第一条语句是字符串时,该字符串就是文档字符串。

函数在执行时使用函数局部变量符号表,所有函数变量赋值都存在局部符号表中;引用变量时,首先,在局部符号表里查找变量,然后,是外层函数局部符号表,再是全局符号表,最后是内置名称符号表。因此,尽管可以引用全局变量和外层函数的变量,但最好不要在函数内直接赋值(除非是 global 语句定义的全局变量,或 nonlocal 语句定义的外层函数变量)。

在调用函数时会将实际参数(实参)引入到被调用函数的局部符号表中;因此,实参是使用按值调用来传递的(其中的值始终是对象的引用而不是对象的值)。

函数定义在当前符号表中把函数名与函数对象关联在一起。解释器把函数名指向的对象作为用户自定义函数。还可以使用其他名称指向同一个函数对象,并访问该函数。

1
2
3
4
5
6
7
8
9
def fib(n):    # write Fibonacci series up to n
"""Print a Fibonacci series up to n."""
a, b = 0, 1
while a < n:
print(a, end=' ')
a, b = b, a+b

f = fib
f(100)

复杂数据类型

列表

1
2
3
4
5
6
7
8
9
fruits = ['orange', 'apple', 'pear', 'banana', 'kiwi', 'apple', 'banana']
fruits.count('apple') # 2
fruits.count('tangerine') # 0
fruits.index('banana') # 3
fruits.index('banana', 4) # Find next banana starting a position 4
fruits.reverse() # ['banana', 'apple', 'kiwi', 'banana', 'pear', 'apple', 'orange']
fruits.append('grape') # ['banana', 'apple', 'kiwi', 'banana', 'pear', 'apple', 'orange', 'grape']
fruits.sort() # ['apple', 'apple', 'banana', 'banana', 'grape', 'kiwi', 'orange', 'pear']
fruits.pop() # 'pear'

insert、remove、sort 等方法只修改列表,返回的默认值为 None 。这是所有Python可变数据结构的设计原则。不是所有数据都可以排序或比较,整数不能与字符串对比,而 None 不能与其他类型对比。

实现堆栈

1
2
3
4
5
stack = [3, 4, 5]
stack.append(6)
stack.append(7)
stack.pop()
stack.pop()

列表也可以用作队列,最先加入的元素,最先取出(“先进先出”);然而,列表作为队列的效率很低。因为,在列表末尾添加和删除元素非常快,但在列表开头插入或移除元素却很慢(因为所有其他元素都必须移动一位)。实现队列最好用 collections.deque,可以快速从两端添加或删除元素。

1
2
3
4
5
6
from collections import deque
queue = deque(["Eric", "John", "Michael"])
queue.append("Terry") # Terry arrives
queue.append("Graham") # Graham arrives
queue.popleft() # The first to arrive now leaves
queue.popleft() # The second to arrive now leaves

列表可嵌套

1
2
3
4
matrix = [
[1, 2, 3, 4],
[5, 6, 7, 8]
]

元祖

元组由多个用逗号隔开的值组成

1
2
t = 1, 2, 3
t[0] # 1

元组与列表很像,但使用场景不同,用途也不同。元组是 immutable (不可变的),一般可包含异质元素序列,通过解包或索引访问。列表是 mutable (可变的),列表元素一般为同质类型,可迭代访问。

构造 0 个或 1 个元素的元组比较特殊。

1
2
empty = ()
singleton = 'hello', # <-- note trailing comma

集合

集合是由不重复元素组成的无序容器。基本用法包括成员检测、消除重复元素。集合对象支持合集、交集、差集、对称差分等数学运算。创建集合用花括号或 set() 函数。注意,创建空集合只能用 set(),不能用 {} , {} 创建的是空字典。

1
2
3
4
5
6
7
8
9
10
11
12
basket = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}
len(basket) # 4
print(basket) # {'orange', 'banana', 'pear', 'apple'}
'orange' in basket # True
'crabgrass' in basket # False

a = set('abracadabra') # {'a', 'r', 'b', 'c', 'd'}
b = set('alacazam') # {'a', 'l', 'c', 'z', 'm'}
a - b # {'r', 'd', 'b'} letters in a but not in b
a | b # {'a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'} letters in a or b or both
a & b # {'a', 'c'} letters in both a and b
a ^ b # {'r', 'd', 'b', 'm', 'z', 'l'} letters in a or b but not both

字典

字典以 关键字 为索引,关键字通常是字符串或数字,也可以是其他任意不可变类型。只包含字符串、数字、元组的元组,也可以用作关键字。但如果元组直接或间接地包含了可变对象,就不能用作关键字。列表不能当关键字,因为列表可以用索引、切片、append() 、extend() 等方法修改。

可以把字典理解为 键值对 的集合,但字典的键必须是唯一的。花括号 {} 用于创建空字典。另一种初始化字典的方式是,在花括号里输入逗号分隔的键值对,这也是字典的输出方式。

字典的主要用途是通过关键字存储、提取值。用 del 可以删除键值对。用已存在的关键字存储值,与该关键字关联的旧值会被取代。通过不存在的键提取值,则会报错。

对字典执行 list(d) 操作,返回该字典中所有键的列表,按插入次序排列(如需排序,请使用 sorted(d))。检查字典里是否存在某个键,使用关键字 in。

1
2
3
4
5
6
7
8
9
tel = {'jack': 4098, 'sape': 4139}
tel['guido'] = 4127 # {'jack': 4098, 'sape': 4139, 'guido': 4127}
tel['jack'] # 4098
del tel['sape']
tel['irv'] = 4127 # {'jack': 4098, 'guido': 4127, 'irv': 4127}
list(tel) # ['jack', 'guido', 'irv']
sorted(tel) # ['guido', 'irv', 'jack']
'guido' in tel # True
'jack' not in tel # False

del语句

del 语句按索引,而不是值从列表中移除元素。与返回值的 pop() 方法不同, del 语句也可以从列表中移除切片,或清空整个列表(之前是将空列表赋值给切片)。

1
2
3
4
a = [-1, 1, 66.25, 333, 333, 1234.5]
del a[0] # [1, 66.25, 333, 333, 1234.5]
del a[2:4] # [1, 66.25, 1234.5]
del a[:] # []

用 del 可以删除 dict 里的键值对

1
2
tel = {'jack': 4098, 'sape': 4139}
del tel['jack'] # {'sape': 4139}

循环遍历数据结构

在字典中循环时,用 items() 方法可同时取出键和对应的值:

1
2
3
knights = {'gallahad': 'the pure', 'robin': 'the brave'}
for k, v in knights.items():
print(k, v)

在序列中循环时,用 enumerate() 函数可以同时取出位置索引和对应的值:

1
2
for i, v in enumerate(['tic', 'tac', 'toe']):
print(i, v)

逆向循环序列时,先正向定位序列,然后调用 reversed() 函数:

1
2
for i in reversed(range(1, 10, 2)):
print(i)

按指定顺序循环序列,可以用 sorted() 函数,在不改动原序列的基础上,返回一个重新的序列:

1
2
3
basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
for i in sorted(basket):
print(i)

编码风格

  • 缩进使用4个空格
  • 类和函数的命名要一致;按惯例,命名类用 UpperCamelCase,命名函数与方法用 lowercase_with_underscores。命名方法中第一个参数总是用 self。

模块

模块包含可执行语句及函数定义。这些语句用于初始化模块,且仅在 import 语句 第一次 遇到模块名时执行。模块有自己的私有符号表,用作模块中所有函数的全局符号表。因此,在模块内使用全局变量时,不用担心与用户定义的全局变量发生冲突。为了保证运行效率,每次解释器会话只导入一次模块。如果更改了模块内容,必须重启解释器;仅交互测试一个模块时,也可以使用 importlib.reload()

1
2
import importlib
importlib.reload(modulename)

模块搜索路径

导入 spam 模块时,解释器首先查找名为 spam 的内置模块。如果没找到,解释器再从 sys.path 变量中的目录列表里查找 spam.py 文件。sys.path 初始化时包含以下位置:

  • 输入脚本的目录(或未指定文件时的当前目录)。
  • PYTHONPATH (目录列表,与 shell 变量 PATH 的语法一样)。
  • The installation-dependent default (by convention including a site-packages directory, handled by the site module).

dir()函数

内置函数 dir() 用于查找模块定义的名称。返回结果是经过排序的字符串列表,没有参数时,dir() 列出当前定义的名称。该函数列出所有类型的名称:变量、模块、函数等。dir() 不会列出内置函数和变量的名称。这些内容的定义在标准模块 builtins 里。

1
2
3
dir()
import builtins
dir(builtins)

Python 只把含 __init__.py 文件的目录当成包。这样可以防止以 string 等通用名称命名的目录,无意中屏蔽出现在后方模块搜索路径中的有效模块。 最简情况下,__init__.py 只是一个空文件,但该文件也可以执行包的初始化代码,或设置__all__变量。

1
__all__ = ["echo", "surround", "reverse"]

from sound.effects import * 将导入 sound 包中的这三个命名子模块。

从包中导入单个模块,引用时必须使用子模块的全名。

1
2
import sound.effects.echo
sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)

另一种导入子模块的方法,不加包前缀也可以使用。

1
2
from sound.effects import echo
echo.echofilter(input, output, delay=0.7, atten=4)

Import 语句的另一种变体是直接导入所需的函数或变量

1
2
from sound.effects.echo import echofilter
echofilter(input, output, delay=0.7, atten=4)

注意,使用 from package import item 时,item 可以是包的子模块(或子包),也可以是包中定义的函数、类或变量等其他名称。import 语句首先测试包中是否定义了 item;如果未在包中定义,则假定 item 是模块,并尝试加载。如果找不到 item,则触发 ImportError 异常。相反,使用 import item.subitem.subsubitem 句法时,除最后一项外,每个 item 都必须是包;最后一项可以是模块或包,但不能是上一项中定义的类、函数或变量。

https://docs.python.org/zh-cn/3/tutorial/index.html

Share