Python新手练习-PyBite

Python新手练习-PyBite

Bite 108 循环历遍可命名元祖计算总分(Loop over a dict of namedtuples calculating a total score)

有一个字典,字典中包含了不同颜色的pybite忍者腰带奖章,以及对应的分数及获得人数。需要构建一个函数,计算python所有忍者的总得分。

知识点:

  • collectionnametuple
  • 列表推导式

代码块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
from collections import namedtuple
BeltStats = namedtuple('BeltStats', 'score ninjas')
ninja_belts = {'yellow': BeltStats(50, 11),
'orange': BeltStats(100, 7),
'green': BeltStats(175, 1),
'blue': BeltStats(250, 5)}
def get_total_points(belts=ninja_belts):
"""Calculate the amount of points rewarded on PyBites given the
ninja_belts dictionary, formula: belt score x belt owners (aka ninjas)
(of course there are more points but let's keep it simple)
Make your code generic so if we update ninja_belts to include
more belts (which we do in the tests) it will still work.
Ah and you can get score and ninjas from the namedtuple with nice
attribute access: belt.score / belt.ninjas (reason why we get
you familiar with namedtuple here, because we love them and use
them all over the place!)
Return the total number of points int from the function."""
total_points = 0
for belt in belts.values():
scores = belt.score * belt.ninjas
total_points += scores
return total_points

列表推导式写法

1
return sum([belt[0] * belt[1] for belt in belts.values()])

Bite 109 健身字典查询及抛出异常(Workout dict lookups and raising an exception)

查询健身周计划的字典,并在日期输入键值错误时,抛出异常

知识点:

  • 抛出异常 -> exception
  • format
  • title()

代码块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
workout_schedule = {'Friday': 'Shoulders',
'Monday': 'Chest+biceps',
'Saturday': 'Rest',
'Sunday': 'Rest',
'Thursday': 'Legs',
'Tuesday': 'Back+triceps',
'Wednesday': 'Core'}
rest, chill, go_train = 'Rest', 'Chill out!', 'Go train {}'
def get_workout_motd(day):
"""Title case passed in day argument (monday or MONDAY -> Monday)
and check if it is in the given workout_schedule dict.
If it is there retrieve the workout, if not raise a KeyError.
Return the chill or go_train variable depending the retrieved
workout value ('Rest' or workout bla)
Trivia: /etc/motd is a file on Unix-like systems that contains
a 'message of the day'"""
try:
workout = workout_schedule[day.title()]
except KeyError:
raise KeyError('Workout does not exist.')
return chill if workout == rest else go_train.format(workout)

Bite 110 类型转换&处理异常(Type conversion and exception handling)

写一个函数,输入包含分子&分母,把分子&分母转换成整数的数据类型,然后分子除以分母。处理两种异常,输入值异常&分母为零。

知识点

  • ValueError
  • ZeroDivisonError
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def divide_numbers(numerator, denominator):
"""For this exercise you can assume numerator and denominator are of type
int/str/float.
Try to convert numerator and denominator to int types, if that raises a
ValueError reraise it. Following do the division and return the result.
However if denominator is 0 catch the corresponding exception Python
throws (cannot divide by 0), and return 0"""
try:
numerator = int(numerator)
denominator = int(denominator)
except ValueError:
raise
try:
return numerator / denominator
except ZeroDivisionError:
return 0

Bite 1 累加 N 个数字(Sum n numbers)

  • 输入:n个数字或者无输入
  • 计算:将所有输入的序列元素数字相加,计算它们总数。如果没有输入数字,则返回从 1、2、3、……到 100 的总数
  • 输出:总数

知识点

  • sum
  • range

思路:

  1. 判断 numbers 是否是 None,如果是None,计算并返回 1……100(range(1,101)) 的叠加总数
  2. 如果 numbers 不是 None,计算并返回所输入的数字的叠加总数

解决代码:

