>백엔드 개발 >파이썬 튜토리얼 >Python 면접 질문에 대한 자세한 요약(답변 포함)

Python 면접 질문에 대한 자세한 요약(답변 포함)

不言
不言앞으로
2019-02-23 13:15:367601검색

Python 면접 질문에 대한 자세한 요약(답변 포함)

이 기사는 Python 면접 질문(답변 포함)을 요약한 것입니다. 도움이 필요한 친구들이 참고할 수 있기를 바랍니다.

관련 기사 추천: "2020 Python 인터뷰 질문 요약(최신)"

1. 다음 코드의 출력은 무엇입니까? 설명해주세요.

def extendList(val, list=[]):
    list.append(val)
    return list
list1 = extendList(10)
list2 = extendList(123,[])
list3 = extendList('a')
print "list1 = %s" % list1
print "list2 = %s" % list2
print "list3 = %s" % list3

extendList의 정의를 수정하여 다음과 같은 예상 동작을 생성하는 방법은 무엇입니까?

위 코드의 출력 결과는 다음과 같습니다.

list1 = [10, 'a']
list2 = [123]
list3 = [10, 'a']

많은 사람들이 list1=[10], list3=['a'라고 잘못 생각합니다. ], 그들은 매번 extendList가 호출될 때마다 list 매개변수의 기본값이 []로 설정될 것이라고 생각하기 때문입니다. 그러나 실제로는 함수가 정의되는 순간에 새로운 기본 목록이 한 번만 생성됩니다.

특정 매개변수 목록을 지정하지 않고 extendList를 호출하면 이 목록 집합의 값이 이후에 사용됩니다. 이는 기본 매개변수가 있는 표현식이 함수가 호출될 때가 아니라 함수가 정의될 ​​때 평가되기 때문입니다. 따라서 list1과 list3은 동일한 기본 목록에서 작동(계산)합니다. 그리고 list2는 별도의 목록에서 작동(계산)합니다. (목록 인수의 값으로 자신의 빈 목록을 전달하여)

extendList의 정의는 다음과 같이 수정할 수 있습니다.

새 목록을 생성할 때 특정 목록 매개변수는 없습니다.

다음 코드는 원하는 결과를 얻을 수 있습니다.

def extendList(val, list=None):
  if list is None:
    list = []
  list.append(val)
  return list

위를 수정하면 출력 결과는 다음과 같습니다.

list1 = [10]
list2 = [123]
list3 = ['a']

2. 다음 코드의 출력 결과는 무엇입니까? 설명해주세요.

def multipliers():
  return [lambda x : i * x for i in range(4)]
print [m(2) for m in multipliers()]

원하는 결과를 얻기 위해 위 승수 정의를 어떻게 수정하나요?

위 코드의 출력 결과는 [6, 6, 6, 6]입니다(우리가 생각했던 [0, 2, 4, 6]이 아님).

위 문제는 Python 클로저의 지연된 바인딩으로 인해 발생합니다. 이는 내부 함수가 호출될 때 인수 값이 클로저 내에서 조회된다는 것을 의미합니다. 따라서 multipliers()에서 반환된 함수가 호출되면 i 값은 가까운 범위에서 조회됩니다. 이 시점에서는 반환된 함수가 호출되었는지 여부에 관계없이 for 루프가 완료되고 i에 최종 값 3이 할당됩니다.

따라서 위 코드에 전달된 값은 2이므로 반환된 각 함수에 전달된 값 3을 곱하고 결국 6(3*2)을 반환합니다. 공교롭게도 『파이썬을 여행하는 히치하이커를 위한 안내서』에서도 람다 함수와 관련해 널리 오해되고 있는 지식 포인트가 있다고 지적하고 있는데 이번 경우는 다르다. 람다 표현식으로 생성된 함수에는 특별한 것이 없습니다. 실제로는 def로 생성된 함수와 동일합니다.

이 문제를 해결하는 몇 가지 방법은 다음과 같습니다.

