List
排序
1 | cars = ['bmw', 'audi', 'toyota', 'subaru'] |
访问list元素
1 | cars = ['bmw', 'audi', 'toyota', 'subaru'] |
增删元素『重要』
1 | motorcycles = ['honda', 'yamaha', 'suzuki', 'ducati'] |
获取list长度
1 | len(cars) |
复制list
1 | my_foods = ['pizza', 'falafel', 'carrot cake'] |
检查特定值是否在list中
1 | banned_users = ['andrew', 'carolina', 'david'] |
在list中检索值
1 | >>> a_list = ['a', 'b', 'new', 'mpilgrim', 'new'] |
if
判断条件为list
注意点
在判断条件为list
时,如果list
为空,即记过为false
,只有在list
有一个元素时,才为true
。
1 | requested_toppings = [] |
这里实际执行的就是else
中的语句,因为requested_toppings
是空的,返回的false
。
多个list
判断
1 | available_toppings = ['mushrooms', 'olives', 'green peppers', 'pepperoni', 'pineapple', 'extra cheese'] |
使用函数range()
1 | for value in range(1, 5): # 生成有序数值 |
对数值列表执行简单的统计计算
1 | digits = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0] |
列表解析
- 复杂模式1
1
2
3
4
5squares = []
for value in range(1, 11):
square = value**2
squares.append(square)
print(squares) - 较复杂模式2
1
2
3
4squares = []
for value in range(1, 11):
squares.append(value**2)
print(squares) - 列表解析要使用这种语法,首先指定一个描述性的列表名,如
1
2squares = [value**2 for value in range(1,11)]
print(squares)squares
;然后,指定一个左方括号,并定义一个表达式,用于生成你要存储到列表中的值。
表达式为value**2
,它计算平方值。接下来,编写一个for
循环,用于给表达式提供值,再加上右方括号。for
循环为for value in range(1,11)
,它将值1~10提供给表达式value**2
。请注意,这里的for
语句末尾没有冒号。
使用列表的一部分:列表切片『重要』
定义列表后,可从其中获取任何部分作为新列表。该技术称为对列表进行切片
。
1 | >>> a_list = ['a', 'b', 'mpilgrim', 'z', 'example'] |
分片赋值
- 一次为多个元素赋值
1
2
3
4
5
6>>> name = list('Perl')
>>> name
['P', 'e', 'r', 'l']
>>> name[1:] = list('ython')
>>> name
['P', 'y', 't', 'h', 'o', 'n'] - 插入新的元素「替换一个空的切片」
1
2
3
4>>> numbers = [1, 5]
>>> numbers[1:1] = [2, 3, 4]
>>> numbers
[1, 2, 3, 4, 5] - 删除元素
1
2
3
4
5>>> numbers
[1, 2, 3, 4, 5]
>>> numbers[1:4] = []
>>> numbers
[1, 5]
列表方法
- append「列表末尾增加元素」
- count 「统计某个元素在列表中出现的次数」
1
2
3
4
5
6
7>>> ['to', 'be', 'or', 'not', 'to', 'be'].count('to')
2
>>> x = [[1, 2], 1, 1, [2, 1, [1, 2]]]
>>> x.count(1)
2
>>> x.count([1, 2])
1 - extend 「在列表末尾增加另一个列表中的多个值」「原列表被修改」
1
2
3
4
5>>> a = [1, 2, 3]
>>> b = [4, 5, 6]
>>> a.extend(b)
>>> a
[1, 2, 3, 4, 5, 6] - index 「索引位置」
1
2
3
4
5
6
7
8
9
10>>> knights = ['We', 'are', 'the', 'knights', 'who', 'say', 'ni']
>>> knights.index('who')
4
>>> knights.index('herring')
Traceback (innermost last):
File "<pyshell>", line 1, in ?
knights.index('herring')
ValueError: list.index(x): x not in list
>>> knights[4]
'who' - insert 「列表插入元素」「第一个参数是索引号,第二个参数是待添加的新元素」
1
2
3
4>>> numbers = [1, 2, 3, 5, 6, 7]
>>> numbers.insert(3, 'four')
>>> numbers
[1, 2, 3, 'four', 5, 6, 7] - pop 「移除列表元素」「默认最后一个」「可实现一种常见的数据结构—栈”后进先出”」
1
2
3
4
5
6
7
8
9>>> x = [1, 2, 3]
>>> x.pop()
3
>>> x
[1, 2]
>>> x.pop(0)
1
>>> x
[2] - remove 「删除第一个指定值的元素」
1
2
3
4
5
6
7
8
9>>> x = ['to', 'be', 'or', 'not', 'to', 'be']
>>> x.remove('be')
>>> x
['to', 'or', 'not', 'to', 'be']
>>> x.remove('bee')
Traceback (innermost last):
File "<pyshell>", line 1, in ?
x.remove('bee')
ValueError: list.remove(x): x not in list - reverse 「按相反的顺序排列列表中的元素」「reversed」
1
2
3
4>>> x = [1, 2, 3]
>>> x.reverse()
>>> x
[3, 2, 1] - sort 「对列表就地排序」「sorted」
1
2
3
4>>> x = [4, 6, 2, 1, 7, 9]
>>> x.sort()
>>> x
[1, 2, 4, 6, 7, 9] - 高级排序「方法sort接受两个可选参数:key和reverse」
1
2
3
4
5
6
7
8>>> x = ['aardvark', 'abalone', 'acme', 'add', 'aerate']
>>> x.sort(key=len)
>>> x
['add', 'acme', 'aerate', 'abalone', 'aardvark']
>>> x = [4, 6, 2, 1, 7, 9]
>>> x.sort(reverse=True)
>>> x
[9, 7, 6, 4, 2, 1]
字符串
设置字符串格式『Python基础教程3.2、3.3节』
%
-转换说明符%s
-s将值的格式设置为字符串%.3f
-将值的格式设置为包含3位小数的浮点数1
2
3
4>>> format = "Hello, %s. %s enough for ya?"
>>> values = ('world', 'Hot')
>>> format % values
'Hello, world. Hot enough for ya?'{}.format
-字符串方法
每个替换字段都用花括号括起,其中可能包含名称,还可能包含有关如何对相应的值进行转换和格式设置的信息1
2
3
4
5
6
7
8
9
10
11
12# 在最简单的情况下,替换字段没有名称或将索引用作名称。
>>> "{}, {} and {}".format("first", "second", "third")
'first, second and third'
>>> "{0}, {1} and {2}".format("first", "second", "third")
'first, second and third'
# 然而,索引无需像上面这样按顺序排列。
>>> "{3} {0} {2} {1} {3} {0}".format("be", "not", "or", "to")
'to be or not to be'
# 命名字段的工作原理与你预期的完全相同。
>>> from math import pi
>>> "{name} is approximately {value:.2f}.".format(value=pi, name="π")
'π is approximately 3.14.'- 格式化字符串核心-
替换字段
替换字段由如下部分组成:字段名
:索引或标识符,指出要设置哪个值的格式并使用结果来替换该字段。除指定值外,还可指定值的特定部分,如列表的元素。转换标志
:跟在叹号后面的单个字符。当前支持的字符包括r(表示repr)
、s(表示str)
和a(表示ascii)
。如果你指定了转换标志,将不使用对象本身的格式设置机制,而是使用指定的函数将对象转换为字符串,再做进一步的格式设置。格式说明符
:跟在冒号后面的表达式(这种表达式是使用微型格式指定语言表示的)。格式说明符让我们能够详细地指定最终的格式,包括格式类型(如字符串、浮点数或十六进制数),字段宽度和数的精度,如何显示符号和千位分隔符,以及各种对齐和填充方式。
3.2 基本转换1
2
3
4>>> "{foo} {} {bar} {}".format(1, 2, bar=4, foo=3)
'3 1 4 2'
>>> "{foo} {1} {bar} {0}".format(1, 2, bar=4, foo=3)
'3 2 4 1'
3.3 宽度、精度、千位分隔符
3.4 符号、对齐、用0填充
字符串方法
- center
通过在两边添加填充字符(默认为空格)让字符串居中。1
2
3
4>>> "The Middle by Jimmy Eat World".center(39)
' The Middle by Jimmy Eat World '
>>> "The Middle by Jimmy Eat World".center(39, "*")
'*****The Middle by Jimmy Eat World*****' - find
在字符串中查找子串。如果找到,就返回子串的第一个字符的索引,否则返回-1。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21>>> 'With a moo-moo here, and a moo-moo there'.find('moo')
7
>>> title = "Monty Python's Flying Circus"
>>> title.find('Monty')
0
>>> title.find('Python')
6
>>> title.find('Flying')
15
>>> title.find('Zirquss')
-1
# 指定搜索的起点和终点(它们都是可选的)。
>>> subject = '$$$ Get rich now!!! $$$'
>>> subject.find('$$$')
0
>>> subject.find('$$$', 1) # 只指定了起点
20
>>> subject.find('!!!')
16
>>> subject.find('!!!', 0, 16) # 同时指定了起点和终点
-1 - join
其作用与split相反,用于合并序列的元素。1
2
3
4
5
6
7
8
9
10
11
12
13
14>>> seq = [1, 2, 3, 4, 5]
>>> sep = '+'
>>> sep.join(seq) # 尝试合并一个数字列表
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: sequence item 0: expected string, int found
>>> seq = ['1', '2', '3', '4', '5']
>>> sep.join(seq) # 合并一个字符串列表
'1+2+3+4+5'
>>> dirs = '', 'usr', 'bin', 'env'
>>> '/'.join(dirs)
'/usr/bin/env'
>>> print('C:' + '\\'.join(dirs))
C:\usr\bin\env - lower
返回字符串的小写版本。1
2>>> 'Trondheim Hammer Dance'.lower()
'trondheim hammer dance' - replace
将指定子串都替换为另一个字符串,并返回替换后的结果。1
2>>> 'This is a test'.replace('is', 'eez')
'Theez eez a test' - split
作用与join相反,用于将字符串拆分为序列。如果没有指定分隔符,将默认在单个或多个连续的空白字符(空格、制表符、换行符等)处进行拆分。1
2
3
4
5
6>>> '1+2+3+4+5'.split('+')
['1', '2', '3', '4', '5']
>>> '/usr/bin/env'.split('/')
['', 'usr', 'bin', 'env']
>>> 'Using the default'.split()
['Using', 'the', 'default'] - strip
将字符串开头和末尾的空白(但不包括中间的空白)删除,并返回删除后的结果。与lower一样,需要将输入与存储的值进行比较时,strip很有用。回到前面介绍lower时使用的用户名示例,并假定用户输入用户名时不小心在末尾加上了一个空格。1
2>>> ' internal whitespace is kept '.strip()
'internal whitespace is kept'还可在一个字符串参数中指定要删除哪些字符。1
2
3
4
5
6
7
8>>> names = ['gumby', 'smith', 'jones']
>>> name = 'gumby '
>>> if name in names: print('Found it!')
...
>>> if name.strip() in names: print('Found it!')
...
Found it!
>>>1
2>>> '*** SPAM * for * everyone!!! ***'.strip(' *!')
'SPAM * for * everyone' - translate
方法translate与replace一样替换字符串的特定部分,但不同的是它只能进行单字符替换。这个方法的优势在于能够同时替换多个字符,因此效率比replace高。
元组tuple
元组:是不可变的列表。一旦创建之后,用任何方法都不可以修改元素。
1 | >>> a_tuple = ("a", "b", "mpilgrim", "z", "example") |
元组和列表的主要区别是元组不能进行修改。用技术术语来说,元组是不可变更
的。从实践的角度来说,没有可用于修改元组的方法。列表有像append()
、extend()
、insert()
、remove()
和pop()
这样的方法。这些方法,元组都没有。可以对元组进行切片操作(因为该方法创建一个新的元组),可以检查元组是否包含了特定的值(因为该操作不修改元组),还可以……就那么多了。
元组有什么好处:
- 元组的速度比列表更快。如果定义了一系列常量值,而所需做的仅是对它进行遍历,那么请使用元组替代列表。
- 对不需要改变的数据进行“写保护”将使得代码更加安全。使用元组替代列表就像是有一条隐含的 assert 语句显示该数据是常量,特别的想法(及特别的功能)必须重写。(??)
- 一些元组可用作字典键(特别是包含字符串、数值和其它元组这样的不可变数据的元组)。列表永远不能当做字典键使用,因为列表不是不可变的。
元组可转换成列表,反之亦然。内建的tuple()
函数接受一个列表参数,并返回一个包含同样元素的元组,而list()
函数接受一个元组参数并返回一个列表。从效果上看,tuple()
冻结列表,而list()
融化元组。
集合{ }
一个简单的集合可以包含任何数据类型的值。如果有两个集合,则可以执行像联合、交集以及集合求差等标准集合运算。
从list创建集合
1 | >>> a_list = ['a', 'b', 'mpilgrim', True, False, 42] |
创建空集合
1 | # 要创建空集合,可不带参数调用 set() 。 |
修改集合
有两种方法可向现有集合中添加值: add() 方法和 update() 方法。
集合是装 唯一值 的袋子。如果试图添加一个集合中已有的值,将不会发生任何事情。将不会引发一个错误;只是一条空操作。
从集合中删除元素
有三种方法可以用来从集合中删除某个值。前两种,discard() 和 remove() 有细微的差异。集合也有个 pop() 方法。pop()
方法从集合中删除某个值,并返回该值。然而,由于集合是无序的,并没有“最后一个”值的概念,因此无法控制删除的是哪一个值。它基本上是随机的。
常见集合操作
1 | >>> a_set = {2, 4, 5, 9, 12, 21, 30, 51, 76, 127, 195} |
字典dict
字典 是键值对的无序集合。向字典添加一个键的同时,必须为该键增添一个值。(之后可随时修改该值。) Python 的字典为通过键获取值进行了优化,而不是反过来。
修改字典
1 | >>> a_dict = {'server': 'db.diveintopython3.org', 'database': 'mysql'} |
混合值字典,value不为单个值
字典并非只能用于字符串。字典的值可以是任何数据类型,包括整数、布尔值、任何对象,甚至是其它的字典。而且就算在同一字典中,所有的值也无须是同一类型,您可根据需要混合匹配。字典的键要严格得多,可以是字符串、整数和其它一些类型。在同一字典中也可混合、匹配使用不同数据类型的键。
1 | >>> SUFFIXES = {1000: ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'], |
grades[‘’]
是否可迭代
Iterable
类似一个概念,实例才是可被CPU操作的,真实存在的东西。
1
2
3
4
5
6
7
8
9
10
11
12
13
14class People():
def __init__(self):
pass
def have_some_food(self):
print('Delicious!')
def hava_a_drink(self):
print('Thanks!')
if __name__ == '__main__':
me = People()
you = People()
me.have_some_food()
me.hava_a_drink()
字典方法『Python基础教程4.2.4节』
- clear
场景一:通过将一个空字典赋给x来“清空”它。这对y没有任何影响,它依然指向原来的字典。场景二:但要删除原来字典的所有元素,必须使用clear。如果这样做,y也将是空的。1
2
3
4
5
6
7
8>>> x = {}
>>> y = x
>>> x['key'] = 'value'
>>> y
{'key': 'value'}
>>> x = {}
>>> x = {}
{'key': 'value'}1
2
3
4
5
6
7
8>>> x = {}
>>> y = x
>>> x['key'] = 'value'
>>> y
{'key': 'value'}
>>> x.clear()
>>> y
{} - copy
返回一个新字典,其包含的键值对与原来的字典相同(这个方法执行的是浅复制,因为值本身是原件,而非副本)。
为避免修改副本时也同时修改了原件,一种办法是执行深复制,即同时复制值及其包含的所有值,等等。为此,可使用模块copy中的函数deepcopy。 - fromkeys
创建一个新字典,其中包含指定的键,且每个键对应的值都是None。 - get
使用get来访问不存在的键时,没有引发异常,而是返回None。你可指定“默认”值,这样将返回你指定的值而不是None。1
2>>> d.get('name', 'N/A')
'N/A' - items
方法items返回一个包含所有字典项的列表,其中每个元素都为(key, value)的形式。字典项在列表中的排列顺序不确定。返回值属于一种名为1
2
3>>> d = {'title': 'Python Web Site', 'url': 'http://www.python.org', 'spam': 0}
>>> d.items()
dict_items([('url', 'http://www.python.org'), ('spam', 0), ('title', 'Python Web Site')])字典视图
的特殊类型。 - keys
返回一个字典视图
,其中包含指定字典中的键。 - pop
用于获取与指定键相关联的值,并将该键值对从字典中删除。1
2
3
4
5>>> d = {'x': 1, 'y': 2}
>>> d.pop('x')
1
>>> d
{'y': 2} - popitem
类似于list.pop,但list.pop弹出列表中的最后一个元素,而popitem随机地弹出一个字典项1
2
3
4
5>>> d = {'url': 'http://www.python.org', 'spam': 0, 'title': 'Python Web Site'}
>>> d.popitem()
('url', 'http://www.python.org')
>>> d
{'spam': 0, 'title': 'Python Web Site'} - setdefault
有点像get,因为它也获取与指定键相关联的值,但除此之外,setdefault还在字典不包含指定的键时,在字典中添加指定的键值对。1
2
3
4
5
6
7
8
9
10>>> d = {}
>>> d.setdefault('name', 'N/A')
'N/A'
>>> d
{'name': 'N/A'}
>>> d['name'] = 'Gumby'
>>> d.setdefault('name', 'N/A')
'Gumby'
>>> d
{'name': 'Gumby'} - update
使用一个字典中的项来更新另一个字典。1
2
3
4
5
6
7
8
9
10>>> d = {
... 'title': 'Python Web Site',
... 'url': 'http://www.python.org',
... 'changed': 'Mar 14 22:09:15 MET 2016'
... }
>>> x = {'title': 'Python Language Website'}
>>> d.update(x)
>>> d
{'url': 'http://www.python.org', 'changed':
'Mar 14 22:09:15 MET 2016', 'title': 'Python Language Website'} - values
返回一个由字典中的值组成的字典视图。不同于方法keys,方法values返回的视图可能包含重复的值。
抽象
参数
- 位置参数
1
2
3
4
5
6
7
8
9
10storage = {}
storage['first'] = {}
storage['middle'] = {}
storage['last'] = {}
>>> me = 'Magnus Lie Hetland'
>>> storage['first']['Magnus'] = [me]
>>> storage['middle']['Lie'] = [me]
>>> storage['last']['Hetland'] = [me]
>>> storage['middle']['Lie']
['Magnus Lie Hetland'] - 关键字参数和默认值
使用名称指定的参数称为关键字参数,主要优点是有助于澄清各个参数的作用。通过给参数指定默认值,可使其变成可选的。具体使用示例如下:1
2>>> store('Mr. Brainsample', 10, 20, 13, 5)
>>> store(patient='Mr. Brainsample', hour=10, minute=20, day=13, month=5)1
2
3
4
5
6
7
8
9
10def hello_3(greeting='Hello', name='world'):
print('{}, {}!'.format(greeting, name))
>>> hello_3()
Hello, world!
>>> hello_3('Greetings')
Greetings, world!
>>> hello_3('Greetings', 'universe')
Greetings, universe!
>>> hello_3(name='Gumby')
Hello, Gumby! - 收集参数
- 参数前面带
一个星号
将提供的所有值都放在一个元组中,也就是将这些值收集起来。1
2
3
4
5
6def print_params_2(title, *params):
print(title)
print(params)
>>> print_params_2('Params:', 1, 2, 3)
Params:
(1, 2, 3) 一个星号
不会收集关键字参数1
2
3
4
5
6
7
8
9>>> def in_the_middle(x, *y, z):
... print(x, y, z)
...
>>> in_the_middle(1, 2, 3, 4, 5, z=7)
1 (2, 3, 4, 5) 7
>>> in_the_middle(1, 2, 3, 4, 5, 7)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: in_the_middle() missing 1 required keyword-only argument: 'z'- 要收集关键字参数,可使用两个星号。
1
2
3
4
5
6
7
8
9
10
11
12def print_params_4(x, y, z=3, *pospar, **keypar):
print(x, y, z)
print(pospar)
print(keypar)
>>> print_params_4(1, 2, 3, 5, 6, 7, foo=1, bar=2)
1 2 3
(5, 6, 7)
{'foo': 1, 'bar': 2}
>>> print_params_4(1, 2)
1 2 3
()
{}
- 参数前面带
作用域
在函数内使用的变量称为局部变量(与之相对的是全局变量)。参数类似于局部变量,因此参数与全局变量同名不会有任何问题。
- 作用域嵌套
Python函数可以嵌套,即可将一个函数放在另一个函数内像1
2
3
4
5
6
7
8
9
10
11
12def multiplier(factor):
def multiplyByFactor(number):
return number * factor
return multiplyByFactor
>>> double = multiplier(2)
>>> double(5)
10
>>> triple = multiplier(3)
>>> triple(3)
9
>>> multiplier(5)(4)
20multiplyByFactor
这样存储其所在作用域的函数称为闭包
。
递归
基线条件
(针对最小的问题):满足这种条件时函数将直接返回一个值。递归条件
:包含一个或多个调用,这些调用旨在解决问题的一部分。
这里的关键是,通过将问题分解为较小的部分,可避免递归没完没了,因为问题终将被分解成基线条件可以解决的最小问题。- 示例:阶乘和幂
- lambda表达式
1
2
3
4
5>>> seq = ["foo", "x41", "?!", "***"]
>>> [x for x in seq if x.isalnum()]
['foo', 'x41']
>>> filter(lambda x: x.isalnum(), seq)
['foo', 'x41']
面向对象
封装
封装
是面向对象编程的一大特点- 面向对象编程的
第一步
——将属性
和方法``封装
到一个抽象的类
中 外界
使用类
创建对象
,然后让对象调用方法
对象方法的细节
都被封装
在类的内部
同一个类
创建的多个对象
之间,属性
互不干扰。- 一个对象的
属性
,可以是另一个类创建的对象
定义没有初始值的属性,如果不知道设置什么初始值,可以设置为None
None
关键字,表示什么都没有- 表示一个
空对象
,没有方法和属性,是一个特殊的常量 - 可以将
None
赋值给任何一个变量
在封装的
方法内部,还可以让自己的``使用其他类创建的对象的属性
调用已经封装好的方法
身份运算符
身份运算符,用于比较两个对象的内存地址
是否一致–是否是对同一个对象的引用
在 Python 中针对None
比较时,建议使用is
判断
运算符 | 描述 | 实例 |
---|---|---|
is | is 是判断两个标识符是不是引用同一个对象 | x is y,类似 id(x) == id(y) |
is not | is not 是判断两个标识符是不是引用不同对象 | x is not y,类似 id(a) != id(b) |
is
与==
的区别:is
用于判断两个变量``引用对象是否为同一个
==
用于判断引用变量的值
是否相等
解析
处理文件和目录
Python3
带有一个模块叫做os
,代表操作系统(operating system)
。os
模块 包含非常多的函数用于获取(和修改)本地目录、文件进程、环境变量等的信息。
1 | import os |
列表解析
列表解析提供了一种紧凑的方式,实现了通过对列表中每一个元素应用一个函数的方法来将一个列表映射到另一个列表。
1 | import os, glob |
字典解析
1 | # 列表解析 |
集合解析
集合也有自己的集合解析的语法。它和字典解析的非常相似,唯一的不同是集合只有值而没有键:值对。
1 | a_set = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} |
正则表达式
替换操作
1 | import re |
电话号码解析实例
1 | import re |
到此应该熟悉了下面的技巧:
1 | ^ # 匹配字符串开始位置。 |
闭合和生成器
正则表达式使用
1 | import re |