1
2
3
4
5
def sum_numbers(numbers=None):
if numbers is None:
return sum(range(1,101))
else:
return sum(numbers)

Bite 5 解析一个列表中的名字(Parse a list of names)

  • 输入:一个列表,包含一串名字的字符串
  • 计算:1. 对名字去重 2.按照surname倒序排序 3. 获取长度最短的 firstname
  • 输出:1.去重后的名字,每个单词首个字母大写 2. 返回排序后的名字列表 3.返回最短的首名 firstname

知识点

  • sorting
  • min
  • lambda
  • list comprehesions

思路:

  1. set()获取NAMES独特值(unique),(set 是 unordered),再用列表推导式,将每一个 set 中的元素 title(), 返回列表
  2. 匿名函数 lambda x: x.split(“ “),将NAMES的元素按照空格 whitespace 拆分成 firstname surname
  3. string[-1]切片获取列表中的倒数第一个元素
  4. sorted方法对元素进行排序,reverse=True(Desending order)
  5. 列表推导式,生成只包含 first name的列表。再用 min()返回最短的firstname

问题代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
NAMES = ['arnold schwarzenegger', 'alec baldwin', 'bob belderbos',
'julian sequeira', 'sandra bullock', 'keanu reeves',
'julbob pybites', 'bob belderbos', 'julian sequeira',
'al pacino', 'brad pitt', 'matt damon', 'brad pitt']
def dedup_and_title_case_names(names):
"""Should return a list of names, each name appears only once"""
pass
def sort_by_surname_desc(names):
"""Returns names list sorted desc by surname"""
names = dedup_and_title_case_names(names)
# ...
def shortest_first_name(names):
"""Returns the shortest first name (str).
You can assume there is only one shortest name.
"""
names = dedup_and_title_case_names(names)
# ...

测试代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from names import (NAMES, dedup_and_title_case_names,
sort_by_surname_desc, shortest_first_name)
def test_dedup_and_title_case_names():
names = dedup_and_title_case_names(NAMES)
assert names.count('Bob Belderbos') == 1
assert names.count('julian sequeira') == 0
assert names.count('Brad Pitt') == 1
assert len(names) == 10
assert all(n.title() in names for n in NAMES)
def test_sort_by_surname_desc():
names = sort_by_surname_desc(NAMES)
assert names[0] == 'Julian Sequeira'
assert names[-1] == 'Alec Baldwin'
def test_shortest_first_name():
assert shortest_first_name(NAMES) == 'Al'

解题代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def dedup_and_title_case_names(names):
"""Should return a list of names, each name appears only once"""
return [name.title() for name in set(names)]
def sort_by_surname_desc(names):
"""Returns names list sorted desc by surname"""
names = dedup_and_title_case_names(names)
return sorted(names, key = lambda x: x.split(" ")[-1] , reverse = True )
def shortest_first_name(names):
"""Returns the shortest first name (str).
You can assume there is only one shortest name.
"""
names = dedup_and_title_case_names(names)
return min([name.split(" ")[0] for name in names])

参考答案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
NAMES = ['arnold schwarzenegger', 'alec baldwin', 'bob belderbos',
'julian sequeira', 'sandra bullock', 'keanu reeves',
'julbob pybites', 'bob belderbos', 'julian sequeira',
'al pacino', 'brad pitt', 'matt damon', 'brad pitt']
def dedup_and_title_case_names(names):
"""Should return a list of names, each name appears only once"""
return list({name.title() for name in names})
def sort_by_surname_desc(names):
"""Returns names list sorted desc by surname"""
names = dedup_and_title_case_names(names)
return sorted(names,
key=lambda x: x.split()[-1],
reverse=True)
def shortest_first_name(names):
"""Returns the shortest first name (str).
You can assume there is only one shortest name.
"""
names = dedup_and_title_case_names(names)
names = [name.split()[0] for name in names]
return min(names, key=len)

