You’ve made it past the phone call with the recruiter, and now it’s time to show that you know how to solve problems with actual code. Whether it’s a HackerRank exercise, a take-home assignment, or an onsite whiteboard interview, this is your moment to prove your coding interview skills.

您已经与招聘人员通了电话,现在该展示您知道如何解决实际代码问题了。 无论是HackerRank练习,带回家的作业还是现场白板面试,这都是您证明自己的编码面试技巧的时刻。

But interviews aren’t just about solving problems: they’re also about showing that you can write clean production code. This means that you have a deep knowledge of Python’s built-in functionality and libraries. This knowledge shows companies that you can move quickly and won’t duplicate functionality that comes with the language just because you don’t know it exists.

但是面试不仅仅是解决问题:还表明您可以编写干净的生产代码。 这意味着您对Python的内置功能和库有深入的了解。 这些知识向公司表明,您可以快速采取行动,不会因为您不知道该语言的存在而复制该语言附带的功能。

At Real Python, we’ve put our heads together and discussed what tools we’re always impressed to see in coding interviews. This article will walk you through the best of that functionality, starting with Python built-ins, then Python’s native support for data structures, and finally Python’s powerful (and often underappreciated) standard library.

在Real Python中,我们齐心协力,讨论了在编程采访中总是给我们留下深刻印象的工具。 本文将向您介绍最佳功能,从Python内置功能开始,然后是Python对数据结构的本机支持,最后是Python强大的(常常被低估的)标准库。

In this article, you’ll learn how to:

在本文中,您将学习如何:

  • Use enumerate() to iterate over both indices and values
  • Debug problematic code with breakpoint()
  • Format strings effectively with f-strings
  • Sort lists with custom arguments
  • Use generators instead of list comprehensions to conserve memory
  • Define default values when looking up dictionary keys
  • Count hashable objects with the collections.Counter class
  • Use the standard library to get lists of permutations and combinations
  • 使用enumerate()遍历索引和值
  • 使用breakpoint()调试有问题的代码
  • 使用f字符串有效地格式化字符串
  • 使用自定义参数对列表进行排序
  • 使用生成器而不是列表推导来节省内存
  • 查找字典键时定义默认值
  • 使用collections.Counter类对可哈希对象进行计数
  • 使用标准库获取排列和组合的列表

Free Bonus: 5 Thoughts On Python Mastery, a free course for Python developers that shows you the roadmap and the mindset you’ll need to take your Python skills to the next level.

免费奖金: 关于Python精通的5个想法 ,这是针对Python开发人员的免费课程,向您展示了将Python技能提升到新水平所需的路线图和心态。

为作业选择合适的内置功能 (Select the Right Built-In Function for the Job)

Python has a large standard library but only a small library of built-in functions, which are always available and don’t need to be imported. It’s worth going through each one, but until you get the chance to do so, here are a few built-in functions worth understanding how to use, and in the case of some of them, what alternatives to use instead.

Python有一个很大的标准库,但是只有一个很小的内置函数库,这些函数始终可用,不需要导入。 值得一读,但是直到您有机会这样做之前,这里有一些内置函数值得了解如何使用,并且在其中一些情况下,可以使用哪些替代方法。

enumerate()而不是range()迭代 (Iterate With enumerate() Instead of range())

This scenario might come up more than any other in coding interviews: you have a list of elements, and you need to iterate over the list with access to both the indices and the values.

这种情况在编写代码采访中可能比其他情况要多:您有一个元素列表,并且需要在访问索引和值的同时迭代列表。

There’s a classic coding interview question named FizzBuzz that can be solved by iterating over both indices and values. In FizzBuzz, you are given a list of integers. Your task is to do the following:

有一个名为FizzBu​​zz的经典编码面试问题,可以通过迭代索引和值来解决。 在FizzBu​​zz中,将为您提供一个整数列表。 您的任务是执行以下操作:

  1. Replace all integers that are evenly divisible by 3 with "fizz"
  2. Replace all integers divisible by 5 with "buzz"
  3. Replace all integers divisible by both 3 and 5 with "fizzbuzz"
  1. "fizz"替换所有可以被3整除的整数
  2. 将所有可被5整除的整数替换为"buzz"
  3. "fizzbuzz"替换所有可被35整除的整数

Often, developers will solve this problem with range():

通常,开发人员会使用range()解决此问题:

>>>

>>> numbers = [45, 22, 14, 65, 97, 72]
>>> for i in range(len(numbers)):
...     if numbers[i] % 3 == 0 and numbers[i] % 5 == 0:
...         numbers[i] = 'fizzbuzz'
...     elif numbers[i] % 3 == 0:
...         numbers[i] = 'fizz'
...     elif numbers[i] % 5 == 0:
...         numbers[i] = 'buzz'
...
>>> numbers
['fizzbuzz', 22, 14, 'buzz', 97, 'fizz']

>>>

Range allows you to access the elements of numbers by index and is a useful tool for some situations. But in this case, where you want to get each element’s index and value at the same time, a more elegant solution uses enumerate():

范围允许您按索引访问numbers元素,并且在某些情况下是有用的工具。 但是在这种情况下,如果您想同时获取每个元素的索引和值,则可以使用enumerate()实现更优雅的解决方案:

>>>

>>> numbers = [45, 22, 14, 65, 97, 72]
>>> for i, num in enumerate(numbers):
...     if num % 3 == 0 and num % 5 == 0:
...         numbers[i] = 'fizzbuzz'
...     elif num % 3 == 0:
...         numbers[i] = 'fizz'
...     elif num % 5 == 0:
...         numbers[i] = 'buzz'
...
>>> numbers
['fizzbuzz', 22, 14, 'buzz', 97, 'fizz']