한 가지 해결책은 Python 생성기를 사용하는 것입니다.

def multipliers():
  for i in range(4): yield lambda x : i * x

또 다른 해결책은 클로저를 생성하고 기본 기능을 사용하여 즉시 바인딩하는 것입니다.

def multipliers():
  return [lambda x, i=i : i * x for i in range(4)]

부분 함수를 사용하는 것도 대안입니다:

from functools import partial
from operator import mul
def multipliers():
  return [partial(mul, i) for i in range(4)]

3. 다음 코드의 출력은 무엇입니까? 설명해주세요.

class Parent(object):
    x = 1
class Child1(Parent):
    pass
class Child2(Parent):
    pass
print Parent.x, Child1.x, Child2.x
Child1.x = 2
print Parent.x, Child1.x, Child2.x
Parent.x = 3
print Parent.x, Child1.x, Child2.x

출력 결과는 다음과 같습니다:

1 1 1
1 2 1
3 2 3

많은 사람들을 혼란스럽게 하거나 놀라게 하는 것은 출력의 마지막 줄이 3 2 1 대신 3 2 3인 이유입니다. parent.x가 다음과 같을 때 child2.x의 값도 변경되는 이유는 무엇입니까? 바뀌었어? 하지만 동시에 Child1.x의 값은 변경되지 않습니까?

이 답변의 핵심은 Python에서 클래스 변수가 내부적으로 사전으로 전달된다는 것입니다.

현재 클래스의 사전에 변수 이름이 없는 경우. 그런 다음 참조된 변수 이름을 찾을 때까지 상위 클래스(예: 상위 클래스)에서 철저하게 검색합니다. (참조된 변수명이 자신의 클래스나 상위 클래스에 없으면 속성 오류가 발생합니다.)

따라서 부모 클래스에 x = 1을 설정하여 변수 x 클래스(값이 1인)가 )은 해당 클래스와 하위 클래스에서 참조될 수 있습니다. 이것이 첫 번째 print 문의 출력이 1 1 1

인 이유입니다. 따라서 하위 클래스 중 하나가 값을 덮어쓰는 경우(예: Child1.x = 2 문을 실행할 때) 이 값은 Modified in 하위 클래스에만 있습니다. . 이것이 두 번째 print 문의 출력이 1 2 1

인 이유입니다. 마지막으로 이 값이 상위 클래스에서 수정되면(예를 들어 Parent.x = 3 문을 실행할 때) 이 변경 사항은 해당 클래스에 영향을 미칩니다. 하위 클래스의 값(이 예에서는 Child2)을 덮어쓰지 않았으므로 세 번째 print 문의 출력 결과는 3 2 3

4입니다. Python2에서 다음 코드의 출력 결과는 무엇입니까? 설명해주세요.

def div1(x,y):
    print "%s/%s = %s" % (x, y, x/y)