缺漏处:

  • 第一个函数,用的是字典推导式。因为字典不允许重复 Key
  • 第三个函数,min()的key参数设置为 len

Bite 8 调换字母顺序(Rotate string characters)

  • 输入:字符串string&整数n
  • 计算:若整数大于0,则将前 n 个字母调换到末尾。/ 若整数小于0,则将后n 个字母调换到末尾。
  • 输出:调换后的字符串(rotated string)

知识点

  • slice切片
  • deque双端队列

代码测试

1
2
3
4
5
6
7
8
Last login: Wed Jul 10 14:50:31 on ttys004
adi0229 (adi0229 *) ~
>>> string = 'hello'
>>> string[2:] + string[:2]
'llohe'
>>> string[-2:] + string[:-2]
'lohel'

解决代码:

1
2
3
4
5
def rotate(string, n):
"""Rotate characters in a string.
Expects string and n (int) for number of characters to move.
"""
return string[n:] + string[:n]

Bite 15 列举 2 个序列(Enumerate 2 sequence)

  • 输入:2 个列表,包含名字和国家字段
  • 计算:列举2个列表的字段——名字和国家,根据索引位置,一一对应。
  • 输出:按照索引的数字顺序,打印出对应的列表字段。

知识点

  • enumerate列举,枚举
  • string formatting字符串格式

代码实例参考

enumerate列举,枚举

https://stackoverflow.com/questions/16326853/enumerate-two-python-lists-simultaneously/16326876

1
2
for index, (value1, value2) in enumerate(zip(data1, data2)):
print index, value1 + value2
  • string formatting字符串对齐

format方法中,使用<,>,^等符号来指定左对齐、右对齐或者居中。

1
2
>>> "{1:<15}{0:^10}{2:>15}".format(center, left_aligned, right_aligned)
'Left Align Centered Right Align'

python 3.6 的 f-string

1
2
>>> f"{left_aligned:<15}{center:^10}{right_aligned:>15}"
'Left Align Centered Right Align'

代码测试

1
2
3
4
5
6
7
8
9
Last login: Wed Jul 10 14:50:31 on ttys004
adi0229 (adi0229 *) ~
>>> names = 'Julian Bob PyBites Dante Martin Rodolfo'.split()
>>> countries = 'Australia Spain Global Argentina USA Mexico'.split()
>>> names
['Julian', 'Bob', 'PyBites', 'Dante', 'Martin', 'Rodolfo']
>>> countries
['Australia', 'Spain', 'Global', 'Argentina', 'USA', 'Mexico']

解决代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
names = 'Julian Bob PyBites Dante Martin Rodolfo'.split()
countries = 'Australia Spain Global Argentina USA Mexico'.split()
def enumerate_names_countries():
"""Outputs:
1. Julian Australia
2. Bob Spain
3. PyBites Global
4. Dante Argentina
5. Martin USA
6. Rodolfo Mexico"""
for index, (name, country) in enumerate(zip(names, countries)):
print("{0:<3}{1:<11}{2}".format(str(index+1)+'.',name,country))
enumerate_names_countries()
$ /Users/apple/anaconda3/envs/magenta/bin/python /Users/apple/Desktop/pybite_intro_08.py
1. Julian Australia
2. Bob Spain
3. PyBites Global
4. Dante Argentina
5. Martin USA
6. Rodolfo Mexico

思路:

  • zip打包,name和 country2 个可迭代的列表对象
  • 在 for 循环中,enumerate组合成索引序列
  • format指定第二个位置左对齐 11 个chars。第一个位置是调试出来的,字符串的间距3chars?

Bite 16 PyBite日期生成器(PyBites date generator)

  • 输入:2 个列表,包含名字和国家字段
  • 计算: 每年每一百天
  • 输出:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import datetime