>>>

For each element, enumerate() returns a counter and the element value. The counter defaults to 0, which conveniently is also the element’s index. Don’t want to start your count at 0? Just use the optional start parameter to set an offset:

对于每个元素, enumerate()返回一个计数器和元素值。 计数器默认为0 ,这也是元素的索引。 不想从0开始计数? 只需使用可选的start参数来设置偏移量:

>>>

>>> numbers = [45, 22, 14, 65, 97, 72]
>>> for i, num in enumerate(numbers, start=52):
...     print(i, num)
...
52 45
53 22
54 14
55 65
56 97
57 72

>>>

By using the start parameter, we access all of the same elements, starting with the first index, but now our count starts from the specified integer value.

通过使用start参数,我们从第一个索引开始访问所有相同的元素,但是现在我们的计数从指定的整数值开始。

使用列表推导代替map()filter() (Use List Comprehensions Instead of map() and filter())

“I think dropping filter() and map() is pretty uncontroversial[.]”

“我认为删除filter()和map()毫无争议[。]”

— Guido van Rossum, Python’s creator

-Python的创建者Guido van Rossum

He may have been wrong about it being uncontroversial, but Guido had good reasons for wanting to remove map() and filter() from Python. One reason is that Python supports list comprehensions, which are often easier to read and support the same functionality as map() and filter().

他可能对此毫无争议是错误的,但是Guido有充分的理由要从Python中删除map()filter() 。 原因之一是Python支持列表解析,列表解析通常更易于阅读,并且支持与map()filter()相同的功能。

Let’s first take a look at how we’d structure a call to map() and the equivalent list comprehension:

首先让我们看一下如何构造对map()的调用以及等效的列表理解:

>>>

>>> numbers = [4, 2, 1, 6, 9, 7]
>>> def square(x):
...     return x*x
...
>>> list(map(square, numbers))
[16, 4, 1, 36, 81, 49]>>> [square(x) for x in numbers]
[16, 4, 1, 36, 81, 49]

>>>

Both approaches, using map() and the list comprehension, return the same values, but the list comprehension is easier to read and understand.

两种使用map()和列表理解的方法都返回相同的值,但是列表理解更易于阅读和理解。

Now we can do the same thing for the filter() and its equivalent list comprehension:

现在,我们可以对filter()及其等效的列表理解执行相同的操作:

>>>

>>> def is_odd(x):
...    return bool(x % 2)
...
>>> list(filter(is_odd, numbers))
[1, 9, 7]>>> [x for x in numbers if is_odd(x)]
[1, 9, 7]

>>>

Like we saw with map(), the filter() and list comprehension approaches return the same value, but the list comprehension is easier to follow.

就像我们在map()看到的那样, filter()和列表理解方法返回相同的值,但是列表理解更容易遵循。

Developers who come from other languages may disagree that list comprehensions are easier to read than map() and filter(), but in my experience beginners are able to pick up list comprehensions much more intuitively.

来自其他语言的开发人员可能不同意列表理解比map()filter()更容易阅读,但是以我的经验,初学者可以更直观地掌握列表理解。

Either way, you’ll rarely go wrong using list comprehensions in a coding interview, as it will communicate that you know what’s most common in Python.

无论哪种方式,您都不会在编码采访中使用列表理解来犯错,因为它可以传达您知道Python中最常见的东西。

使用breakpoint()而不是print()调试 (Debug With breakpoint() Instead of print())

You may have debugged a small problem by adding print() to your code and seeing what was printed out. This approach works well at first but quickly becomes cumbersome. Plus, in a coding interview setting, you hardly want print() calls peppered throughout your code.

您可以通过将print()添加到代码中并查看打印出的内容来调试一个小问题。 这种方法起初效果很好,但很快变得麻烦。 另外,在编码采访设置中,您几乎不需要在整个代码中进行print()调用。

Instead, you should be using a debugger. For non-trivial bugs, it’s almost always faster than using print(), and given that debugging is a big part of writing software, it shows that you know how to use tools that will let you develop quickly on the job.

相反,您应该使用调试器。 对于非重要的错误,它几乎总是比使用print()更快,并且鉴于调试是编写软件的重要组成部分,因此它表明您知道如何使用可让您快速完成工作的工具。

If you’re using Python 3.7, you don’t need to import anything and can just call breakpoint() at the location in your code where you’d like to drop into the debugger:

如果您使用的是Python 3.7,则无需导入任何内容,只需在代码中要放入调试器的位置调用breakpoint()即可:

 # Some complicated code with bugs# Some complicated code with bugsbreakpointbreakpoint ()
()

Calling breakpoint() will put you into pdb, which is the default Python debugger. On Python 3.6 and older, you can do the same by importing pdb explicitly:

调用breakpoint()将使您进入pdb ,这是默认的Python调试器。 在Python 3.6及更高版本上,您可以通过显式导入pdb来执行以下操作:

Like breakpoint(), pdb.set_trace() will put you into the pdb debugger. It’s just not quite as clean and is a tad more to remember.

breakpoint()pdb.set_trace()会将您带入pdb调试器。 它不是很干净,还需要记住一点。

There are other debuggers available that you may want to try, but pdb is part of the standard library, so it’s always available. Whatever debugger you prefer, it’s worth trying them out to get used to the workflow before you’re in a coding interview setting.

您可能还想尝试其他可用的调试器,但是pdb是标准库的一部分,因此它始终可用。 无论您喜欢哪种调试器,都值得在使用编码面试设置之前尝试一下它们以适应工作流程。

