|
1 | 1 | ---
|
2 |
| -id: |
3 |
| -title: "[译] [XXX] XXXXXXXXXXXXXXXX" |
| 2 | +id: 39 |
| 3 | +title: "[译] [304] 一个函数的合理任务应该是什么样的?" |
4 | 4 | ---
|
5 | 5 |
|
6 | 6 |
|
7 | 7 | ## 3.4 What’s a reasonable task for a function?
|
| 8 | +## 3.4 一个函数的合理任务应该是什么样的? |
8 | 9 |
|
9 | 10 | There’s no clear rule for what makes a good function, but there are some intuitions and recommendations we can share. Make no mistake, though: identifying good functions is a skill that takes time and practice. To help you with this, in this section we’ll outline our recommendations and provide you with some good and bad examples to help build that intuition. Then, in Section 3.5, we’ll show you a bunch of examples of how to write good functions.
|
10 | 11 |
|
| 12 | +好的函数并没有固定的标准,但我们能提供一些直观的建议和指导。需要明确的是,辨别优秀的函数是一种需要时间积累和实践锻炼的能力。在本节中,我们会简要介绍我们的建议,并给出一些好与坏的实例,以助于培养你们的这种直觉。接下来,在第三章的第五节中,我们会提供一系列编写优质函数的实例。 |
| 13 | + |
11 | 14 | ### 3.4.1 Attributes of good functions
|
| 15 | +### 3.4.1 良好函数的特征 |
12 | 16 |
|
13 | 17 | Here are some guidelines that we believe will help you see what makes a good function:
|
14 | 18 |
|
| 19 | +下面提供的这些指导原则,我们相信将有助于你洞察怎样设计出一个良好的函数: |
15 | 20 |
|
16 | 21 | * **One clear task to perform.** If they are leaf functions, this might be something like, “compute the volume of a sphere”, “find the largest number in a list”, or “check to see if a list contains a specific value.” Non-leaf functions can achieve more broad goals, like “update the game graphics” or “collect and sanitize input from the user”. Non-leaf functions should still have a particular goal in mind but are designed knowing they will likely call other functions to achieve their goal.
|
17 | 22 |
|
| 23 | +* **执行一项明确的任务。** 以叶子函数为例,这可能是“计算一个球体的体积”、“从列表中找出最大的数字”或是“检查一个列表是否包含某个特定值”。对于非叶子函数,它们可能承担更为宽泛的目标,例如“刷新游戏的视觉效果”或“搜集并净化用户输入”。尽管非叶子函数有明确的目标,但其设计时已考虑到可能会调用其他函数来共同完成任务。 |
| 24 | + |
18 | 25 | * **Clearly defined behavior.** The task “find the largest number in a list” is clearly defined. If I gave you a list of numbers and asked you for the largest number, you know what you should do. In contrast, the task “find the best word in the list” is poorly defined as stated. You need more information – what's the “best” word? Is it the longest, the one that uses the fewest vowels, the one that doesn’t share any of the same letters as “Leo” or “Dan”? You get the point; subjective tasks aren’t great for computers. Instead, we could write the function “find the word in the list that has the most characters” as what is expected is well defined. Often programmers can’t put all the particulars of a function just in the name, so they fill in the details in the docstring to clarify its use. If you find yourself having to write more than a few sentences to describe the functions behavior, the task is probably too much for a single function.
|
19 | 26 |
|
| 27 | +* **定义明确的行为。** “在列表中寻找最大的数字”这个任务定义得很清楚。假如我给你一组数字,要你找出其中最大的一个,你会知道该如何着手。而“找出列表中最佳的单词”这一任务,表述得就过于模糊。你需要额外的信息——什么样的单词是“最佳”的?是最长的,还是使用元音最少的,或是与“Leo”和“Dan”没有任何相同字母的?这就说明了问题;对于计算机而言,主观性的任务并不合适。因此,我们可以设计一个函数,名为“找出列表中字符数最多的单词”,这样的预期结果就非常明确。程序员们往往无法仅通过函数名来涵盖函数的所有细节,所以他们会在函数的文档字符串中补充详细信息,以便阐明其具体用途。如果你发现自己需要写很多句话来描述一个函数的行为,那么这个任务很可能超出了一个函数所能承载的范围。 |
| 28 | + |
20 | 29 | * **Short in number of lines of code.** We’ve heard different rules over the years for the length of functions, informed by different company style guidelines. The lengths we’ve heard vary from 12 lines to 20 lines of Python code as the maximum number of lines. In these rules, the number of lines is being used as a proxy for code complexity and it’s not a bad general rule of thumb. As programmers ourselves, we both apply similar rules to our code to ensure the complexity doesn’t get out of hand. With Copilot, we can use this as a guide as well. If you ask Copilot for a function and it gives you back 50 lines of code, this probably isn’t a good function name or task and, as we discussed earlier, that many lines of code are likely to have errors anyway.
|
21 | 30 |
|
| 31 | +* **代码行数宜简短。** 多年来,我们了解到不同公司的风格指南对函数长度有着不同的规则。我们听到单个 Python 函数的最大行数限制,从 12 到 20 不等。这些规则中,把行数作为衡量代码复杂度的一个参考指标,是一个不错的通用原则。我们作为程序员,在编写代码时也会遵循类似的准则,以确保复杂度不会过高。在使用 Copilot 时,我们同样可以参考这一准则。如果你要求 Copilot 生成一个函数,而它返回了 50 行代码,这很可能意味着函数命名或任务描述不够好;而且如我们之前所讨论的,这么多行代码很可能本身就存在错误。 |
| 32 | + |
22 | 33 | * **General value over specific use.** A function that returns the number of values in a list that are greater than 1 might be a specific need for a part of your program, but there’s a way to make this better. The function should be rewritten to return the number of values in the list that are greater than another parameter. The new function would work for your use case (give the function 1 for the 2nd parameter) and for any other value than 1. We strive to have functions be as simple, but as powerful as possible.
|
23 | 34 |
|
| 35 | +* **追求通用性而非定制化。** 设计一个函数,如果它仅返回列表中大于 1 的元素数量,这可能只是满足了某个程序的某个具体需求。然而,我们可以让它变得更好:重构该函数,使其能够返回列表中大于某个给定参数的元素数量。这样的新函数不仅能够适应你的特定场景(只需将第二个参数设为 1),还能适应任何其他数值。我们的目标是让函数在保持简洁的同时,发挥最大的功效。 |
| 36 | + |
24 | 37 | * **Clear input and output.** You generally don’t want a lot of parameters. That doesn’t mean you can’t have a lot of input though. A single parameter could be a list of items (we’ll talk more about lists soon). It does mean that you want to find ways to keep the number of inputs to a minimum. You can only return one thing, but again, you can return a list so you aren’t as limited as it may appear. But if you find yourself writing a function that sometimes returns a list, sometimes returns a single value, and sometimes returns nothing, that’s probably not a good function.
|
25 | 38 |
|
| 39 | +* **清晰的输入与输出。** 通常情况下,你并不希望函数有太多的参数。这并不是说你不能接受大量的输入数据。例如,一个参数可以是一个项目列表(我们之后会详细讨论列表)。这样做的目的是为了尽量减少输入的数量。虽然函数只能返回一个结果,但由于可以返回列表,所以你实际上并不像看起来那样受限。但如果发现自己编写的函数有时返回列表,有时又返回单个值,有时则不返回任何东西,那么这个函数很可能设计得不够合理。 |
| 40 | + |
26 | 41 | ### 3.4.2 Examples of good (and bad) leaf functions
|
| 42 | +### 3.4.2 一些正面例子(和反面例子) |
27 | 43 |
|
28 | 44 | Here are examples of good leaf functions:
|
29 | 45 |
|
| 46 | +以下是关于叶子函数的一些正面例子: |
| 47 | + |
30 | 48 | * _Compute the volume of a sphere_ —- given the sphere’s radius, return its volume.
|
31 | 49 |
|
| 50 | +* “计算球体体积” —- 提供球的半径,便能得出其体积。 |
| 51 | + |
32 | 52 | * _Find the largest number in a list_ —- given a list, return the largest value.
|
33 | 53 |
|
34 |
| -* _Check to see if a list contains a specific value_ —- given a list and a value, return true if the list contains the value and false if it does not. |
| 54 | +* “找出列表中的最大数” —— 给定一个列表,返回其中的最大值。 |
| 55 | + |
| 56 | +* _Check to see if a list contains a specific value_ —- given a list and a value, return `true` if the list contains the value and `false` if it does not. |
| 57 | + |
| 58 | +* “检查列表中是否存在某个值” —— 提供一个列表和一个特定的值,若列表中含有该值,函数返回 `true`;若不含有,返回 `false`。 |
35 | 59 |
|
36 | 60 | * _Print the state of the checkers game_ —- given a 2D list representing the game board, output the game board to the screen in text.
|
37 | 61 |
|
| 62 | +* “打印跳棋游戏状态” —— 给定一个二维列表代表游戏棋盘,在屏幕上以文本形式输出棋盘状态。 |
| 63 | + |
38 | 64 | * _Insert a value in a list_ -— given a list, a new value, and a location in the list, return a new list that is the old list with the new value inserted at the desired location.
|
39 | 65 |
|
| 66 | +* “在列表中插入一个值” —— 给定一个列表、一个新值以及列表中的位置,返回一个新的列表,新列表是旧列表在指定位置插入新值后的版本。 |
| 67 | + |
40 | 68 | Here are examples of bad leaf functions and our reasons for why they are bad:
|
41 | 69 |
|
| 70 | +以下是一些反面例子,我们也解释了它们不好的原因: |
| 71 | + |
42 | 72 | * _Request a user’s tax information and return the amount they owe this year._ -- Perhaps in some countries this wouldn’t be too bad, but we can’t imagine this as a single function in either the United States or Canada given the complexity of the tax rules!
|
43 | 73 |
|
| 74 | +* “请求用户的税务信息并返回他们今年应缴的税款” —— 或许在某些国家,这个场景尚可接受;但如果在美国或加拿大,考虑到税收制度的复杂性,我们很难将其设想为一个简单的功能。 |
| 75 | + |
44 | 76 | * _Identify the largest value in the list and remove that value from the list._ -- This might not seem so bad, but it’s really doing two things. The first is to find the largest value in the list. The second is to remove a value from the list. We’d recommend two leaf functions, one that finds the largest and one that removes the value from the list. However, this might make a good non-leaf function if your program needs to perform this task frequently.
|
45 | 77 |
|
| 78 | +* “识别列表中的最大值并将其从列表中删除” —— 这种做法乍一看似乎没什么不妥,但其实它同时完成了两个任务。首先是寻找列表中的最大数值,其次是将该数值从列表中剔除。我们推荐将其拆分为两个简单的叶子函数,一个负责查找最大值,另一个负责删除指定值。当然,如果你的程序频繁需要进行这一操作,将其作为一个复合函数也是一个不错的选择。 |
| 79 | + |
46 | 80 | * (Thinking of our dataset from Chapter 2) _Return the names of the quarterbacks with more than 4000 yards of passing in the dataset._ -- This has too much specificity. Without a doubt, the number 4000 should be a parameter. But it’d likely be better to make a function that takes as input the position (quarterback, running back), the statistic (passing yards, games played), and the cutoff that we care about (4000, 8000), all as parameters. This new function would provide far more capability than the original, allowing a user to call the function to determine not only the names of particular quarterbacks who threw for more than 4000 yards, but also running backs who had more than 12 rushing touchdowns.
|
47 | 81 |
|
| 82 | +* (回想第二章提到的数据集)“列出传球码数超过 4000 码的四分卫姓名” —— 此函数过于专门化。数字 4000 无疑应作为一个参数。不过,更优的做法是构建一个函数,它将接收诸如位置(四分卫、跑卫)、统计数据(传球码数、比赛次数)以及我们所关注的界限值(4000、8000)等参数。这样的新函数将大大扩展其应用范围,用户不仅可以利用它来查询那些传球码数超过 4000 码的四分卫,还能找出超过12次冲球达阵的跑卫。 |
| 83 | + |
48 | 84 | * _Determine the best movie of all time._ -- This is too vague. Best movie by what definition? What movies should it consider? A better version of this might be a function that determines the highest rated movie by users given at least a minimum number of ratings. This function would likely be part of a larger program where the function would have, as input, data from a movie database (say IMDB) and minimum number of user ratings. The output of the function would be the highest rated movie that has at least as many ratings as specified.
|
49 | 85 |
|
| 86 | +* “选出史上最佳影片” -- 这个任务描述过于宽泛。最佳影片是根据什么标准来评定的呢?需要考虑哪些电影作品?一个更佳的方案是设计一个函数,它能够在满足最低评分人数要求的前提下,找出平均评分最高的电影。这个函数可能是某个更庞大程序的组成部分,其输入数据来自电影资料库(例如 IMDB)以及一个用户评分的最小阈值。输出结果则是达到规定评分人数且评分最高的那一部。 |
| 87 | + |
50 | 88 | * _Play Call of Duty_. -- This might be the `main` function in the large code base for the game _Call of Duty_, but it is definitely not a leaf function.
|
| 89 | + |
| 90 | +* “玩《使命召唤》” -- 这可能是《使命召唤》游戏的大型代码库中 `main` 主函数,但它肯定不是一个叶子函数。 |
0 commit comments