from itertools import islice
from gendates import gen_special_pybites_dates
def test_gen_special_pybites_dates():
gen = gen_special_pybites_dates()
dates = list(islice(gen, 100))
expected = [datetime.datetime(2017, 3, 29, 0, 0),
datetime.datetime(2017, 7, 7, 0, 0),
datetime.datetime(2017, 10, 15, 0, 0),
datetime.datetime(2017, 12, 19, 0, 0),
datetime.datetime(2018, 1, 23, 0, 0),
datetime.datetime(2018, 5, 3, 0, 0),
datetime.datetime(2018, 8, 11, 0, 0),
datetime.datetime(2018, 11, 19, 0, 0),
datetime.datetime(2018, 12, 19, 0, 0),
datetime.datetime(2019, 2, 27, 0, 0)]
assert dates[:10] == expected

知识点

  • islice

http://funhacks.net/2017/02/13/itertools/

1
islice(iterable, [start,] stop [, step])
1
2
3
4
5
6
7
8
9
10
11
12
>>> from itertools import count, islice
>>>
>>> list(islice([10, 6, 2, 8, 1, 3, 9], 5))
[10, 6, 2, 8, 1]
>>>
>>> list(islice(count(), 6))
[0, 1, 2, 3, 4, 5]
>>>
>>> list(islice(count(), 3, 10))
[3, 4, 5, 6, 7, 8, 9]
>>> list(islice(count(), 3, 10 ,2))
[3, 5, 7, 9]

关于itertool里的count

官方文档:https://docs.python.org/zh-cn/3/library/itertools.html#itertools.count

1
2
3
4
5
6
7
def count(start=0, step=1):
# count(10) --> 10 11 12 13 14 ...
# count(2.5, 0.5) -> 2.5 3.0 3.5 ...
n = start
while True:
yield n
n += step
1
itertools.count(start=0, step=1)

可见,count()返回 0 开头,1 为步长的序列。

上面的代码块,最后一行代码解读,count()返回一个可迭代对象(),开始索引是 3,结束索引 10,step 步长是 2。
所以,加上list()之后,输出是[3,5,7,9]

datetime.datetime

https://docs.python.org/3/library/datetime.html

一个datetime对象

1
class datetime.datetime(year, month, day, hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold=0)

年月日是必需参数。测试脚本里的 2 个0,指的是小时hour和分钟minute

1
2
3
4
5
6
7
from datetime import datetime
PYBITES_BORN = datetime(year=2016, month=12, day=19)
def gen_special_pybites_dates():
pass

datetime

https://www.guru99.com/date-time-and-datetime-classes-in-python.html#5

1
2
3
4
5
6
7
>>> from datetime import datetime
>>> datetime.today()
datetime.datetime(2019, 7, 12, 19, 27, 59, 688655)
>>> from datetime import timedelta
>>> timedelta(days=100)
datetime.timedelta(100)
>>> datetime.timedelta(100)

语言问题,对题目具体要求不甚了解,代码没写出,因此直接看了答案,恍然大悟:

1
2
3
4
5
6
7
8
9
10
11
from datetime import datetime, timedelta
PYBITES_BORN = datetime(year=2016, month=12, day=19)
def gen_special_pybites_dates():
days = 0
while True:
days += 1
if days % 100 == 0 or days % 365 == 0:
yield PYBITES_BORN + timedelta(days=days)

思路:

  1. 新建 Days 变量,初始赋值 0
  2. 永久循环,每次循环迭代变量+1
  3. 当days 是 100 或者 365 的整数时,返回 PYBITES_BORN + 当前天数的时间 delta

反思:

  • 查询timedelta()等相关函数知识,是必要的
  • 需要强化英语语言的理解水平

Bite 19 写一个简单的属性(Write a Simple Property)

  • 输入:格式为字符串的名称(name),格式为 datetime 的过期时间(expires)
  • 计算:当前时间,是否大于过期时间。
  • 输出:一个名为番茄钟的类(class),包含过期与否的布尔值属性

