Maison  >  Article  >  développement back-end  >  Résumé détaillé des questions d'entretien Python (avec réponses)

Résumé détaillé des questions d'entretien Python (avec réponses)

不言
不言avant
2019-02-23 13:15:367549parcourir

Résumé détaillé des questions d'entretien Python (avec réponses)

Cet article vous apporte un résumé des questions d'entretien Python (avec réponses). Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer. aidé.

Articles connexes recommandés  : " Résumé des questions d'entretien Python en 2020 (dernières) "

1 . Quelle est la sortie du code suivant ? Veuillez expliquer.

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

Comment modifier la définition de extendList pour produire le comportement attendu suivant ?

Le résultat de sortie du code ci-dessus sera :

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

Beaucoup de personnes penseront à tort que list1= [10], list3=['a'], car ils pensaient qu'à chaque fois que extendList est appelé, la valeur par défaut du paramètre list sera définie sur [Mais la situation réelle est que le nouveau]. La liste par défaut n'est utilisée que lorsque la fonction est appelée Créée une fois au moment de la définition.

Lorsque extendList est appelé sans spécifier de liste de paramètres spécifique, les valeurs de cet ensemble de liste seront utilisées par la suite. En effet, les expressions avec des paramètres par défaut sont évaluées lorsque la fonction est définie et non lorsqu'elle est appelée. Par conséquent, list1 et list3 fonctionnent (calculent) sur la même liste par défaut. Et list2 fonctionne (calcule) sur une liste distincte. (En passant une propre liste vide comme valeur de l'argument de liste).

La définition de extendList peut être modifiée comme suit.

Bien que cela crée une nouvelle liste sans paramètres de liste spécifiques.

Le code suivant peut produire les résultats souhaités.

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

Avec la modification ci-dessus, le résultat de sortie deviendra :

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

2. Quel sera le résultat de sortie du code suivant ? Veuillez expliquer.

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

Comment modifier la définition des multiplicateurs ci-dessus pour produire les résultats souhaités ?

Le résultat de sortie du code ci-dessus est [6, 6, 6, 6] (et non [0, 2, 4, 6] comme nous le pensions).

Le problème ci-dessus est causé par la liaison retardée des fermetures Python. Cela signifie que lorsque la fonction interne est appelée, la valeur de l'argument est recherchée dans la fermeture. Par conséquent, lorsqu’une fonction renvoyée par multiplicateurs() est appelée, la valeur de i sera recherchée dans la plage proche. À ce stade, que la fonction renvoyée ait été appelée ou non, la boucle for est terminée et i reçoit la valeur finale de 3.

Par conséquent, chaque fois que la fonction renvoyée est multipliée par la valeur transmise 3, car la valeur transmise dans le code précédent est 2, elle renvoie finalement 6 (3*2). Par coïncidence, "The Hitchhiker's Guide to Python" a également souligné qu'il existe également un point de connaissance largement mal compris lié aux fonctions lambdas, mais il est différent de ce cas. Il n'y a rien de spécial dans la fonction créée par l'expression lambda. C'est en fait la même que la fonction créée par def.

Voici quelques façons de résoudre ce problème.

Une solution consiste à utiliser des générateurs Python.

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

Une autre solution consiste à créer une fermeture et à la lier immédiatement à l'aide de la fonction par défaut.

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

Une alternative consiste à utiliser des fonctions partielles :

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

3. Quel sera le résultat du code suivant ? Veuillez expliquer.

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

Le résultat sera :

1 1 1
1 2 1
3 2 3

Ce qui confond ou surprend beaucoup de gens, c'est pourquoi la dernière ligne de résultat est 3 2 3 au lieu de 3 2 1. Pourquoi le parent changer. x change également la valeur de child2.x ? Mais en même temps la valeur de Child1.x n’est pas modifiée ?

La clé de cette réponse est qu'en Python, les variables de classe sont transmises en interne sous forme de dictionnaire.

Si un nom de variable n'est pas trouvé dans le dictionnaire sous la classe actuelle. Recherchez ensuite de manière exhaustive dans les classes de niveau supérieur (telles que sa classe parent) jusqu'à ce que le nom de la variable référencée soit trouvé. (Si le nom de la variable de référence n'est pas trouvé dans la propre classe ou dans une classe de niveau supérieur, une erreur d'attribut sera générée.)

Par conséquent, définissez x = 1 dans la classe parent et laissez la variable x classe (avec la valeur 1) Peut être référencé dans sa classe et ses sous-classes. C'est pourquoi la sortie de la première instruction print est 1 1 1

Par conséquent, si l'une de ses sous-classes est écrasée par une valeur (par exemple, lorsque nous exécutons l'instruction Child1.x = 2), cette valeur Modifié uniquement dans les sous-classes. C'est pourquoi la sortie de la deuxième instruction print est 1 2 1

Enfin, si cette valeur est modifiée dans la classe parent, (par exemple, lorsque nous exécutons l'instruction Parent.x = 3), ce changement Cela affectera les valeurs qui n'ont pas été remplacées par la sous-classe (dans cet exemple, Child2). C'est pourquoi le résultat de la troisième instruction d'impression est 3 2 3

4. le résultat sous Python2 Quel sera-t-il ? Veuillez expliquer.

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.)

En quoi les résultats seront-ils différents sous Python3 ? (Bien sûr, en supposant que l'instruction print ci-dessus soit convertie en syntaxe Python3)

Dans Python2, la sortie du code ci-dessus sera

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

Par défaut, Python 2 effectue automatiquement des calculs d'entiers si deux sont tous des entiers. Par conséquent, 5/2 donne 2 et 5./2 donne 2.5

Notez que dans Python 2, vous pouvez remplacer ce comportement en ajoutant la référence suivante.

de la future division d'importation

Notez également que l'opérateur // effectuera toujours une division entière, quel que soit le type de l'opérateur. C'est pourquoi même dans Python 2, le résultat de 5.0//2.0 est 2.0. Cependant, dans Python3, une telle fonctionnalité n'existe pas,

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

因此,在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视频教程

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer