
递推思想:
首先,从终点camp开始倒推前一站最少携带多少升水才能足够抵达camp
接下来逐步往前,每一站都按上面算法标记。
有几种路线可选,有不同的结果,该点标记取较小的

辅助引入坐标系表达取水点位置。
延展问题,A路线尝试编程解
# 递推:到达camp处恰好水喝完,倒推离开前一站至少有3升水!
# 依次往前类推,
s = [[0,0], [2,2],[6,3],[8,1],[11,3],[13,3],[16,0]]
s = s[::-1]
for i in range(len(s)-1):
d = s[i][0] - s[i+1][0]
v = s[i][1] - s[i+1][1]
if d + v <= 0:
s[i + 1][1] = 0
else:
s[i + 1][1] = abs(d+v)
print(s[-1][1])
print(s)
5
[[16, 0], [13, 0], [11, 0], [8, 2], [6, 1], [2, 3], [0, 5]]

棍子上1-9构成一个数字。棍子可以在一个或多个地方折断,然后重新排列成一个新的数字。例如,有一次中断,1 2 3 可以在1和2之间打破成2 3 1,或者在2和3之间分解成3 1 2。(注意 3 2 1 不可能通过折断一次就实现)
1 2 3 −→2 3 1 或3 1 2 共有两种序列实现
对于以下每个木棍和断裂次数,可以得到的最大数字的最后三位数字是多少?
A. 断点可以有2个,4 3 9 7 2 9 5 6
B. 断点可以有3个,4 3 9 7 2 9 5 6
C. 断点可以有4个,4 3 9 7 2 9 5 6
可以制作出的最大数字的最后三位数是多少?
心算更容易得到
A. 972,956,43
B. 97,956,43,2
C. 9,9,72,56,43
究竟什么是代码质量?
我们如何衡量它?我们如何提高代码质量并清理我们的 Python 代码?
代码质量一般指的是你的代码的功能和可维护性如何。在以下情况下,代码被认为是高质量的。
它能达到其目的
它的行为可以被测试
它遵循一致的风格
它是可以理解的
它不包含安全漏洞
有良好的文档记录
易于维护
由于我们已经在《Python中的测试》和《Python中的现代测试驱动开发》文章中讨论了前两点,本文的重点是第三点到第七点。
这篇文章探讨了如何用linters、代码格式化器和安全漏洞扫描器来提高Python代码的质量。
完整的Python指南:现代Python环境--依赖性和工作区管理Python中的测试现代Python中的测试驱动开发Python代码质量(本文!)Python类型检查记录Python代码和项目Python项目工作流程
Linters通过对源代码的分析来标记编程错误、bug、风格错误和可疑的结构。提示工具很容易设置,提供合理的默认值,并通过消除对风格有不同意见的开发人员之间的摩擦来改善整个开发人员的经验。
虽然品头论足是一种常见的做法,但它仍然被许多开发者所诟病,因为开发者往往是,嗯,意见过激。让我们看一个简单的例子。
numbers = []
while True:
answer = input('Enter a number: ')
if answer != 'quit':
numbers.append(answer)
else:
break
print('Numbers: %s' % numbers)
第二种写法
numbers = []
while (answer := input("Enter a number: ")) != "quit":
numbers.append(answer)
print(f"Numbers: {numbers}")
第三种写法
numbers = []
while True:
answer = input("Enter a number: ")
if answer == "quit":
break
numbers.append(answer)
print(f"Numbers: {numbers}")
哪一个更好?
就功能而言,它们是一样的。
你更喜欢哪一个?你项目的合作者更喜欢哪一个?
作为一个软件开发人员,你很可能在一个团队中工作。而且,在一个团队环境中,所有的开发人员遵循相同的编码标准是非常重要的。否则,要读懂别人的代码就更难了。代码审查的重点应该是更高层次的问题,而不是平凡的语法格式问题。
例如,如果你决定用感叹号来结束每个句子,那么读者就很难推断出语气。如果你更进一步,忽略了常见的标准,如大写字母和间距规则,你的句子将非常难以阅读。阅读你的文章会花费更多的脑力。你会失去读者和合作者。这与代码的情况类似。我们使用风格指南来使我们的开发者伙伴(包括我们自己)更容易推断出意图并与我们合作。
作为Python开发者,我们很幸运地拥有PEP-8风格指南,它提供了一套惯例、指南和最佳实践,使我们的代码更容易阅读和维护。它着重于命名规则、代码注释和布局问题(如缩进和空白)。举几个例子。
79个字符的最大行长
用空格代替制表符
小写的函数名
在提示工具方面,虽然有很多这样的工具,但大多数情况下,每个工具都是在代码逻辑或执行代码标准方面寻找错误。
代码逻辑--这些工具检查编程错误,执行代码标准,搜索代码气味,并检查代码复杂性。 Pyflakes和McCabe(复杂性检查器)是最流行的检查代码逻辑的工具。
代码风格 - 这些只是强制执行代码标准(基于PEP-8)。
Flake8
Flake8是一个围绕Pyflakes、pycodestyle和McCabe的包装器。
它可以像其他PyPI软件包一样被安装。
pip install flake8
假设你有以下代码保存在一个叫做my_module.py的文件中。
from requests import *
def get_error_message(error_type):
if error_type == 404:
return 'red'
elif error_type == 403:
return 'orange'
elif error_type == 401:
return 'yellow'
else:
return 'blue'
def main():
res = get('https://api.github.com/events')
STATUS = res.status_code
if res.ok:
print(f'{STATUS}')
else:
print(get_error_message(STATUS))
if __name__ == '__main__':
main()
运行该模块
python -m flake8 my_module.py
运行生成
my_module.py:1:1: F403 'from requests import *' used; unable to detect undefined names
my_module.py:3:1: E302 expected 2 blank lines, found 1
my_module.py:15:11: F405 'get' may be undefined, or defined from star imports: requests
my_module.py:25:1: E303 too many blank lines (4)
你也可能看到my_module.py:26:11: W292文件末尾没有换行错误,这取决于你的代码编辑器的配置。
对于每一次违反,都会打印一行,其中包含以下数据。
文件路径(相对于Flake8运行的目录)
行号
列号
违规规则的ID
规则的描述
以 F 开头的违规是来自 Pyflakes 的错误,而以 E 开头的违规是来自 pycodestyle。
在纠正了这些违规行为后,你应该有。
from requests import get
def get_error_message(error_type):
if error_type == 404:
return 'red'
elif error_type == 403:
return 'orange'
elif error_type == 401:
return 'yellow'
else:
return 'blue'
def main():
res = get('https://api.github.com/events')
STATUS = res.status_code
if res.ok:
print(f'{STATUS}')
else:
print(get_error_message(STATUS))
if __name__ == '__main__':
main()
除了PyFlakes和pycodestyle,你也可以用Flake8来检查循环复杂性。
例如,get_error_message函数的复杂性为4,因为有四个可能的分支(或代码路径)。
def get_error_message(error_type):
if error_type == 404:
return 'red'
elif error_type == 403:
return 'orange'
elif error_type == 401:
return 'yellow'
else:
return 'blue'
要强制执行最大复杂度为3或更低,请运行。
$ python -m flake8 --max-complexity 3 my_module.py
Flake8应该会失败。
my_module.py:4:1: C901 'get_error_message' 太复杂(4)
将代码改写成这样
def get_error_message(error_type):
颜色 = {
404:'红色'。
403: '橙色',
401: '黄色',
}
return colors[error_type] if error_type in colors else 'blue'.
Flake8现在应该通过了。
$ python -m flake8 --max-complexity 3 my_module.py
你可以通过Flake8强大的插件系统为其添加额外的检查。例如,为了执行PEP-8的命名规则,安装pep8-naming。
$ pip install pep8-naming
运行。
$ python -m flake8 my_module.py
你应该看到
my_module.py:15:6: N806 函数中的变量'STATUS'应该是小写的
修复。
def main():
res = get('https://api.github.com/events')
status = res.status_code
如果res.ok:
print(f'{status}')
否则。
print(get_error_message(status))
查看Awesome Flake8 Extensions,了解最受欢迎的扩展列表。
Pylama也是一个流行的linting工具,它和Flake8一样,把几个linters粘在一起。
代码格式化器
贷款人只是检查你的代码中的问题,而代码格式化器实际上是根据一套标准来重新格式化你的代码。
将你的代码保持在正确的格式中是一项必要的但又枯燥的工作,应该由计算机来完成。
为什么它是必要的?
遵循风格指南的格式良好的代码更容易阅读,这使得它更容易发现bug和加入新的开发人员。它还可以减少合并冲突。
可读性很重要--Python的禅意
同样,由于这是一项枯燥的工作,开发人员往往对此意见不一(制表符与空格,单引号与双引号,等等),使用代码格式化工具,根据一套标准自动将代码重新格式化到位。
isort
isort用于自动将你的代码中的导入分成以下几组。
标准库
第三方
本地
然后,组中的导入被单独按字母顺序排列。
python -m flake8 --max-complexity 3 my_module.py
my_module.py:4:1: C901 'get_error_message' is too complex (4)
def get_error_message(error_type):
colors = {
404: 'red',
403: 'orange',
401: 'yellow',
}
return colors[error_type] if error_type in colors else 'blue'
python -m flake8 --max-complexity 3 my_module.py
pip install pep8-naming
python -m flake8 my_module.py
网友评论