知识点:

  • datetime
  • properties

一个疑问,如何指定函数参数的类型?

1
2
def pick(l: list, index: int) -> int:
return l[index]

从上面的示例可知,pick 函数输入 2 个参数,一个l列表,一个index整数,输出是整数(integer)。

另一个疑问,如何传入datetime类型的对象?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from datetime import datetime
class Person:
def __init__(self, first_name, last_name, birth_date):
self.first_name = first_name
self.last_name = last_name
self.birth_date = datetime.strptime(birth_date, '%b %d %Y')
def fullname(self):
return self.first + ' ' + self.last_name
person = Person('John', 'Doe', 'Jun 1 2005')
print(person.birth_date)

输出

1
2005-06-01 00:00:00

想法:判断 -> NOW(当前时间) 大于> expires(过期时间),返回布尔值

解题过程:

查看datetime.now()的输出

1
2
>>> datetime.now()
datetime.datetime(2019, 7, 15, 14, 13, 34, 943274)

检索“compare date python”,获得示例代码

来源:https://www.geeksforgeeks.org/comparing-dates-python/

1
2
3
4
5
6
7
8
9
10
11
import datetime
# date in yyyy/mm/dd format
d1 = datetime.datetime(2018, 5, 3)
d2 = datetime.datetime(2018, 6, 1)
# Comparing the dates will return
# either True or False
print("d1 is greater than d2 : ", d1 > d2)
print("d1 is less than d2 : ", d1 < d2)
print("d1 is not equal to d2 : ", d1 != d2)

测试脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from datetime import timedelta
from simple_property import Promo, NOW
def test_promo_expired():
past_time = NOW - timedelta(seconds=3)
twitter_promo = Promo('twitter', past_time)
assert twitter_promo.expired
def test_promo_not_expired():
future_date = NOW + timedelta(days=1)
newsletter_promo = Promo('newsletter', future_date)
assert not newsletter_promo.expired

解题代码

1
2
3
4
5
6
7
8
9
10
11
from datetime import datetime
NOW = datetime.now()
class Promo:
def __init__(self, name, datetime):
self.name = name
self.datetime = datetime
self.expired = NOW-datetime

显然,函数的「参数格式」以及「datetime」格式转化,在本题中不需要处理。
只需要 -> 添加 self.expired 属性,通过判断时间大小,返回 True&False 的布尔值

Bite 21 查询一个嵌入式数据结构(Query a nested data structure)

  • 输入:一个cars字典
  • 计算:1、根据字符的 key,获取value 2、匹配字符串 3、根据阿拉伯字母顺序排序
  • 输出:1、所有 jeeps 的模型名称 2、获取每个制造商的第一种车型 3、获取所有名称中包含字符串Trail的车型 3、按照阿拉伯字母对车型字典中的值进行排序
  • 根据论坛讨论,2018.12.18日的讨论,每个函数都传入 cars 字典作为局部变量(Scope local),这样写法更好。

知识点

  • dictionary comprehesions
  • sorted

任务 1

获取所有 jeeps 的型号名称,返回相应字符串

1
2
3
4
def get_all_jeeps(cars=cars):
"""return a comma + space (', ') separated string of jeep models
(original order)"""
pass

思路:

join()将序列中的元素以指定字符串连接生成新的字符串,输出:’, ‘(逗号+空格)分割的 Jeep models(吉普车型号)

1
str.join(sequence)

解题代码块:

1
2
3
4
5
6
7
8
9
def get_all_jeeps(cars=cars):
"""return a comma + space (', ') separated string of jeep models
(original order)"""
# print(', '.join(cars['Jeep']))
return ', '.join(cars['Jeep'])
get_all_jeeps()

终端输出

1
Grand Cherokee, Cherokee, Trailhawk, Trackhawk

任务 2

获取所有制造商的第一个车型名称,返回相应列表 list