使用f字符串格式化字符串 (Format strings With f-Strings)

Python has a lot of different ways to handle string formatting, and it can be tricky to know what to use. In fact, we tackle formatting in depth in two separate articles: one about string formatting in general and one specifically focused on f-strings. In a coding interview, where you’re (hopefully) using Python 3.6+, the suggested formatting approach is Python’s f-strings.

Python有很多不同的方式来处理字符串格式,而且要知道使用什么可能会很棘手。 实际上,我们在两篇单独的文章中深入探讨了格式化:一篇关于字符串格式化的一般文章 ,另一篇专门针对f字符串的文章 。 在一次编程采访中(希望使用Python 3.6+),建议的格式化方法是Python的f字符串。

f-strings support use of the string formatting mini-language, as well as powerful string interpolation. These features allow you to add variables or even valid Python expressions and have them evaluated at runtime before being added to the string:

f字符串支持使用字符串格式化迷你语言以及强大的字符串插值功能。 这些功能使您可以添加变量甚至有效的Python表达式,并在将它们添加到字符串之前在运行时对其求值:

>>>

>>> def get_name_and_decades(name, age):
...     return f"My name is {name} and I'm {age / 10:.5f} decades old."
...
>>> get_name_and_decades("Maria", 31)
My name is Maria and I'm 3.10000 decades old.

>>>

The f-string allows you to put Maria into the string and add her age with the desired formatting in one succinct operation.

f字符串使您可以将Maria放入字符串中,并通过一次简洁的操作以所需的格式添加年龄。

The one risk to be aware of is that if you’re outputting user-generated values, then that can introduce security risks, in which case Template Strings may be a safer option.

要意识到的一个风险是,如果您输出用户生成的值,则可能会带来安全风险,在这种情况下, 模板字符串可能是一个更安全的选择。

使用sorted()对复杂列表sorted() (Sort Complex Lists With sorted())

Plenty of coding interview questions require some kind of sorting, and there are multiple valid ways you can sort items. Unless the interviewer wants you to implement your own sorting algorithm, it’s usually best to use sorted().

大量的采访问题编码需要某种排序,并且可以使用多种有效方式对项目进行排序。 除非访问者希望您实现自己的排序算法,否则通常最好使用sorted()

You’ve probably seen the most simple uses of sorting, such as sorting lists of numbers or strings in ascending or descending order:

您可能已经看到了排序的最简单用法,例如按升序或降序对数字或字符串列表进行排序:

>>>