def div2(x,y):
    print "%s//%s = %s" % (x, y, x//y)
div1(5,2)
div1(5.,2)
div2(5,2)
div2(5.,2.)

Python3에서는 결과가 어떻게 달라질까요? (물론 위의 print 문이 Python3의 구문으로 변환된다고 가정합니다.)

Python2에서 위 코드의 출력은 다음과 같습니다.

5/2 = 2
5.0/2 = 2.5
5//2 = 2
5.0//2.0 = 2.0

기본적으로 Python 2는 둘 다 정수인 경우 자동으로 정수 계산을 수행합니다. 따라서 5/2의 결과는 2이고 5./2의 결과는 2.5

Python 2에서는 다음 참조를 추가하여 이 동작을 재정의할 수 있습니다.

from future import Division

또한 // 연산자는 연산자 유형에 관계없이 항상 정수 나누기를 수행한다는 점에 유의하세요. 그렇기 때문에 Python 2에서도 5.0//2.0의 결과는 2.0입니다. 하지만 Python3에는 그러한 기능이 없습니다.

例如,在两端都是整形的情况下,它不会执行整形除法

因此,在Python3中,将会是如下结果:

5/2 = 2.5
5.0/2 = 2.5
5//2 = 2
5.0//2.0 = 2.0

注: 在 Python 3 中,/ 操作符是做浮点除法,而 // 是做整除(即商没有余数,比如 10 // 3 其结果就为 3,余数会被截除掉,而 (-7) // 3 的结果却是 -3。这个算法与其它很多编程语言不一样,需要注意,它们的整除运算会向0的方向取值。而在 Python 2 中,/ 就是整除,即和 Python 3 中的 // 操作符一样)

5、下面代码的输出结果将是什么?

list = ['a', 'b', 'c', 'd', 'e']
print list[10:]

下面的代码将输出[],不会产生IndexError错误。就像所期望的那样,尝试用超出成员的个数的index来获取某个列表的成员。

例如,尝试获取list[10]和之后的成员,会导致IndexError.

然而,尝试获取列表的切片,开始的index超过了成员个数不会产生IndexError,而是仅仅返回一个空列表。

这成为特别让人恶心的疑难杂症,因为运行的时候没有错误产生,导致bug很难被追踪到。

6、考虑下列代码片段:

list = [ [ ] ] * 5
list  # output?
list[0].append(10)
list  # output?
list[1].append(20)
list  # output?
list.append(30)
list  # output?

2,4,6,8行将输出什么结果?试解释。

输出的结果如下:

[[], [], [], [], []]
[[10], [10], [10], [10], [10]]
[[10, 20], [10, 20], [10, 20], [10, 20], [10, 20]]
[[10, 20], [10, 20], [10, 20], [10, 20], [10, 20], 30]

解释如下:

第一行的输出结果直觉上很容易理解,例如 list = [ [ ] ] * 5 就是简单的创造了5个空列表。然而,理解表达式list=[ [ ] ] * 5的关键一点是它不是创造一个包含五个独立列表的列表,而是它是一个创建了包含对同一个列表五次引用的列表。只有了解了这一点,我们才能更好的理解接下来的输出结果。

list[0].append(10) 将10附加在第一个列表上。

但由于所有5个列表是引用的同一个列表,所以这个结果将是:

[[10], [10], [10], [10], [10]]

同理,list[1].append(20)将20附加在第二个列表上。但同样由于5个列表是引用的同一个列表,所以输出结果现在是:

[[10, 20], [10, 20], [10, 20], [10, 20], [10, 20]]

作为对比, list.append(30)是将整个新的元素附加在外列表上,因此产生的结果是: [[10, 20], [10, 20], [10, 20], [10, 20], [10, 20], 30].

7、Given a list of N numbers。

给定一个含有N个数字的列表。

使用单一的列表生成式来产生一个新的列表,该列表只包含满足以下条件的值:

(a)偶数值

(b)元素为原始列表中偶数切片。

例如,如果list[2]包含的值是偶数。那么这个值应该被包含在新的列表当中。因为这个数字同时在原始列表的偶数序列(2为偶数)上。然而,如果list[3]包含一个偶数,

那个数字不应该被包含在新的列表当中,因为它在原始列表的奇数序列上。

对此问题的简单解决方法如下:

[x for x in list[::2] if x%2 == 0]

例如,给定列表如下:

list = [ 1 , 3 , 5 , 8 , 10 , 13 , 18 , 36 , 78 ]

列表生成式[x for x in list[::2] if x%2 == 0] 的结果是,

[10, 18, 78]

这个表达式工作的步骤是,第一步取出偶数切片的数字,

第二步剔除其中所有奇数。

8、给定以下字典的子类,下面的代码能够运行么?为什么?

class DefaultDict(dict):
  def __missing__(self, key):
    return []d = DefaultDict()
d['florp'] = 127

能够运行。

当key缺失时,执行DefaultDict类,字典的实例将自动实例化这个数列。

相关学习推荐:python视频教程

위 내용은 Python 면접 질문에 대한 자세한 요약(답변 포함)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 公众号:马哥Linux运维에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제