1、序列切片
一些常见的序列类型是列表,元组和字符串。我们可以通过切片另一个序列来创建一个序列。以下功能以列表为例,但是它们也可以应用于元组,字符串和其他序列类型(例如,字节)。
>>> a = [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
>>> # Using a range, [start, end)
>>> a[1:3]
[2, 4]
>>> # Using a range with a step
>>> a[1:9:2]
[2, 6, 10, 14]
>>> # Leave out the start = an implicit start of 0
>>> a[:5]
[0, 2, 4, 6, 8]
>>> # Leave out the stop = an implicit end to the very last item
>>> a[9:]
[18, 20]
>>> # Entire list
>>> a[:]
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
2、反转序列
有时,我们想反转一个序列。尽管我们可以使用for循环来实现它,但是有一种直接的方法。同样,如上所述,当某个功能可用于序列时,通常意味着字符串,元组和列表都支持该功能。
>>> a = (1, 2, 3, 4, 5)
>>> a[::-1]
(5, 4, 3, 2, 1)
>>> b = 'start'
>>> b[::-1]
'trats'
3、使用反向索引访问序列中的元素
如果要在序列末尾访问某些元素,则向后计数会更容易。在Python序列中,最后一个元素的索引为-1,前一个元素的索引为-2,依此类推。
>>> a = 'Hello World!'
>>> # instead of using a[len(a)-1]
>>> a[-1]
'!'
>>> # in combination with slicing
>>> a[-5:-1]
'orld'
4、多项作业
当我们想将某些值分配给几个变量时,我们可以进行多次分配。我们可以应用相同的习惯用法来交换列表中的两个变量或两个元素。在幕后,此功能与本文稍后介绍的元组拆包密切相关。
>>> # instead of doing a = 8; b = 5
>>> a, b = 8, 5
>>> print(f'a is {a}; b is {b}')
a is 8; b is 5
>>> # Swap two variables
>>> a, b = b, a
>>> print(f'a is {a}; b is {b}')
a is 5; b is 8
>>> # Swap the first and last elements in a list
>>> numbers = [1, 2, 3, 4, 5]
>>> numbers[0], numbers[-1] = numbers[-1], numbers[0]
>>> numbers
[5, 2, 3, 4, 1]
5、检查序列是否为空
仅当序列(例如,列表,元组)不为空时,某些操作才有意义,因此我们需要在应用适当的操作之前进行检查。为此,我们可以仅使用not关键字来否定序列(例如not []),该True序列的值就好像该序列为空。此外,我们可以对另外两种常见的数据类型做相同的事情:dict和set。
>>> empty_list = [(), '', [], {}, set()]
>>> for item in empty_list:
... if not item:
... print(f'Do something with the {type(item)}')
...
Do something with the <class 'tuple'>
Do something with the <class 'str'>
Do something with the <class 'list'>
Do something with the <class 'dict'>
Do something with the <class 'set'>
6、列表理解
列表推导是Python的一个方便功能,我们可以很方便地构建列表。列表推导的一般格式为[some_expression for element in iterable if some_condition]。
>>> a = [1, 2, 3, 4, 5]
>>> [x*2 for x in a]
[2, 4, 6, 8, 10]
>>> [x*3 for x in a if x%2 == 1]
[3, 9, 15]
7、设定理解
集合理解的用法与列表理解类似,如上所述。不同之处在于,我们将使用大括号而不是方括号。同样,重复元素将通过set数据类型的定义而删除。
>>> a = [1, -2, 2, -3, 3, 4, 4, 5, 5, 5]
>>> {x*x for x in a}
{1, 4, 9, 16, 25}
8、字典理解
除了列表和设置理解之外,理解功能还可以用于创建字典数据类型。 字典由键值对组成,因此字典理解涉及键和值的规范,它们之间用冒号分隔。
>>> a = [1, 2, 3, 4, 5]
>>> {x: x*x for x in a}
{1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
9、生成器表达式
Python中的生成器是创建迭代器的便捷方法。由于生成器是“惰性”的(即在请求时产生所需的项),因此它们的内存效率很高。创建生成器的一种特殊方式称为生成器表达式,该表达式在语法上类似于列表理解,只是使用括号而不是方括号。
在下面的示例中,当生成器直接用于可以迭代的函数中时,括号是可选的。
>>> sum(x**2 for x in range(100))
328350
>>> max((x*x for x in range(100)))
9801
10、打开一个元组
元组是Python中非常常见的数据结构。它们只是一组相关值,而元组的常见用法涉及访问其元素。我们可以使用索引访问这些元素,但是解压缩是更方便的方法。与它的用法有关,我们可以使用下划线指示不需要的元素,并使用星号分配除命名元素之外的其余元素。
>>> items = (0, 'b', 'one', 10, 11, 'zero')
>>> a, b, c, d, e, f = items
>>> print(f)
zero
>>> a, *b, c = items
>>> print(b)
['b', 'one', 10, 11]
>>> *_, a, b = items
>>> print(a)
11
11、在循环中使用Enumerate()
该enumerate()函数接受一个可迭代的对象来创建一个迭代器。此外,它可以跟踪迭代次数。我们可以选择设置计数的开始。默认计数从0开始。
>>> students = ('John', 'Mary', 'Mike')
>>> for i, student in enumerate(students):
... print(f'Iteration: {i}, Student: {student}')
...
Iteration: 0, Student: John
Iteration: 1, Student: Mary
Iteration: 2, Student: Mike
>>> for i, student in enumerate(students, 35001):
... print(f'Student Name: {student}, Student ID #: {i}')
...
Student Name: John, Student ID #: 35001
Student Name: Mary, Student ID #: 35002
Student Name: Mike, Student ID #: 35003
12、在循环中使用Reversed()
reversed()函数通常在for循环中使用,以一种与原始可迭代对象相反的顺序创建迭代器的方法。
>>> tasks = ['laundry', 'picking up kids', 'gardening', 'cooking']
>>> for task in reversed(tasks):
... print(task)
...
cooking
gardening
picking up kids
laundry
13、Zip()函数
zip()功能在一对一匹配的基础上连接多个可迭代对象很有用。如果某些可迭代项超过最短的可迭代项,则会被截断。此函数返回一个迭代器,因此经常在迭代中使用。我们还可以使用zip()函数使用星号将解压缩的迭代器解压缩,并将解压缩后的项目分配给变量。
>>> students = ('John', 'Mary', 'Mike')
>>> ages = (15, 17, 16)
>>> scores = (90, 88, 82, 17, 14)
>>> for student, age, score in zip(students, ages, scores):
... print(f'{student}, age: {age}, score: {score}')
...
John, age: 15, score: 90
Mary, age: 17, score: 88
Mike, age: 16, score: 82
>>> zipped = zip(students, ages, scores)
>>> a, b, c = zip(*zipped)
>>> print(b)
(15, 17, 16)
14、排序的Lambda
Lambda是匿名函数,可以使用单行表达式接受多个参数。它的常见用法之一是在sorted()函数中设置为key参数。除此之外,lambda通常用于某些函数(例如max(),map()),其中单行表达式适用于使用def关键字替换常规函数。
>>> students = [{'name': 'John', 'score': 98}, {'name': 'Mike', 'score': 94}, {'name': 'Jennifer', 'score': 99}]
>>> sorted(students, key=lambda x: x['score'])
[{'name': 'Mike', 'score': 94}, {'name': 'John', 'score': 98}, {'name': 'Jennifer', 'score': 99}]
15、速记条件分配
此功能主要是语法糖。当你需要根据特定条件为变量分配值时,我们可以使用以下通用形式的速记分配:y = x(如果condition_met否则为another_x)。
>>> some_condition = True
>>> # the expanded format
>>> if some_condition:
... x = 5
... else:
... x = 3
>>> print(f'x is {x}')
x is 5
>>> # the shorthand way
>>> x = 5 if some_condition else 3
>>> print(f'x is {x}')
x is 5
16、集合中的成员资格测试
有时,我们需要在将操作应用于集合或匹配项之前测试集合中是否存在某个元素。惯用的方法是使用in关键字。
>>> a = ('one', 'two', 'three', 'four', 'five')
>>> if 'one' in a:
... print('The tuple contains one.')
...
The tuple contains one.
>>> b = {0: 'zero', 1: 'one', 2: 'two', 3: 'three'}
>>> if 2 in b.keys():
... print('The dict has the key of 2.')
...
The dict has the key of 2.
17、使用Get()检索字典中的值
通常,我们可以在方括号中指定密钥以检索密钥的值。但是,如果字典中不存在该键,则会引发错误。当然,我们可以使用try / except解决此问题。相反,我们可以使用get()方法,当键不在字典中时,该方法允许我们使用默认值。
>>> number_dict = {0: 'zero', 1: 'one', 2: 'two', 3: 'three'}
>>> number_dict[5]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 5
>>> number_dict.get(5, 'five')
'five'
18、获取字典中其值最大的关键字
对于字典,有时我们需要找出其值最大的键。我们首先可以在所有值的列表中找到最大值的索引,然后从另一个存储所有键的列表中找到相应的键。另外,一种更简单的方法是在max()函数中指定key参数。
为简单起见,我们不考虑最大值可能重复的情况。此外,可以使用min()函数将相同的方法应用于查找最小值的键。
>>> model_scores = {'model_a': 100, 'model_z': 198, 'model_t': 150}
>>> # workaround
>>> keys, values = list(model_scores.keys()), list(model_scores.values())
>>> keys[values.index(max(values))]
'model_z'
>>> # one-line
>>> max(model_scores, key=model_scores.get)
'model_z'
19、使用Print()函数进行调试
对于较小的项目,我们总是可以使用print()函数来帮助我们进行调试。我们也经常将此功能用于教学目的。我们经常在print()函数中使用一些技巧。第一个是结束除默认换行符以外的字符串,第二个是使用f字符串,这使我们能够创建包含某些表达式的字符串。
>>> for i in range(5):
... print(i, end=', ' if i < 4 else '\n')
...
0, 1, 2, 3, 4
>>> for i in range(5):
... print(f'{i} & {i*i}', end=', ' if i < 4 else '\n')
...
0 & 0, 1 & 1, 2 & 4, 3 & 9, 4 & 16
20、海象运算符
海象运算符(:=)是Python 3.8+中可用的新功能。它只是赋值表达式的另一个名称-赋给表达式中的变量。通常,当表达式使用变量时,必须提前声明该变量。使用海象运算符,变量赋值可以包含在表达式中,并且可以立即使用该变量。
>>> a = ['j', 'a', 'k', 'd', 'c']
>>> if (n := len(a))%2 == 1:
... print(f'The number of letters is {n}, which is odd.')
...
The number of letters is 5, which is odd.
21、分割字符串
当我们使用字符串时,将字符串分成单词列表是一项常见的任务。在这种情况下,我们可以使用split()函数,该函数使用分隔符和可选的最大分割数。一个相关的函数是rsplit()函数,该函数具有相似的功能,只是它从右侧开始进行拆分,以满足设置时的最大拆分需求。
>>> sentence = 'this is, a python, tutorial, about, idioms.'
>>> sentence.split(', ')
['this is', 'a python', 'tutorial', 'about', 'idioms.']
>>> sentence.split(', ', 2)
['this is', 'a python', 'tutorial, about, idioms.']
>>> sentence.rsplit(', ')
['this is', 'a python', 'tutorial', 'about', 'idioms.']
>>> sentence.rsplit(', ', 2)
['this is, a python, tutorial', 'about', 'idioms.']
22、以可迭代方式连接字符串
在处理字符串时,有时我们需要通过合并包含在可迭代对象(例如,列表,元组)中的一系列字符串来创建单个字符串。在这种情况下,我们可以使用所需的分隔符调用的join()函数。
>>> words = ('Hello', 'Python', 'Programmers')
>>> '!'.join(words)
'Hello!Python!Programmers'
>>> words_dict = {0: 'zero', 1: 'one', 2: 'two', 3: 'three'}
>>> '&'.join(words_dict.values())
'zero&one&two&three'
23、 Map()函数
map()函数是高阶函数(即,使用函数作为参数或返回函数作为其输出的函数)。它具有map(function,iterables)的通用格式,该格式会将函数应用于iterable,并返回一个map对象,它是一个迭代器。可迭代的数量应与该函数所需的参数数量匹配。
在下面的示例中,内置的pow()函数需要两个参数。当然,也可以使用自定义函数。附带说明一下,当我们使用map()函数创建列表时,我们很可能可以使用列表推导来达到相同的效果。
>>> numbers = (1, 2, 4, 6)
>>> indices = (2, 1, 0.5, 2)
>>> # use map()
>>> list(map(pow, numbers, indices))
[1, 2, 2.0, 36]
>>> # list comprehensions
>>> [pow(x, y) for x, y in zip(numbers, indices)]
[1, 2, 2.0, 36]
>>> def good_word(x: str):
... has_vowels = not set('aeiou').isdisjoint(x.lower())
... long_enough = len(x) > 7
... good_start = x.lower().startswith('pre')
... return has_vowels & long_enough & good_start
...
>>> words = ['Good', 'Presentation', 'preschool', 'prefix']
>>> list(filter(good_word, words))
['Presentation', 'preschool']
25、找出列表中最频繁的元素
当我们使用列表记录可能包含重复元素的内容时,例如跟踪一系列游戏的获胜者,这是一项相关任务,以找出谁赢得了最多的时间。可以通过指定键参数使用max()函数来完成此操作,该参数将通过集合中元素的计数找出最大值。
>>> winnings = ['John', 'Billy', 'Billy', 'Sam', 'Billy', 'John']
>>> max(set(winnings), key = winnings.count)
'Billy'
26、跟踪列表中元素的频率
在上面的示例之后,我们还想知道非冠军选手在比赛中的表现如何,因此我们可以找出第二名和第三名。要做到这一点,我们需要找出每个玩家有多少奖金。我们可以将字典理解和sorted()函数与lambda函数一起使用。
>>> winnings = ['John', 'Billy', 'Billy', 'Sam', 'Billy', 'John']
>>> tracked = {item: winnings.count(item) for item in set(winnings)}
>>> sorted(tracked.items(), key=lambda x: x[1], reverse=True)
[('Billy', 3), ('John', 2), ('Sam', 1)]
27、检查对象的类型
检查对象的类型是Python自省主题的一部分。有时,在应用相应的功能之前,我们需要知道某个对象是否为某种类型。为此,我们可以使用type()or isinstance()函数,后者是允许一对多检查的更灵活的方法。
>>> def check_type(number):
... if type(number) == int:
... print('do something with an int')
... if isinstance(number, (int, float)):
... print('do something with an int or float')
...
>>> check_type(5)
do something with an int
do something with an int or float
>>> check_type(4.2)
do something with an int or float
28、Any()函数
假设我们有一个记录列表,该记录跟踪约翰到达工作地点的时间。一个用例是我们想知道他本周是否有任何迟到的情况,在这种情况下,该any()功能非常方便。True如果布尔列表中的任何元素为,则此函数返回True。
>>> arrival_hours = {'Mon': 8.5, 'Tue': 8.75, 'Wed': 9, 'Thu': 8.5, 'Fri': 8.5}
>>> arrival_checks = [x>8.75 for x in arrival_hours.values()]
>>> any(arrival_checks)
True
29、All()函数
按照上面的相同示例,我们还想知道他是否整周始终在9:30之前到达工作地点。要测试是否存在这种情况,我们可以使用all()函数,该函数True仅在布尔列表中的所有元素均为时返回True。
>>> arrival_checks_all = [x<9.5 for x in arrival_hours.values()]
>>> all(arrival_checks_all)
True
30、在文件上使用带关键字
在处理文件时,我们需要打开它,处理内容,然后关闭它。如果您在使用后没有关闭文件,则文件可能会在一段时间内不可用。with在这种情况下,关键字非常有用。如下所示,使用后该文件将自动关闭。
>>> with open('a_file.txt') as file:
... pass
...
>>> file.closed
True