>>> sorted([6,5,3,7,2,4,1])
[1, 2, 3, 4, 5, 6, 7]>>> sorted(['cat', 'dog', 'cheetah', 'rhino', 'bear'], reverse=True)
['rhino', 'dog', 'cheetah', 'cat', 'bear]

>>>

By default, sorted() has sorted the input in ascending order, and the reverse keyword argument causes it to sort in descending order.

默认情况下, sorted()已按升序对输入进行排序,而reverse关键字参数使它按降序进行排序。

It’s worth knowing about the optional keyword argument key that lets you specify a function that will be called on every element prior to sorting. Adding a function allows custom sorting rules, which are especially helpful if you want to sort more complex data types:

值得一提的是有关可选关键字参数key知识,该关键字使您可以指定在排序之前将在每个元素上调用的函数。 添加功能允许使用自定义排序规则,如果要对更复杂的数据类型进行排序,这将特别有用:

>>>

>>> animals = [
...     {'type': 'penguin', 'name': 'Stephanie', 'age': 8},
...     {'type': 'elephant', 'name': 'Devon', 'age': 3},
...     {'type': 'puma', 'name': 'Moe', 'age': 5},
... ]
>>> sorted(animals, key=lambda animal: animal['age'])
[
    {'type': 'elephant', 'name': 'Devon', 'age': 3},
    {'type': 'puma', 'name': 'Moe', 'age': 5},
    {'type': 'penguin', 'name': 'Stephanie, 'age': 8},
]

>>>

By passing in a lambda function that returns each element’s age, you can easily sort a list of dictionaries by a single value of each of those dictionaries. In this case, the dictionary is now sorted in ascending order by age.

通过传入返回每个元素的年龄的lambda函数 ,您可以轻松地按每个词典的单个值对词典列表进行排序。 在这种情况下,字典现在按年龄升序排列。

有效利用数据结构 (Leverage Data Structures Effectively)

Algorithms get a lot of attention in coding interviews, but data structures are arguably even more important. In a coding interviewing context, picking the right data structure can have a major impact on performance.

算法在采访采访中得到了很多关注,但是数据结构可以说更重要。 在编码访问环境中,选择正确的数据结构可能会对性能产生重大影响。

Beyond theoretical data structures, Python has powerful and convenient functionality built into its standard data structure implementations. These data structures are incredibly useful in coding interviews because they give you lots of functionality by default and let you focus your time on other parts of the problem.

除理论数据结构外,Python还具有内置于其标准数据结构实现中的强大而便捷的功能。 这些数据结构在对采访进行编码时非常有用,因为它们默认情况下为您提供了许多功能,并使您可以将时间集中在问题的其他部分。

使用集合存储唯一值 (Store Unique Values With Sets)

You’ll often need to remove duplicate elements from an existing dataset. New developers will sometimes do so with lists when they should be using sets, which enforce the uniqueness of all elements.

您通常需要从现有数据集中删除重复的元素。 新开发人员有时应在使用集时强制使用列表,这些集会强制所有元素的唯一性。

Pretend you have a function named get_random_word(). It will always return a random selection from a small set of words:

假设您有一个名为get_random_word()的函数。 它将始终从一小部分单词中返回随机选择:

>>>

>>> import random
>>> all_words = "all the words in the world".split()
>>> def get_random_word():
...    return random.choice(all_words)

>>>

You’re supposed to call get_random_word() repeatedly to get 1000 random words and then return a data structure containing every unique word. Here are two common, suboptimal approaches and one good approach.

您应该反复调用get_random_word()以获取1000个随机单词,然后返回包含每个唯一单词的数据结构。 这是两种常见的次优方法,一种是好的方法。

Bad Approach

错误的方法

get_unique_words() stores values in a list then converts the list into a set:

get_unique_words()将值存储在列表中,然后将列表转换为集合:

>>>

>>> def get_unique_words():
...     words = []
...     for _ in range(1000):
...         words.append(get_random_word())
...     return set(words)
>>> get_unique_words()
{'world', 'all', 'the', 'words'}

>>>

This approach isn’t terrible, but it unnecessarily creates a list and then converts it to a set. Interviewers almost always notice (and ask about) this type of design choice.

这种方法并不可怕,但是它不必要地创建了一个列表,然后将其转换为集合。 采访者几乎总是注意到(并询问)这种类型的设计选择。

Worse Approach

更差的方法

To avoid converting from a list to a set, you now store values in a list without using any other data structures. You then test for uniqueness by comparing new values with all elements currently in the list:

为了避免从列表转换为集合,现在可以在不使用任何其他数据结构的情况下将值存储在列表中。 然后,您可以通过将新值与列表中当前的所有元素进行比较来测试唯一性:

>>>

>>> def get_unique_words():
...     words = []
...     for _ in range(1000):
...         word = get_random_word()
...         if word not in words:
...             words.append(word)
...     return words
>>> get_unique_words()
['world', 'all', 'the', 'words']

>>>

This is worse than the first approach, because you have to compare every new word against every word already in the list. That means that as the number of words grows, the number of lookups grows quadratically. In other words, the time complexity grows on the order of O(N²).

这比第一种方法差,因为您必须将每个新单词与列表中已有的每个单词进行比较。 这意味着随着单词数量的增加,查找数量也将平方增加。 换句话说,时间复杂度以O(N²)的数量级增长。

Good Approach

好的方法

Now, you skip using lists altogether and instead use a set from the start:

现在,您完全跳过使用列表,而是从头开始使用一个集合:

>>>

>>> def get_unique_words():
...     words = set()
...     for _ in range(1000):
...         words.add(get_random_word())
...     return words
>>> get_unique_words()
{'world', 'all', 'the', 'words'}

>>>

This may not look much different than the other approaches except for making use of a set from the beginning. If you consider what’s happening within .add(), it even sounds like the second approach: get the word, check if it’s already in the set, and if not, add it to the data structure.

除了从一开始就使用集合以外,这可能与其他方法没有太大不同。 如果您考虑.add()发生的事情,它甚至听起来像第二种方法:获取单词,检查它是否已经在集合中,如果没有,则将其添加到数据结构中。

So why is using a set different from the second approach?

那么为什么使用一套不同于第二种方法呢?

It’s different because sets store elements in a manner that allows near-constant-time checks whether a value is in the set or not, unlike lists, which require linear-time lookups. The difference in lookup time means that the time complexity for adding to a set grows at a rate of O(N), which is much better than the O(N²) from the second approach in most cases.

这是不同的,因为集合存储元素的方式允许近恒定时间检查值是否在集合中,这与需要线性时间查找的列表不同。 查找时间的差异意味着添加到集合中的时间复杂度以O(N)的速率增长,这在大多数情况下比第二种方法的O(N²)好得多。

使用生成器节省内存 (Save Memory With Generators)

List comprehensions are convenient tools but can sometimes lead to unnecessary memory usage.

列表推导是方便的工具,但有时会导致不必要的内存使用。

Imagine you’ve been asked to find the sum of the first 1000 perfect squares, starting with 1. You know about list comprehensions, so you quickly code up a working solution:

假设您被要求查找从1开始的前1000个完美平方的总和。您了解列表推导,因此可以快速编写一个可行的解决方案:

>>>

>>> sum([i * i for i in range(1, 1001)])
333833500

>>>

Your solution makes a list of every perfect square between 1 and 1,000,000 and sums the values. Your code returns the right answer, but then your interviewer starts increasing the number of perfect squares you need to sum.

您的解决方案列出了介于1到1,000,000之间的每个理想平方并对其求和。 您的代码返回正确的答案,但随后您的面试官开始增加您需要求和的完美平方的数量。

At first, your function keeps popping out the right answer, but soon it starts slowing down until eventually the process seems to hang for an eternity. This is the last thing you want happening in a coding interview.

刚开始,您的函数会不断弹出正确的答案,但很快它就会开始变慢,直到最终该过程似乎永久终止。 这是您要在编码面试中发生的最后一件事。

What’s going on here?

这里发生了什么?

It’s making a list of every perfect square you’ve requested and summing them all. A list with 1000 perfect squares may not be large in computer-terms, but 100 million or 1 billion is quite a bit of information and can easily overwhelm your computer’s available memory resources. That’s what’s happening here.

它会列出您所要求的每个完美正方形,并对它们进行汇总。 在计算机术语方面,具有1000个完美平方的列表可能并不大,但是1亿或10亿个列表中的信息很多,很容易使计算机的可用内存资源不堪重负。 这就是这里发生的事情。

Thankfully, there’s a quick way to solve the memory problem. You just replace the brackets with parentheses:

值得庆幸的是,有一种快速的方法可以解决内存问题。 您只需将括号替换为括号即可:

>>>

>>> sum((i * i for i in range(1, 1001)))
333833500

>>>

Swapping out the brackets changes your list comprehension into a generator expression. Generator expressions are perfect for when you know you want to retrieve data from a sequence, but you don’t need to access all of it at the same time.

取消括号,将列表理解变为生成器表达式 。 当您知道要从序列中检索数据,而无需同时访问所有数据时,生成器表达式非常适合。

Instead of creating a list, the generator expression returns a generator object. That object knows where it is in the current state (for example, i = 49) and only calculates the next value when it’s asked for.

生成器表达式不创建列表,而是返回generator对象。 该对象知道当前状态(例如, i = 49 ),并且仅在需要时才计算下一个值。

So when sum iterates over the generator object by calling .__next__() repeatedly, the generator checks what i equals, calculates i * i, increments i internally, and returns the proper value to sum. The design allows generators to be used on massive sequences of data, because only one element exists in memory at a time.

因此,当sum重复调用.__next__()在生成器对象上进行迭代时,生成器将检查i等于,计算i * i ,在内部递增i并返回适当的值sum 。 该设计允许生成器用于大量数据序列,因为一次内存中仅存在一个元素。

使用.get().setdefault()在字典中定义默认值 (Define Default Values in Dictionaries With .get() and .setdefault())

One of the most common programming tasks involves adding, modifying, or retrieving an item that may or may not be in a dictionary. Python dictionaries have elegant functionality to make these tasks clean and easy, but developers often check explicitly for values when it isn’t necessary.

最常见的编程任务之一是添加,修改或检索可能不在字典中的项目。 Python字典具有精巧的功能,可以使这些任务简洁明了,但是开发人员经常在不需要时显式检查值。

Imagine you have a dictionary named cowboy, and you want to get that cowboy’s name. One approach is to explicitly check for the key with a conditional:

想象一下,您有一本名为cowboy的字典,并且您想获得该牛仔的名字。 一种方法是使用条件语句显式检查密钥:

>>>

>>> cowboy = {'age': 32, 'horse': 'mustang', 'hat_size': 'large'}
>>> if 'name' in cowboy:
...     name = cowboy['name']
... else:
...     name = 'The Man with No Name'
...
>>> name
'The Man with No Name'

>>>

This approach first checks if the name key exists in the dictionary, and if so, it returns the corresponding value. Otherwise, it returns a default value.

此方法首先检查字典中是否存在name关键字,如果存在,则返回相应的值。 否则,它将返回默认值。

While explicitly checking for keys does work, it can easily be replaced with one line if you use .get():

虽然显式检查密钥确实有效,但是如果使用.get() ,则可以很容易地用一行替换:

>>>

>>> name = cowboy.get('name', 'The Man with No Name')

>>>

get() performs the same operations that were performed in the first approach, but now they’re handled automatically. If the key exists, then the proper value will be returned. Otherwise, the default value will get returned.

get()执行与第一种方法相同的操作,但是现在它们是自动处理的。 如果键存在,则将返回正确的值。 否则,将返回默认值。

But what if you want to update the dictionary with a default value while still accessing the name key? .get() doesn’t really help you here, so you’re left with explicitly checking for the value again:

但是,如果要在仍访问name键的同时使用默认值更新字典,该怎么办? .get()并没有真正帮助您,因此您需要再次明确检查值:

>>>

>>> if 'name' not in cowboy:
...     cowboy['name'] = 'The Man with No Name'
...
>>> name = cowboy['name']

>>>

Checking for the value and setting a default is a valid approach and is easy to read, but again Python offers a more elegant method with .setdefault():

检查值并设置默认值是一种有效的方法,并且易于阅读,但是Python再次使用.setdefault()提供了更优雅的方法:

>>>

>>> name = cowboy.setdefault('name', 'The Man with No Name')

>>>

.setdefault() accomplishes exactly the same thing as the snippet above. It checks if name exists in cowboy, and if so it returns that value. Otherwise, it sets cowboy['name'] to The Man with No Name and returns the new value.

.setdefault()与上面的代码片段完全相同。 它检查name中存在cowboy ,如果是这样,返回该值。 否则,它将cowboy['name']The Man with No Name并返回新值。

利用Python的标准库 (Take Advantage of Python’s Standard Library)

By default, Python comes with a lot of functionality that’s just an import statement away. It’s powerful on its own, but knowing how to leverage the standard library can supercharge your coding interview skills.

默认情况下,Python带有很多功能,而这些功能只是import语句。 它本身具有强大的功能,但是知道如何利用标准库可以增强您的编码面试技巧。

It’s hard to pick the most useful pieces from all of the available modules, so this section will focus on just a small subset of its utility functions. Hopefully, these will prove useful to you in coding interviews and also whet your appetite to learn more about the advanced functionality of these and other modules.

很难从所有可用模块中挑选最有用的部分,因此本节将仅关注其实用程序功能的一小部分。 希望这些对您的面试编码很有用,也可以激发您的胃口,以了解有关这些模块和其他模块的高级功能的更多信息。

使用collections.defaultdict()处理缺少的字典键 (Handle Missing Dictionary Keys With collections.defaultdict())

.get() and .setdefault() work well when you’re setting a default for a single key, but it’s common to want a default value for all possible unset keys, especially when programming in a coding interview context.

当您为单个键设置默认值时, .get().setdefault()可以很好地工作,但是通常需要为所有可能的未设置键设置默认值,尤其是在编码采访上下文中编程时。

Pretend you have a group of students, and you need to keep track of their grades on homework assignments. The input value is a list of tuples with the format (student_name, grade), but you want to easily look up all the grades for a single student without iterating over the list.

假设您有一群学生,并且您需要在作业上跟踪他们的成绩。 输入值是格式为(student_name, grade)的元组列表,但是您想轻松地查找单个学生的所有成绩,而无需遍历该列表。

One way to store the grade data uses a dictionary that maps student names to lists of grades:

存储成绩数据的一种方法是使用字典将学生姓名映射到成绩列表:

>>>

>>> student_grades = {}
>>> grades = [
...     ('elliot', 91),
...     ('neelam', 98),
...     ('bianca', 81),
...     ('elliot', 88),
... ]
>>> for name, grade in grades:
...     if name not in student_grades:
...         student_grades[name] = []
...     student_grades[name].append(grade)
...
>>> student_grades
{'elliot': [91, 88], 'neelam': [98], 'bianca': [81]}

>>>

In this approach, you iterate over the students and check if their names are already properties in the dictionary. If not, you add them to the dictionary with an empty list as the default value. You then append their actual grades to that student’s list of grades.

通过这种方法,您可以遍历学生并检查他们的名字是否已经在字典中成为属性。 如果不是,则将它们添加到词典中,并将空列表作为默认值。 然后,将他们的实际成绩附加到该学生的成绩列表中。

But there’s an even cleaner approach that uses a defaultdict, which extends standard dict functionality to allow you to set a default value that will be operated upon if the key doesn’t exist:

但是,还有一种更干净的方法使用defaultdict ,它扩展了标准dict功能以允许您设置默认值,如果键不存在,将对其进行操作:

>>>

>>> from collections import defaultdict
>>> student_grades = defaultdict(list)
>>> for name, grade in grades:
...     student_grades[name].append(grade)

>>>

In this case, you’re creating a defaultdict that uses the list() constructor with no arguments as a default factory method. list() with no arguments returns an empty list, so defaultdict calls list() if the name doesn’t exist and then allows the grade to be appended. If you want to get fancy, you could also use a lambda function as your factory value to return an arbitrary constant.

在这种情况下,您要创建一个defaultdict ,它使用不带参数的list()构造函数作为默认工厂方法。 没有参数的list()返回一个空列表,因此,如果名称不存在,则defaultdict调用list() ,然后允许添加等级。 如果想花哨的话,也可以使用lambda函数作为工厂值来返回任意常量。

Leveraging a defaultdict can lead to cleaner application code because you don’t have to worry about default values at the key level. Instead, you can handle them once at the defaultdict level and afterwards act as if the key is always present.

利用defaultdict可以使应用程序代码更defaultdict ,因为您不必担心键级别的默认值。 取而代之的是,您可以在defaultdict级别处理它们一次,然后再执行操作,就好像该密钥始终存在。

collections.Counter计数可哈希对象 (Count Hashable Objects With collections.Counter)

You have a long string of words with no punctuation or capital letters and you want to count how many times each word appears.

您有很长的单词串,没有标点符号或大写字母,并且您想计算每个单词出现的次数。

You could use a dictionary or defaultdict and increment the counts, but collections.Counter provides a cleaner and more convenient way to do exactly that. Counter is a subclass of dict that uses 0 as the default value for any missing element and makes it easier to count occurrences of objects:

您可以使用字典或defaultdict增加计数,但是collections.Counter提供了一种更干净,更方便的方式来实现这一点。 Counter是dict的子类,它使用0作为任何缺少的元素的默认值,并使计数对象的出现更加容易:

>>>

>>> from collections import Counter
>>> words = "if there was there was but if
... there was not there was not".split()
>>> counts = Counter(words)
>>> counts
Counter({'if': 2, 'there': 4, 'was': 4, 'not': 2, 'but': 1})

>>>

When you pass in the list of words to Counter, it stores each word along with a count of how many times that word occurred in the list.

当您将单词列表传递给Counter ,它将存储每个单词以及该单词在列表中出现多少次的计数。

Are you curious what the two most common words were? Just use .most_common():

您是否好奇两个最常见的词是什么? 只需使用.most_common()

>>>

>>> counts.most_common(2)
[('there', 4), ('was', 4)]

>>>

.most_common() is a convenience method and simply returns the n most frequent inputs by count.

.most_common()是一种便捷方法,它仅通过计数返回n最频繁的输入。

使用string常量访问常见的字符串组 (Access Common String Groups With string Constants)

It’s trivia time! Is 'A' > 'a' true or false?

现在是琐事! 'A' > 'a'对还是错?

It’s false, because the ASCII code for A is 65, but a is 97, and 65 is not greater than 97.

这是错误的,因为A的ASCII码是65,但是a是97,而65不大于97。

Why does the answer matter? Because if you want to check if a character is part of the English alphabet, one popular way is to see if it’s between A and z (65 and 122 on the ASCII chart).

为什么答案很重要? 因为如果要检查字符是否是英语字母的一部分,一种流行的方法是查看字符是否在Az之间(在ASCII图表上为65和122)。

Checking the ASCII code works but is clumsy and easy to mess up in coding interviews, especially if you can’t remember whether lowercase or uppercase ASCII characters come first. It’s much easier to use the constants defined as part of the string module.

检查ASCII码是可行的,但是笨拙且容易在编码采访中弄乱,特别是如果您不记得是小写还是大写ASCII字符排在首位。 使用定义为string模块一部分的常量要容易得多。

You can see one in use in is_upper(), which returns whether all characters in a string are uppercase letters:

您可以在is_upper()看到一个正在使用的is_upper() ,该is_upper()返回字符串中的所有字符是否均为大写字母:

>>>

>>> import string
>>> def is_upper(word):
...     for letter in word:
...         if letter not in string.ascii_uppercase:
...             return False
...     return True
...
>>> is_upper('Thanks Geir')
False
>>> is_upper('LOL')
True

>>>

is_upper() iterates over the letters in word, and checks if the letters are part of string.ascii_uppercase. If you print out string.ascii_uppercase you’ll see that it’s just a lowly string. The value is set to the literal 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.

is_upper()遍历word的字母,并检查字母是否为string.ascii_uppercase一部分。 如果您打印出string.ascii_uppercase您会发现它只是一个string.ascii_uppercase的字符串。 该值设置为文字'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

All string constants are just strings of frequently referenced string values. They include the following:

所有string常量都是经常引用的字符串值的字符串。 其中包括:

  • string.ascii_letters
  • string.ascii_uppercase
  • string.ascii_lowercase
  • string.digits
  • string.hexdigits
  • string.octdigits
  • string.punctuation
  • string.printable
  • string.whitespace
  • string.ascii_letters
  • string.ascii_uppercase
  • string.ascii_lowercase
  • string.digits
  • string.hexdigits
  • string.octdigits
  • string.punctuation
  • string.printable
  • string.whitespace

These are easier to use and, even more importantly, easier to read.

这些更易于使用,更重要的是,更易于阅读。

使用itertools生成排列和组合 (Generate Permutations and Combinations With itertools)

Interviewers love to give real life scenarios to make coding interviews seem less intimidating, so here’s a contrived example: you go to an amusement park and decide to figure out every possible pair of friends that could sit together on a roller coaster.

采访者喜欢给出真实的生活场景,以使编码采访看起来不那么吓人,所以这是一个人为的例子:您去游乐园,并决定找出可能坐在过山车上的每对朋友。

Unless generating these pairs is the primary purpose of the interview question, it’s likely that generating all the possible pairs is just a tedious step on the way towards a working algorithm. You could calculate them yourself with nested for-loops, or you could use the powerful itertools library.

除非生成这些对是访谈问题的主要目的,否则生成所有可能的对可能只是迈向有效算法的乏味步骤。 您可以使用嵌套的for循环自己计算它们,也可以使用功能强大的itertools库 。

itertools has multiple tools for generating iterable sequences of input data, but right now we’ll just focus on two common functions: itertools.permutations() and itertools.combinations().

itertools具有用于生成输入数据可迭代序列的多种工具,但现在我们仅关注两个常用函数: itertools.permutations()itertools.combinations()

itertools.permutations() builds a list of all permutations, meaning it’s a list of every possible grouping of input values with a length matching the count parameter. The r keyword argument lets us specify how many values go in each grouping:

itertools.permutations()构建所有排列的列表,这意味着它是长度与count参数匹配的所有可能的输入值分组的列表。 r关键字参数使我们可以指定每个分组中有多少个值:

>>>

>>> import itertools
>>> friends = ['Monique', 'Ashish', 'Devon', 'Bernie']
>>> list(itertools.permutations(friends, r=2))
[('Monique', 'Ashish'), ('Monique', 'Devon'), ('Monique', 'Bernie'),
('Ashish', 'Monique'), ('Ashish', 'Devon'), ('Ashish', 'Bernie'),
('Devon', 'Monique'), ('Devon', 'Ashish'), ('Devon', 'Bernie'),
('Bernie', 'Monique'), ('Bernie', 'Ashish'), ('Bernie', 'Devon')]

>>>

With permutations, the order of the elements matters, so ('sam', 'devon') represents a different pairing than ('devon', 'sam'), meaning that they would both be included in the list.

对于排列,元素的顺序很重要,因此('sam', 'devon')表示的配对与('devon', 'sam') ,这意味着它们都将包含在列表中。

itertools.combinations() builds combinations. These are also the possible groupings of the input values, but now the order of the values doesn’t matter. Because ('sam', 'devon') and ('devon', 'sam') represent the same pair, only one of them would be included in the output list:

itertools.combinations()建立组合。 这些也是输入值的可能分组,但是现在值的顺序不再重要。 因为('sam', 'devon')('devon', 'sam')代表同一对,所以输出列表中将仅包含其中一个:

>>>

>>> list(itertools.combinations(friends, r=2))
[('Monique', 'Ashish'), ('Monique', 'Devon'), ('Monique', 'Bernie'),
('Ashish', 'Devon'), ('Ashish', 'Bernie'), ('Devon', 'Bernie')]

>>>

Since the order of the values matters with combinations, there are fewer combinations than permutations for the same input list. Again, because we set r to 2, each grouping has two names in it.

由于值的顺序与组合有关,因此与相同输入列表的排列相比,组合数更少。 同样,因为我们将r设置为2,所以每个分组中都有两个名称。

.combinations() and .permutations() are just small examples of a powerful library, but even these two functions can be quite useful when you’re trying to solve an algorithm problem quickly.

.combinations().permutations()只是功能强大的库的小例子,但是当您试图快速解决算法问题时,即使这两个函数也可能非常有用。

结论:编码采访超级大国 (Conclusion: Coding Interview Superpowers)

You can now feel comfortable using some of Python’s less common, but more powerful, standard features in your next coding interview. There’s a lot to learn about the language as a whole but this article should have given you a starting point to go deeper while letting you use Python more effectively when you interview.

现在,您可以在下一次编码采访中使用Python的一些不常见但功能更强大的标准功能,感到很自在。 关于语言的整体知识有很多,但是本文应该为您提供一个起点,让您更深入地学习,同时在面试时可以更有效地使用Python。

In this article, you’ve learned different types of standard tools to supercharge your coding interview skills:

在本文中,您学习了各种类型的标准工具来增强您的编码面试技能:

  • Powerful built-in functions
  • Data structures built to handle common scenarios with barely any code
  • Standard library packages that have feature-rich solutions for specific problems, letting you write better code faster
  • 强大的内置功能
  • 建立的数据结构几乎不需要任何代码即可处理常见情况
  • 标准库软件包具有针对特定问题的功能丰富的解决方案,可让您更快地编写更好的代码

Interviewing may not be the best approximation of real software development, but it’s worth knowing how to succeed in any programming environment, even interviews. Thankfully, learning how to use Python during coding interviews can help you understand the language more deeply, which will pay dividends during day-to-day development.

面试也许并不是真正的软件开发的最佳方案,但是值得知道如何在任何编程环境中取得成功,甚至是面试。 值得庆幸的是,在编码面试中学习如何使用Python可以帮助您更深入地理解该语言,这将在日常开发中带来好处。

翻译自: https://www.pybloggers.com/2019/03/how-to-stand-out-in-a-python-coding-interview/

如何在Python编码面试中脱颖而出相关推荐

  1. python100个必背知识-python编程面试中必考的知识点,数据类型全解,笔记超全面...

    原标题:python编程面试中必考的知识点,数据类型全解,笔记超全面 python作为一门高级编程语言,它的定位是优雅.明确和简单.阅读Python编写的代码感觉像在阅读英语一样,这让使用者可以专注于 ...

  2. python中奇数怎么表示_如何在python输出数据中的奇数

    如何在python输出数据中的奇数 发布时间:2020-07-10 17:08:48 来源:亿速云 阅读:131 这篇文章将为大家详细讲解有关如何在python输出数据中的奇数,文章内容质量较高,因此 ...

  3. 工程师如何在面试中脱颖而出

    价值 | 思考 | 共鸣 简评:不单纯说技术,工程师在申请人池中如何脱颖而出. 每个人都想在面试中脱颖而出,我也一样.事实上,这是工程师最长问到的问题之一. 为了或多更多参考,我问了好多朋友,他们都是 ...

  4. python中nlp的库_单词袋简介以及如何在Python for NLP中对其进行编码

    python中nlp的库 by Praveen Dubey 通过Praveen Dubey 单词词汇入门以及如何在Python中为NLP 编写代码的简介 (An introduction to Bag ...

  5. 如何在Python调试过程中设置不中断的断点?面试必学

    你对如何让调试器变得更快产生过兴趣吗?本文将分享我们在为 Python 构建调试器时得到的一些经验. 整段故事讲的是我们在 Rookout 公司的团队为 Python 调试器开发不中断断点的经历,以及 ...

  6. 码这么多字只为搞懂如何在Python和Java中使用JSON

    目录 1 JSON是什么? 1.1 JSON是众多编程语言共同的"简谱" 1.2 JSON是一种高度结构化的文本 2 如何在Python中使用JSON 2.1 内置库json的编码 ...

  7. @程序员,如何在编程面试中脱颖而出?

    如果能多了解一些面试的基本知识,可以帮助你在面试中对自身有更准确的定位,并且能提升你的面试技巧. 作者 | edA‑qa mort‑ora‑y 译者 | 苏本如,责编 | 郭芮 出品 | CSDN(I ...

  8. linux python matplotlib 使用,关于Linux:如何在Python的matplotlib中设置“后端”?

    我是matplotlib的新用户,我的平台是Ubuntu 10.04 Python 2.6.5 这是我的代码 import matplotlib matplotlib.use('Agg') impor ...

  9. javascript面试_在编码面试中需要注意的3个JavaScript问题

    javascript面试 JavaScript is the official language of all modern web browsers. As such, JavaScript que ...

最新文章

  1. cv2.threshold() 阈值:使用Python,OpenCV进行简单的图像分割
  2. 从零开始搭建一个vue项目 -- vue-cli/cooking-cli(一)
  3. 使用libssh2连接到远程服务器
  4. poj-1979 dfs
  5. [渝粤教育] 中国矿业大学 恋爱心理学 参考 资料
  6. Solution 7: 判断两链表是否相交
  7. 关于TCP/IP协议及网络通信相关问题
  8. mysql安装版安装
  9. Syncfusion教程:在Xamarin.Forms中创建数据输入表单 (4)
  10. springmvc自定义类型转换
  11. 基于PHP+MySQL图书管理系统的设计与实现
  12. docker命令的使用
  13. 【机器学习入门到精通系列】元胞自动机和代码举例(这一篇就够了!)
  14. keras深度学习之猫狗分类三(特征提取)
  15. matlab sin函数怎么写,matlab实现插值法sin函数
  16. spec之install
  17. 教育界杂志教育界杂志社教育界编辑部2022年第24期目录
  18. viewpro.php是啥意思,海信 Hi-View Pro系列 画质引擎芯片简介
  19. h0156.国王的金矿
  20. Ray 分布式简单教程(2)

热门文章

  1. 基于Java+MySQL实现(Web)高校资源综合发布系统【100010343】
  2. 聚乙二醇表面修饰氧化锌量子点/FA-PEG-CdTe/CdS量子点荧光探针特异性标记Hep-2的制备
  3. ROM, SRAM, SDRAM的区别
  4. Python-pandas拆分列与堆叠列
  5. ACRush 楼天成 回忆录
  6. Java基础——Stream
  7. App Store Connect 上构建的新版本上传后找不到,二进制文件无效
  8. 深入讲解VsCode各场景高级调试与使用技巧
  9. Mean ± SEM or Mean(SD)
  10. python获取星期几_如何在Python中获取日期的星期几?