1
2
3
def get_first_model_each_manufacturer(cars=cars):
"""return a list of matching models (original ordering)"""
pass

解题代码块:

1
2
3
4
5
6
7
8
9
10
11
def get_all_matching_models(cars=cars, grep='trail'):
"""return a list of all models containing the case insensitive
'grep' string which defaults to 'trail' for this exercise,
sort the resulting sequence alphabetically"""
grep_list = []
for models in cars.values():
for model in models:
if grep.casefold() in model.casefold():
grep_list.append(model)
return sorted(grep_list)

终端输出

1
['Falcon', 'Commodore', 'Maxima', 'Civic', 'Grand Cherokee']

任务 3

获取所有包含某段字符串(本例是trail)的型号名称,按照阿拉伯字母顺序排序,返回相应列表

1
2
3
4
5
def get_all_matching_models(cars=cars, grep='trail'):
"""return a list of all models containing the case insensitive
'grep' string which defaults to 'trail' for this exercise,
sort the resulting sequence alphabetically"""
pass

思路:

  1. 新建一个空的列表
  2. 使用in运算符,历遍所有字典中的values(注:case-insensitive,意思是大小写不敏感,所以用casefold()转换),判断其对应的字符串中,是否包含grep所对应的’trail’字符串
  3. 如果包含’trail’添加入空列表之中,最后,按照阿拉伯字母排序(注:sorted(list),如果列表元素是数字,那么默认是按照增序排序。如果列表元素是字符串,则按照字母顺序(alphabetical order)排序)。

解题代码块:

1
2
3
4
5
6
7
8
9
10
11
def get_all_matching_models(cars=cars, grep='trail'):
"""return a list of all models containing the case insensitive
'grep' string which defaults to 'trail' for this exercise,
sort the resulting sequence alphabetically"""
grep_list = []
for models in cars.values():
for model in models:
if grep.casefold() in model.casefold():
grep_list.append(model)
return sorted(grep_list)

终端输出

1
2
['Trailblazer', 'Trailhawk']
['Accord', 'Commodore', 'Falcon']

任务 4

获取型号名称,按照阿拉伯字母顺序排序,返回相应字典

1
2
3
4
5
def get_all_matching_models(cars=cars, grep='trail'):
"""return a list of all models containing the case insensitive
'grep' string which defaults to 'trail' for this exercise,
sort the resulting sequence alphabetically"""
pass

思路:

  1. 新建一个空的字典
  2. 历遍cars字典,获取它的所有键值
  3. 按照所有键值,添加入新字典,并使用sorted方法来重新按字母排序 value 里的元素。

解题代码块:

1
2
3
4
5
6
7
8
9
def sort_car_models(cars=cars):
"""return a copy of the cars dict with the car models (values)
sorted alphabetically"""
cars_sorted = {}
for key, value in cars.items():
cars_sorted[key] = sorted(value)
return cars_sorted

最后通关成功:

小结:

  • Debug 时,务必查看test_cars.py,里面详细写明了代码是如何得到验证的,也熟悉了 asert。在任务三时,发现会另外传入一个’CO’,包含大写字母的字符串。这时候,把原来的变量grep“加上casefold便通过测试了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
