Q: Why use function decorators? Give an example.
A decorator is essentially a callable Python object that is used to modify or extend a function or class definition. One of the beauties of decorators is that a single decorator definition can be applied to multiple functions (or classes). Much can thereby be accomplished with decorators that would otherwise require lots of boilerplate (or even worse redundant!) code. Flask, for example, uses decorators as the mechanism for adding new endpoints to a web application. Examples of some of the more common uses of decorators include adding synchronization, type enforcement, logging, or pre/post conditions to a class or function.
问:为什么要使用功能装饰器?举个例子
装饰器本质上是一个可调用的Python对象,用于修改或扩展函数或类定义。装饰器的美丽之处在于,可以将单个装饰器定义应用于多个功能(或类)。因此,可以通过装饰器来完成许多工作,否则将需要大量样板(或更糟的冗余!)代码。例如,Flask使用装饰器作为向Web应用程序添加新端点的机制。装饰器的一些更常见的用途的例子包括向同步或功能添加同步,类型强制,日志记录或预/后期条件。
Q: What are lambda expressions, list comprehensions and generator expressions? What are the advantages and appropriate uses of each?
Lambda expressions
List comprehensions provide a concise syntax for creating lists. List comprehensions are commonly used to make lists where each element is the result of some operation(s) applied to each member of another sequence or iterable. They can also be used to create a subsequence of those elements whose members satisfy a certain condition. In Python, list comprehensions provide an alternative to using the built-in map()
and filter()
map
and lambda
Generator expressions
问:什么是lambda表达式,列表推导和生成器表达式?每个的优点和适当的用途是什么?
Lambda表达式是用于创建单行匿名函数的简写技术。他们简单的内联自然通常(尽管并不总是)会导致比可选的形式函数声明更可读和更简洁的代码。另一方面,根据定义,他们简洁的内在性大大限制了他们能够做的事情及其适用性。匿名和内联,在代码中的多个位置使用相同的lambda函数的唯一方法是冗余地指定它。
列表推导提供了创建列表的简洁语法。列表推导通常用于列出每个元素是应用于另一个序列的每个成员或可迭代的一些操作的结果的列表。它们也可用于创建成员满足一定条件的元素的子序列。在Python中,列表推导提供了使用内置map()和filter()函数的替代方法。
由于lambda表达式和列表推导的应用使用可能重叠,所以意见与使用一个对象的时间和地点有很大差异。需要记住的一点是,列表的理解比使用map和lambda的可比解决方案执行得更快一些(一些快速测试产生了大约10%的性能差异)。这是因为调用lambda函数创建一个新的堆栈框架,而列表理解中的表达式则不会这样做。
生成器表达式在语法和功能上与列表推导相似,但是在两种操作方式之间存在一些相当显着的差异,因此,每个应用程序应该被使用。简而言之,迭代生成器表达式或列表理解将基本上做同样的事情,但列表理解将首先创建内存中的整个列表,而生成器表达式将根据需要在运行时创建项目。因此,生成器表达式可以用于非常大(甚至无限)的序列,并且它们的惰性(即,按需)生成值导致改进的性能和较低的存储器使用。不过值得注意的是,标准的Python列表方法可以用于列表推导的结果,但不能直接用于生成器表达式。
Q: Consider the two approaches below for initializing an array and the arrays that will result. How will the resulting arrays differ and why should you use one initialization approach vs. the other? 问:考虑以下两种方法来初始化一个数组和将导致的数组。结果阵列如何不同,为什么要使用一个初始化方法呢?
While both methods appear at first blush to produce the same result, there is an extremely significant difference between the two. Method 2 produces, as you would expect, an array of 3 elements, each of which is itself an independent 4-element array. In method 1, however, the members of the array all point to the same object. This can lead to what is most likely unanticipated and undesired behavior as shown below. 虽然两种方法首先出现腮红产生相同的结果,但两者之间存在极大的差异。方法2根据您的预期产生3个元素的数组,每个元素本身就是独立的4元素数组。然而,在方法1中,数组的成员都指向相同的对象。这可能导致如下所示的最可能意外的和不期望的行为。
Q: What will be printed out by the second append() statement below?下面的第二个append()语句将打印什么?
When the default value for a function argument is an expression, the expression is evaluated only once, not every time the function is called. Thus, once the list argument has been initialized to an empty array, subsequent calls to append without any argument specified will continue to use the same array to which list was originally initialized. This will therefore yield the following, presumably unexpected, behavior:当函数参数的默认值是一个表达式时,该表达式只计算一次,而不是每次调用该函数时。因此,一旦列表参数被初始化为一个空数组,后续的追加调用没有指定任何参数将继续使用与该列表最初初始化的相同的数组。因此,这将产生以下,大概是意想不到的行为:
Q: How might one modify the implementation of the ‘append’ method in the previous question to avoid the undesirable behavior described there?在上一个问题中如何修改“append”方法的实现,以避免在此描述的不良行为?
The following alternative implementation of the append method would be one of a number of ways to avoid the undesirable behavior described in the answer to the previous question:附加方法的以下替代实现将是避免在上一个问题的答案中描述的不良行为的一些方法之一:
Q: How can you swap the values of two variables with a single line of Python code?如何用一行Python代码交换两个变量的值?
Consider this simple example:考虑这个简单的例子:
In many other languages, swapping the values of x and y requires that you to do the following:在许多其他语言中,交换x和y的值要求您执行以下操作:
But in Python, makes it possible to do the swap with a single line of code (thanks to implicit tuple packing and unpacking) as follows:但是在Python中,可以使用一行代码进行交换(由于隐式元组打包和解包),如下所示:
Q: What will be printed out by the last statement below?下面最后一个陈述将会打印什么?
In any closure in Python, variables are bound by name. Thus, the above line of code will print out the following:在Python中的任何闭包中,变量都被名称绑定。因此,上述代码行将打印出如下内容:
Presumably not what the author of the above code intended!大概不是上述代码的作者想要的!
A workaround is to either create a separate function or to pass the args by name; e.g.: 解决方法是创建单独的函数或通过名称传递args;例如。
Q: What are the key differences between Python 2 and 3?Python 2和3之间的关键区别是什么?
Although Python 2 is formally considered legacy at this point, its use is still widespread enough that is important for a developer to recognize the differences between Python 2 and 3.虽然Python 2在这一点上被正式视为遗产,但其使用仍然很广泛,这对开发人员来说,识别Python 2和3之间的差异很重要。
Here are some of the key differences that a developer should be aware of:以下是开发人员应注意的一些主要区别:
- Text and Data instead of Unicode and 8-bit strings. Python 3.0 uses the concepts of text and (binary) data instead of Unicode strings and 8-bit strings. The biggest ramification of this is that any attempt to mix text and data in Python 3.0 raises a TypeError (to combine the two safely, you must decode bytes or encode Unicode, but you need to know the proper encoding, e.g. UTF-8) 文本和数据而不是Unicode和8位字符串。 Python 3.0使用文本和(二进制)数据的概念,而不是Unicode字符串和8位字符串。最大的影响是任何在Python 3.0中混合文本和数据的尝试引发了一个TypeError(要安全地组合两个,你必须对字节进行解码或编码Unicode,但是您需要知道正确的编码,例如UTF-8)
- This addresses a longstanding pitfall for naïve Python programmers. In Python 2, mixing Unicode and 8-bit data would work if the string happened to contain only 7-bit (ASCII) bytes, but you would get UnicodeDecodeError if it contained non-ASCII values. Moreover, the exception would happen at the combination point, not at the point at which the non-ASCII characters were put into the str object. This behavior was a common source of confusion and consternation for neophyte Python programmers.这解决了天真的Python程序员的长期陷阱。在Python 2中,如果字符串只包含7位(ASCII)字节,则混合Unicode和8位数据将会起作用,但是如果包含非ASCII值,则会得到UnicodeDecodeError。此外,异常将发生在组合点,而不是将非ASCII字符放入到str对象中。这种行为是新手Python程序员的一个常见的混乱和惊奇的来源。
- print function. The
print
- statement has been replaced with a
print()
- xrange – buh-bye.
xrange()
- no longer exists (
range()
- now behaves like
xrange()
- API changes:API更改
zip()
- ,
map()
- and
filter()
dict.keys()
- ,
dict.items()
- and
dict.values()
dict.iterkeys()
- ,
dict.iteritems()
- and
dict.itervalues()
- Comparison operators. The ordering comparison operators (
<
- ,
<=
- ,
>=
- ,
>
- ) now raise a
TypeError
- exception when the operands don’t have a meaningful natural ordering. Some examples of the ramifications of this include: 比较运算符。当操作数没有有意义的自然排序时,排序比较运算符(<,<=,> =,>)会引发TypeError异常。其中一些例子包括:
1 < ''
- ,
0 > None
- or
len <= len
None < None
- now raises a
TypeError
- instead of returning
False 无<None现在引发一个TypeError而不是返回False
- Sorting a heterogeneous list no longer makes sense – all the elements must be comparable to each other 排序异构列表不再是有意义的 - 所有元素必须相互比较
Q: Is Python interpreted or compiled?Python是解释还是编译?
As noted in Why Are There So Many Pythons?, this is, frankly, a bit of a trick question in that it is malformed. Python itself is nothing more than an interface definition (as is true with any language specification) of which there are multiple implementations. Accordingly, the question of whether “Python” is interpreted or compiled does not apply to the Python language itself; rather, it applies to each specific implementation of the Python specification.
Further complicating the answer to this question is the fact that, in the case of CPython (the most common Python implementation), the answer really is “sort of both”. Specifically, with CPython, code is first compiled and then interpreted. More precisely, it is not precompiled to native machine code, but rather to bytecode. While machine code is certainly faster, bytecode is more portable and secure. The bytecode is then interpreted in the case of CPython (or both interpreted and compiled to optimized machine code at runtime in the case of PyPy).
正如为什么有这么多Pythons所说的,坦白说,这是一个棘手的问题,因为它是畸形的。 Python本身就是一个接口定义(与任何语言规范一样),其中有多个实现。因此,“Python”是否被解释或编译的问题不适用于Python语言本身;相反,它适用于Python规范的每个具体实现。
对这个问题的答案进一步复杂化的事实是,在CPython(最常见的Python实现)的情况下,答案确实是“两者兼有”。具体来说,使用CPython,代码首先被编译并解释。更准确地说,它不是预编译为本地机器代码,而是字节码。虽然机器代码肯定更快,字节码更便于携带和安全。然后在CPython的情况下解释字节码(或者在PyPy的情况下,它们在运行时被解释并编译成优化的机器代码)。
Q: What are some alternative implementations to CPython? When and why might you use them? 什么是CPython的一些替代实现?什么时候和为什么要使用它们?
One of the more prominent alternative implementations is Jython, a Python implementation written in Java that utilizes the Java Virtual Machine (JVM). While CPython produces bytecode to run on the CPython VM, Jython produces Java bytecode to run on the JVM.其中一个更为突出的替代实现是Jython,这是一个使用Java虚拟机(JVM)编写的Python实现。当CPython生成字节码在CPython VM上运行时,Jython生成Java字节码以在JVM上运行。
Another is IronPython, written in C# and targeting the .NET stack. IronPython runs on Microsoft’s Common Language Runtime (CLR). 另一个是IronPython,用C#编写,并以.NET堆栈为目标。 IronPython运行在Microsoft的公共语言运行时(CLR)上。
As also pointed out in Why Are There So Many Pythons?, it is entirely possible to survive without ever touching a non-CPython implementation of Python, but there are advantages to be had from switching, most of which are dependent on your technology stack. 同样也指出,为什么有这么多的Pythons?,完全有可能在没有触及Python的非CPython实现的情况下生存下去,但是从交换中获得优势,其中大部分取决于您的技术堆栈。
Another noteworthy alternative implementation is PyPy whose key features include: 另一个值得注意的替代实现是PyPy,其主要功能包括:
- Speed. Thanks to its Just-in-Time (JIT) compiler, Python programs often run faster on PyPy. 速度。由于它的Just-in-Time(JIT)编译器,Python程序通常在PyPy上运行得更快。
- Memory usage. Large, memory-hungry Python programs might end up taking less space with PyPy than they do in CPython. 内存使用情况。大量的内存匮乏的Python程序可能会比使用PyPy在CPython中占用更少的空间。
- Compatibility. PyPy is highly compatible with existing python code. It supports cffi and can run popular Python libraries like Twisted and Django. 兼容性。 PyPy与现有的Python代码高度兼容。它支持cffi,并且可以运行流行的Python库,如Twisted和Django。
- Sandboxing.
- Stackless mode.
Q: What’s your approach to unit testing in Python? 在Python中单元测试的方法是什么?
The most fundamental answer to this question centers around Python’s unittest testing framework. Basically, if a candidate doesn’t mention unittest when answering this question, that should be a huge red flag.
unittest supports test automation, sharing of setup and shutdown code for tests, aggregation of tests into collections, and independence of the tests from the reporting framework. The unittest module provides classes that make it easy to support these qualities for a set of tests.
Assuming that the candidate does mention unittest (if they don’t, you may just want to end the interview right then and there!), you should also ask them to describe the key elements of the unittest framework; namely, test fixtures, test cases, test suites and test runners.
A more recent addition to the unittest framework is mock. mock allows you to replace parts of your system under test with mock objects and make assertions about how they are to be used. mock is now part of the Python standard library, available as unittest.mock in Python 3.3 onwards.
The value and power of mock are well explained in An Introduction to Mocking in Python. As noted therein, system calls are prime candidates for mocking: whether writing a script to eject a CD drive, a web server which removes antiquated cache files from /tmp, or a socket server which binds to a TCP port, these calls all feature undesired side-effects in the context of unit tests. Similarly, keeping your unit-tests efficient and performant means keeping as much “slow code” as possible out of the automated test runs, namely filesystem and network access.
这个问题的最根本的答案围绕Python的单元测试测试框架。基本上,如果候选人在回答这个问题时没有提及单元测试,那应该是一个巨大的红旗。
unittest支持测试自动化,用于测试的设置和关闭代码共享,集合中的测试集合以及报告框架中测试的独立性。 unittest模块提供了一些类,可以轻松地为一组测试支持这些质量。
假设候选人提到单元测试(如果不这样做,你可能只想结束面试,那么那里!),你也应该要求他们描述单元测试框架的关键要素;即测试夹具,测试用例,测试套件和测试跑步者。
对单元测试框架的更新更为嘲笑。模拟允许您用模拟对象来替换被测系统的部分,并对如何使用它们进行断言。模拟现在是Python标准库的一部分,可以在Python 3.3之前作为unittest.mock使用。
模拟的价值和力量在Python中的模拟介绍中有很好的解释。如其中所述,系统调用是嘲笑的主要候选者:无论是写入脚本以弹出CD驱动器,从/ tmp中删除过时的缓存文件的Web服务器还是绑定到TCP端口的套接字服务器,这些调用都是不可取的在单元测试的背景下的副作用。同样,保持单元测试的效率和性能意味着在自动化测试运行(即文件系统和网络访问)中保持尽可能多的“慢代码”。
Q: What are some key differences to bear in mind when coding in Python vs. Java? 在Python与Java之间进行编码时,要牢记一些关键的区别?
Disclaimer #1.
Disclaimer #2.
With the above two disclaimers in mind, here is a sampling of some key differences to bear in mind when coding in Python vs. Java:
- Dynamic vs static typing.
- Static vs. class methods. A static method in Java does not translate to a Python class method.
- In Python, calling a class method involves an additional memory allocation that calling a static method or function does not.
- In Java, dotted names (e.g., foo.bar.method) are looked up by the compiler, so at runtime it really doesn’t matter how many of them you have. In Python, however, the lookups occur at runtime, so “each dot counts”.
- Method overloading.
- Single vs. double quotes. Whereas the use of single quotes vs. double quotes has significance in Java, they can be used interchangeably in Python (but no, it won’t allow beginnning the same
- Getters and setters (not!).
- Classes are optional.
- Indentation matters…
免责声明#1。 Java和Python之间的差异很多,可能是一个值得自己(冗长的)帖子的主题。以下简要介绍两种语言之间的一些主要区别。
免责声明#2。这里的意图不是发起与Python与Java的优点的宗教争斗(尽可能多的乐趣!)。相反,这个问题真的只是看看开发人员如何看待两种语言之间的实际差异。以下列表故意避免了从编程生产力角度讨论Python对Java的可争取的优势。
考虑到上述两个免责声明,以下是在Python与Java中编码时要记住的一些关键差异的抽样:
动态与静态类型。两种语言之间最大的区别之一是Java限于静态类型,而Python则支持动态输入变量。
静态与类的方法。 Java中的静态方法不会转化为Python类方法。
在Python中,调用类方法涉及一个额外的内存分配,调用静态方法或函数不会。
在Java中,虚拟名称(例如foo.bar.method)由编译器查找,因此在运行时,它们中有多少是无关紧要的。然而,在Python中,查找在运行时发生,因此“每个点计数”。
方法重载而Java需要明确指定具有不同签名的多个同名函数,在Python中可以使用单个函数完成相同的操作,包括可选参数,如果未由调用者指定,则使用默认值。
单引号与双引号。而使用单引号与双引号在Java中具有重要意义,它们可以在Python中互换使用(但是不允许使用双引号开始使用相同的字符串,并尝试以单引号结尾,或者反之亦然!)。
Getters和setters(不是!)。 Python中的getter和setter是多余的;相反,你应该使用“属性”内置(这是它的原因!)。在Python中,getter和setter都会浪费CPU和程序员的时间。
课程是可选的。而Java需要在封闭类定义的上下文中定义每个函数,Python没有这样的要求。
缩进在Python中很重要。这很多新手Python编程人员。
Q: What is Python particularly good for? When is using Python the “right choice” for a project? 什么是Python优势?什么时候使用Python是项目的“正确选择”?
Although likes and dislikes are highly personal, a developer who is “worth his or her salt” will highlight features of the Python language that are generally considered advantageous (which also helps answer the question of what Python is “particularly good for”). Some of the more common valid answers to this question include:
- Ease of use and ease of refactoring,
- More compact code,
- A dynamically-typed and strongly-typed language,
- It’s free and open source!
With regard to the question of when using Python is the “right choice” for a project, the complete answer also depends on a number of issues orthogonal to the language itself, such as prior technology investment, skill set of the team, and so on. Although the question as stated above implies interest in a strictly technical answer, a developer who will raise these additional issues in an interview will always “score more points” with me since it indicates an awareness of, and sensitivity to, the “bigger picture” (i.e., beyond just the technology being employed). Conversely, a response that Python is always the right choice is a clear sign of an unsophisticated developer.
虽然喜欢和不喜欢是非常个人化的,但是“值得他或她的盐”的开发人员将突出显示通常被认为是有利的Python语言的功能(这也有助于回答Python是什么“特别好”的问题)。这个问题的一些更常见的有效答案包括:
由于Python语法的灵活性,易于使用和易于重构,这使得它对于快速原型设计特别有用。
更紧凑的代码,再次感谢Python的语法,以及丰富的功能丰富的Python库(与大多数Python语言实现一起分发)。
一种动态类型和强类型的语言,提供了代码灵活性的罕见组合,同时避免了麻烦的隐式类型转换错误。
它是免费的和开源的!需要我们说更多吗?
关于使用Python是否是项目的“正确选择”的问题,完整的答案也取决于与语言本身正交的许多问题,如现有技术投资,团队技能等等。虽然上述问题意味着对严格技术性答案的兴趣,但是在面试中提出这些额外问题的开发人员总是会对我“多点”,因为它表明了对“大图”的意识和敏感性, (即,不仅仅是所采用的技术)。相反,Python总是正确的选择的答案是一个不成熟的开发人员的明确标志。
Q: What are some drawbacks of the Python language? Python语言有什么缺点?
For starters, if you know a language well, you know its drawbacks, so responses such as “there’s nothing I don’t like about it” or “it has no drawbacks” are very telling indeed.
The two most common valid answers to this question (by no means intended as an exhaustive list) are:
- The Global Interpreter Lock (GIL). CPython (the most common Python implementation) is not fully thread safe. In order to support multi-threaded Python programs, CPython provides a global lock that must be held by the current thread before it can safely access Python objects. As a result, no matter how many threads or processors are present, only one thread is ever being executed at any given time. In comparison, it is worth noting that the PyPy implementation discussed earlier in this article provides a stackless mode that supports micro-threads for massive concurrency.
- Execution speed. Python can be slower than compiled languages since it is interpreted. (Well, sort of. See our earlier discussion on this topic.)
对于初学者来说,如果你知道一门语言,你就会知道它的缺点,所以对于“没有什么我不喜欢的”或者“没有缺点”这样的回答是非常有说服力的。
这个问题的两个最常见的有效答案(绝不意味着作为详尽的列表)是:
全局解释器锁(GIL)。 CPython(最常见的Python实现)不是完全线程安全的。 为了支持多线程Python程序,CPython提供了一个全局锁,必须由当前线程持有,然后才能安全地访问Python对象。 因此,无论存在多少个线程或处理器,在任何给定时间只有一个线程将被执行。 相比之下,值得注意的是,本文前面讨论的PyPy实现提供了支持微线程大规模并发的无栈模式。
执行速度 Python可以比编译语言慢,因为它被解释。 (好的,请参阅我们之前关于这个话题的讨论。)