from cars import (get_all_jeeps, get_first_model_each_manufacturer,
get_all_matching_models, sort_car_models)
def test_get_all_jeeps():
expected = 'Grand Cherokee, Cherokee, Trailhawk, Trackhawk'
actual = get_all_jeeps()
assert type(actual) == str
assert actual == expected
def test_get_first_model_each_manufacturer():
actual = get_first_model_each_manufacturer()
expected = ['Falcon', 'Commodore', 'Maxima', 'Civic', 'Grand Cherokee']
assert actual == expected
def test_get_all_matching_models_default_grep():
expected = ['Trailblazer', 'Trailhawk']
# sorting requirement might be missed and is not essential for this method
assert sorted(get_all_matching_models()) == expected
def test_get_all_matching_models_different_grep():
expected = ['Accord', 'Commodore', 'Falcon']
# sorting requirement might be missed and is not essential for this method
assert sorted(get_all_matching_models(grep='CO')) == expected
def test_sort_dict_alphabetically():
actual = sort_car_models()
# Order of keys should not matter, two dicts are equal if they have the
# same keys and the same values.
# The car models (values) need to be sorted here though
expected = {
'Ford': ['Fairlane', 'Falcon', 'Festiva', 'Focus'],
'Holden': ['Barina', 'Captiva', 'Commodore', 'Trailblazer'],
'Honda': ['Accord', 'Civic', 'Jazz', 'Odyssey'],
'Jeep': ['Cherokee', 'Grand Cherokee', 'Trackhawk', 'Trailhawk'],
'Nissan': ['350Z', 'Maxima', 'Navara', 'Pulsar'],
}
assert actual == expected

Bite 26 字典推导式 -> 酷炫(Dictionary comprehensions are awesome)

字典推导式与列表推导式相似,只是构建的是字典,而不是列表。它是方便快速地操作键和值的方法。通常只有一行代码,或者在检查 PEP8 规范之后是两行代码。
知识点:
输入:原始字典,排除的键值
计算:复制字典,匹配排除的键值,并从字典从删除
输出:排除对应键之后的字典

  • collectionnametuple
  • 列表推导式

代码块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
bites = {6: 'PyBites Die Hard',
7: 'Parsing dates from logs',
9: 'Palindromes',
10: 'Practice exceptions',
11: 'Enrich a class with dunder methods',
12: 'Write a user validation function',
13: 'Convert dict in namedtuple/json',
14: 'Generate a table of n sequences',
15: 'Enumerate 2 sequences',
16: 'Special PyBites date generator',
17: 'Form teams from a group of friends',
18: 'Find the most common word',
19: 'Write a simple property',
20: 'Write a context manager',
21: 'Query a nested data structure'}
exclude_bites = {6, 10, 16, 18, 21}
def filter_bites(bites=bites, bites_done=exclude_bites):
"""return the bites dict with the exclude_bites filtered out"""
pass
1
2
3
def filter_bites(bites=bites, bites_done=exclude_bites):
"""return the bites dict with the exclude_bites filtered out"""
return { k:v for k,v in bites.items() if k not in bites_done }

查看了例子

1
2
3
4
5
6
7
# dict comprehension example to reverse key:value pair in a dictionary
>f_dict = {f:i for i,f in enumerate(fruits)}
>f_dict
{'apple': 0, 'banana': 2, 'cherry': 3, 'mango': 1}
# dict comprehension to reverse key:value pair in a dictionary
>{v:k for k,v in f_dict.items()}
{0: 'apple', 1: 'mango', 2: 'banana', 3: 'cherry'}

思路:若 k 不在给定的 set 里,便添加入新的字典之后。第一次拼写少了in,之后通关。

1
2
3
4
5
6
def filter_bites(bites=bites, bites_done=exclude_bites):
"""return the bites dict with the exclude_bites filtered out"""
return { k:v for k,v in bites.items() if k not in bites_done }
a = filter_bites(bites=bites, bites_done=exclude_bites)
print(a)

To do

改成每题一小篇,以固定标题的形式,组织成专栏,写给六个月前的自己,帮助 0 基础,甚至是负基础的小白入门同学朋友。

重新调整笔记结构,让别人更易读,而不是偏私人的呢喃。

changelog

2019.03.02 init pybite108

2019.03.05 update pybite109

2019.03.08 update pybite110

2019.03.12 update pybite8

2019.03.16 update pybite15

2019.03.19 update pybite16

2019.03.20 update pybite19

2019.03.22 update pybite21

2019.03.23 update pybite26

2019.03.24 update pybite1

2019.03.27 update pybite5