Heim > Backend-Entwicklung > Python-Tutorial > Schriftliche Python-Testfragen (aktuell 2017) Python-Interviewfragen, schriftliche Testfragen

Schriftliche Python-Testfragen (aktuell 2017) Python-Interviewfragen, schriftliche Testfragen

PHPz
Freigeben: 2020-09-03 15:37:51
Original
5358 Leute haben es durchsucht

Möchten Sie einen Python-Entwicklungsjob finden? Dann müssen Sie höchstwahrscheinlich nachweisen, dass Sie mit Python umgehen können. Die folgenden Fragen decken viele Fähigkeiten im Zusammenhang mit Python ab. Der Schwerpunkt der Fragen liegt hauptsächlich auf der Sprache selbst und nicht auf einem bestimmten Paket oder Modul. Jede Frage kann nach Möglichkeit zu einem Tutorial erweitert werden. Manche Fragen umfassen möglicherweise sogar mehrere Bereiche.

Schriftliche Python-Testfragen (aktuell 2017) Python-Interviewfragen, schriftliche Testfragen

Ich hatte noch nie eine so schwierige Frage im Vorstellungsgespräch wie diese Fragen, wenn Sie ... Sie können es ganz einfach beantworten: Suchen Sie sich einen Job! Im Folgenden finden Sie die neuesten geschriebenen Python-Testfragen im Jahr 2017.

Empfohlene verwandte Artikel : „ Zusammenfassung der Python-Interviewfragen im Jahr 2020 (aktuell)

Frage 1

Was genau ist Python? Sie können in Ihrer Antwort einen Vergleich mit anderen Techniken durchführen (und werden dazu ermutigt).

Antwort

Hier sind einige wichtige Punkte:

Python ist eine interpretierte Sprache. Das heißt, im Gegensatz zur C-Sprache und von C-abgeleiteten Sprachen muss Python-Code vor der Ausführung nicht kompiliert werden. Weitere interpretierte Sprachen sind PHP und Ruby.

Python ist eine dynamisch typisierte Sprache, was bedeutet, dass Sie beim Deklarieren einer Variablen nicht den Typ der Variablen angeben müssen. Sie können Code wie x=111 und x="I'm a string" direkt schreiben und das Programm meldet keinen Fehler.

Python eignet sich sehr gut für die objektorientierte Programmierung (OOP), da es die Definition von Klassen durch Zusammensetzung und Vererbung unterstützt. In Python gibt es keinen Zugriffsspezifizierer (ähnlich wie öffentlich und privat) Die Grundlage für dieses Design ist, dass „jeder ein Erwachsener ist“.

In der Python-Sprache sind Funktionen erstklassige Objekte. Das bedeutet, dass sie Variablen zugewiesen werden können und Funktionen entweder Funktionstypen zurückgeben oder Funktionen als Eingabe akzeptieren können. Auch Klassen sind erstklassige Objekte.

Python-Code lässt sich schnell schreiben, läuft aber normalerweise langsamer als kompilierte Sprachen. Glücklicherweise ermöglicht Python das Hinzufügen von in der Sprache C geschriebenen Erweiterungen, sodass wir den Code optimieren und Engpässe beseitigen können, was normalerweise erreichbar ist. Numpy ist ein gutes Beispiel. Es läuft sehr schnell, da viele arithmetische Operationen in Python nicht implementiert sind.

Python wird in einer Vielzahl von Anwendungen eingesetzt – Netzwerkanwendungen, Automatisierung, wissenschaftliche Modellierung, Big-Data-Anwendungen usw. Es wird auch oft als „Klebesprache“ verwendet, um anderen Sprachen und Komponenten zu helfen, besser zu funktionieren.

Python macht schwierige Dinge einfach, sodass sich Programmierer auf das Design von Algorithmen und Datenstrukturen konzentrieren können, anstatt sich mit Details auf niedriger Ebene auseinanderzusetzen.

Frage 2

Ergänzen Sie den fehlenden Code

def print_directory_contents(sPath):
    """
    这个函数接受文件夹的名称作为输入参数,
    返回该文件夹中文件的路径,
    以及其包含文件夹中文件的路径。
    """
    # 补充代码
Nach dem Login kopieren

Antwort

def print_directory_contents(sPath):
    import os                                       
    for sChild in os.listdir(sPath):                
        sChildPath = os.path.join(sPath,sChild)
        if os.path.isdir(sChildPath):
            print_directory_contents(sChildPath)
        else:
            print sChildPath
Nach dem Login kopieren

Achten Sie besonders auf die folgenden Punkte :

Die Namenskonvention sollte vereinheitlicht werden. Wenn im Beispielcode eine Namenskonvention sichtbar ist, befolgen Sie die vorhandene Konvention.

Rekursive Funktionen müssen rekursiv sein und terminieren. Stellen Sie sicher, dass Sie verstehen, wie das funktioniert, sonst erhalten Sie endlose Callstacks.

Wir verwenden das OS-Modul, um mit dem Betriebssystem zu interagieren, und die Interaktionsmethode ist plattformübergreifend. Sie können den Code als sChildPath = sPath + '/' + sChild schreiben, dies führt jedoch auf Windows-Systemen zu einem Fehler.

Es ist sehr wertvoll, mit den Grundmodulen vertraut zu sein, aber versuchen Sie nicht, sie alle auswendig zu lernen. Denken Sie daran, dass Google Ihr Mentor und Freund bei Ihrer Arbeit ist.

Wenn Sie die beabsichtigte Funktion des Codes nicht verstehen, zögern Sie nicht, nachzufragen.

Halten Sie sich an das KISS-Prinzip! Halten Sie es einfach, aber Ihr Gehirn kann es verstehen!

Warum diese Frage gestellt wird:

Zeigt die Grundkenntnisse des Interviewers im Umgang mit dem Betriebssystem an

Rekursion ist wirklich nützlich

Frage 3

Lesen Sie den Code unten und schreiben Sie die Endwerte von A0, A1 in An.

A0 = dict(zip(('a','b','c','d','e'),(1,2,3,4,5)))
A1 = range(10)
A2 = [i for i in A1 if i in A0]
A3 = [A0[s] for s in A0]
A4 = [i for i in A1 if i in A3]
A5 = {i:i*i for i in A1}
A6 = [[i,i*i] for i in A1]
Nach dem Login kopieren

Antwort

A0 = {'a': 1, 'c': 3, 'b': 2, 'e': 5, 'd': 4}
A1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
A2 = []
A3 = [1, 3, 2, 5, 4]
A4 = [1, 2, 3, 4, 5]
A5 = {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}
A6 = [[0, 0], [1, 1], [2, 4], [3, 9], [4, 16], [5, 25], [6, 36], [7, 49], [8, 64], [9, 81]]
Nach dem Login kopieren

Warum stellen Sie diese Frage:

Listenverständnis ist sehr zeitsparend ist für viele Menschen auch ein großes Lernhindernis.

Wenn Sie den Code verstehen, können Sie wahrscheinlich den richtigen Wert schreiben.

Einige der Codes sind absichtlich seltsam geschrieben. Weil es unter den Menschen, mit denen Sie zusammenarbeiten, auch Verrückte geben wird.

Frage 4

Python und Multithreading. Ist das ein guter Ideencode? Listen Sie einige Möglichkeiten auf, wie Sie Python-Code parallel ausführen können.

Antwort

Python并不支持真正意义上的多线程。Python中提供了多线程包,但是如果你想通过多线程提高代码的速度,使用多线程包并不是个好主意。Python中有一个被称为Global Interpreter Lock(GIL)的东西,它会确保任何时候你的多个线程中,只有一个被执行。线程的执行速度非常之快,会让你误以为线程是并行执行的,但是实际上都是轮流执行。经过GIL这一道关卡处理,会增加执行的开销。这意味着,如果你想提高代码的运行速度,使用threading包并不是一个很好的方法。

不过还是有很多理由促使我们使用threading包的。如果你想同时执行一些任务,而且不考虑效率问题,那么使用这个包是完全没问题的,而且也很方便。但是大部分情况下,并不是这么一回事,你会希望把多线程的部分外包给操作系统完成(通过开启多个进程),或者是某些调用你的Python代码的外部程序(例如Spark或Hadoop),又或者是你的Python代码调用的其他代码(例如,你可以在Python中调用C函数,用于处理开销较大的多线程工作)。

为什么提这个问题

因为GIL就是个混账东西(A-hole)。很多人花费大量的时间,试图寻找自己多线程代码中的瓶颈,直到他们明白GIL的存在。

问题5

你如何管理不同版本的代码?

答案

版本管理!被问到这个问题的时候,你应该要表现得很兴奋,甚至告诉他们你是如何使用Git(或是其他你最喜欢的工具)追踪自己和奶奶的书信往来。我偏向于使用Git作为版本控制系统(VCS),但还有其他的选择,比如subversion(SVN)。

为什么提这个问题:

因为没有版本控制的代码,就像没有杯子的咖啡。有时候我们需要写一些一次性的、可以随手扔掉的脚本,这种情况下不作版本控制没关系。但是如果你面对的是大量的代码,使用版本控制系统是有利的。版本控制能够帮你追踪谁对代码库做了什么操作;发现新引入了什么bug;管理你的软件的不同版本和发行版;在团队成员中分享源代码;部署及其他自动化处理。它能让你回滚到出现问题之前的版本,单凭这点就特别棒了。还有其他的好功能。怎么一个棒字了得!

问题6

下面代码会输出什么:

def f(x,l=[]):
    for i in range(x):
        l.append(i*i)
    print l
f(2)
f(3,[3,2,1])
f(3)
Nach dem Login kopieren

答案:

[0, 1]
[3, 2, 1, 0, 1, 4]
[0, 1, 0, 1, 4]
Nach dem Login kopieren

呃?

第一个函数调用十分明显,for循环先后将0和1添加至了空列表l中。l是变量的名字,指向内存中存储的一个列表。第二个函数调用在一块新的内存中创建了新的列表。l这时指向了新生成的列表。之后再往新列表中添加0、1、2和4。很棒吧。第三个函数调用的结果就有些奇怪了。它使用了之前内存地址中存储的旧列表。这就是为什么它的前两个元素是0和1了。

不明白的话就试着运行下面的代码吧:

l_mem = []
l = l_mem           # the first call
for i in range(2):
    l.append(i*i)
print l             # [0, 1]
l = [3,2,1]         # the second call
for i in range(3):
    l.append(i*i)
print l             # [3, 2, 1, 0, 1, 4]
l = l_mem           # the third call
for i in range(3):
    l.append(i*i)
print l             # [0, 1, 0, 1, 4]
Nach dem Login kopieren

问题7

“猴子补丁”(monkey patching)指的是什么?这种做法好吗?

答案

“猴子补丁”就是指,在函数或对象已经定义之后,再去改变它们的行为。

举个例子:

import datetime
datetime.datetime.now = lambda: datetime.datetime(2012, 12, 12)
Nach dem Login kopieren

大部分情况下,这是种很不好的做法 - 因为函数在代码库中的行为最好是都保持一致。打“猴子补丁”的原因可能是为了测试。mock包对实现这个目的很有帮助。

为什么提这个问题?

答对这个问题说明你对单元测试的方法有一定了解。你如果提到要避免“猴子补丁”,可以说明你不是那种喜欢花里胡哨代码的程序员(公司里就有这种人,跟他们共事真是糟糕透了),而是更注重可维护性。还记得KISS原则码?答对这个问题还说明你明白一些Python底层运作的方式,函数实际是如何存储、调用等等。

另外:如果你没读过mock模块的话,真的值得花时间读一读。这个模块非常有用。

问题8

这两个参数是什么意思:*args,**kwargs?我们为什么要使用它们?

答案

如果我们不确定要往函数中传入多少个参数,或者我们想往函数中以列表和元组的形式传参数时,那就使要用*args;如果我们不知道要往函数中传入多少个关键词参数,或者想传入字典的值作为关键词参数时,那就要使用**kwargs。args和kwargs这两个标识符是约定俗成的用法,你当然还可以用*bob和**billy,但是这样就并不太妥。

下面是具体的示例:

def f(*args,**kwargs): print args, kwargs
l = [1,2,3]
t = (4,5,6)
d = {'a':7,'b':8,'c':9}
f()
f(1,2,3)                    # (1, 2, 3) {}
f(1,2,3,"pythontab")           # (1, 2, 3, 'pythontab') {}
f(a=1,b=2,c=3)              # () {'a': 1, 'c': 3, 'b': 2}
f(a=1,b=2,c=3,zzz="hi")     # () {'a': 1, 'c': 3, 'b': 2, 'zzz': 'hi'}
f(1,2,3,a=1,b=2,c=3)        # (1, 2, 3) {'a': 1, 'c': 3, 'b': 2}
f(*l,**d)                   # (1, 2, 3) {'a': 7, 'c': 9, 'b': 8}
f(*t,**d)                   # (4, 5, 6) {'a': 7, 'c': 9, 'b': 8}
f(1,2,*t)                   # (1, 2, 4, 5, 6) {}
f(q="winning",**d)          # () {'a': 7, 'q': 'winning', 'c': 9, 'b': 8}
f(1,2,*t,q="winning",**d)   # (1, 2, 4, 5, 6) {'a': 7, 'q': 'winning', 'c': 9, 'b': 8}
def f2(arg1,arg2,*args,**kwargs): print arg1,arg2, args, kwargs
f2(1,2,3)                       # 1 2 (3,) {}
f2(1,2,3,"pythontab")              # 1 2 (3, 'pythontab') {}
f2(arg1=1,arg2=2,c=3)           # 1 2 () {'c': 3}
f2(arg1=1,arg2=2,c=3,zzz="hi")  # 1 2 () {'c': 3, 'zzz': 'hi'}
f2(1,2,3,a=1,b=2,c=3)           # 1 2 (3,) {'a': 1, 'c': 3, 'b': 2}
f2(*l,**d)                   # 1 2 (3,) {'a': 7, 'c': 9, 'b': 8}
f2(*t,**d)                   # 4 5 (6,) {'a': 7, 'c': 9, 'b': 8}
f2(1,2,*t)                   # 1 2 (4, 5, 6) {}
f2(1,1,q="winning",**d)      # 1 1 () {'a': 7, 'q': 'winning', 'c': 9, 'b': 8}
f2(1,2,*t,q="winning",**d)   # 1 2 (4, 5, 6) {'a': 7, 'q': 'winning', 'c': 9, 'b': 8}
Nach dem Login kopieren

为什么提这个问题?

有时候,我们需要往函数中传入未知个数的参数或关键词参数。有时候,我们也希望把参数或关键词参数储存起来,以备以后使用。有时候,仅仅是为了节省时间。

问题9

下面这些是什么意思:@classmethod, @staticmethod, @property?

回答背景知识

这些都是装饰器(decorator)。装饰器是一种特殊的函数,要么接受函数作为输入参数,并返回一个函数,要么接受一个类作为输入参数,并返回一个类。@标记是语法糖(syntactic sugar),可以让你以简单易读得方式装饰目标对象。

@my_decorator
def my_func(stuff):
    do_things
Is equivalent to
def my_func(stuff):
    do_things
my_func = my_decorator(my_func)
Nach dem Login kopieren

你可以在本网站上找到介绍装饰器工作原理的教材。

真正的答案

@classmethod, @staticmethod和@property这三个装饰器的使用对象是在类中定义的函数。下面的例子展示了它们的用法和行为:

class MyClass(object):
    def init(self):
        self._some_property = "properties are nice"
        self._some_other_property = "VERY nice"
    def normal_method(*args,**kwargs):
        print "calling normal_method({0},{1})".format(args,kwargs)
    @classmethod
    def class_method(*args,**kwargs):
        print "calling class_method({0},{1})".format(args,kwargs)
    @staticmethod
    def static_method(*args,**kwargs):
        print "calling static_method({0},{1})".format(args,kwargs)
    @property
    def some_property(self,*args,**kwargs):
        print "calling some_property getter({0},{1},{2})".format(self,args,kwargs)
        return self._some_property
    @some_property.setter
    def some_property(self,*args,**kwargs):
        print "calling some_property setter({0},{1},{2})".format(self,args,kwargs)
        self._some_property = args[0]
    @property
    def some_other_property(self,*args,**kwargs):
        print "calling some_other_property getter({0},{1},{2})".format(self,args,kwargs)
        return self._some_other_property
o = MyClass()
# 未装饰的方法还是正常的行为方式,需要当前的类实例(self)作为第一个参数。
o.normal_method 
# <bound method MyClass.normal_method of <main.MyClass instance at 0x7fdd2537ea28>>
o.normal_method() 
# normal_method((<main.MyClass instance at 0x7fdd2537ea28>,),{})
o.normal_method(1,2,x=3,y=4) 
# normal_method((<main.MyClass instance at 0x7fdd2537ea28>, 1, 2),{&#39;y&#39;: 4, &#39;x&#39;: 3})
# 类方法的第一个参数永远是该类
o.class_method
# <bound method classobj.class_method of <class main.MyClass at 0x7fdd2536a390>>
o.class_method()
# class_method((<class main.MyClass at 0x7fdd2536a390>,),{})
o.class_method(1,2,x=3,y=4)
# class_method((<class main.MyClass at 0x7fdd2536a390>, 1, 2),{&#39;y&#39;: 4, &#39;x&#39;: 3})
# 静态方法(static method)中除了你调用时传入的参数以外,没有其他的参数。
o.static_method
# <function static_method at 0x7fdd25375848>
o.static_method()
# static_method((),{})
o.static_method(1,2,x=3,y=4)
# static_method((1, 2),{&#39;y&#39;: 4, &#39;x&#39;: 3})
# @property是实现getter和setter方法的一种方式。直接调用它们是错误的。
# “只读”属性可以通过只定义getter方法,不定义setter方法实现。
o.some_property
# 调用some_property的getter(<main.MyClass instance at 0x7fb2b70877e8>,(),{})
# &#39;properties are nice&#39;
# “属性”是很好的功能
o.some_property()
# calling some_property getter(<main.MyClass instance at 0x7fb2b70877e8>,(),{})
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# TypeError: &#39;str&#39; object is not callable
o.some_other_property
# calling some_other_property getter(<main.MyClass instance at 0x7fb2b70877e8>,(),{})
# &#39;VERY nice&#39;
# o.some_other_property()
# calling some_other_property getter(<main.MyClass instance at 0x7fb2b70877e8>,(),{})
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# TypeError: &#39;str&#39; object is not callable
o.some_property = "pythontab"
# calling some_property setter(<main.MyClass object at 0x7fb2b7077890>,(&#39;pythontab&#39;,),{})
o.some_property
# calling some_property getter(<main.MyClass object at 0x7fb2b7077890>,(),{})
# &#39;pythontab&#39;
o.some_other_property = "pythontab.com"
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# AttributeError: can&#39;t set attribute
o.some_other_property
# calling some_other_property getter(<main.MyClass object at 0x7fb2b7077890>,(),{})
Nach dem Login kopieren

问题10

简要描述Python的垃圾回收机制(garbage collection)。

答案

这里能说的很多。你应该提到下面几个主要的点:

Python在内存中存储了每个对象的引用计数(reference count)。如果计数值变成0,那么相应的对象就会小时,分配给该对象的内存就会释放出来用作他用。

偶尔也会出现引用循环(reference cycle)。垃圾回收器会定时寻找这个循环,并将其回收。举个例子,假设有两个对象o1和o2,而且符合o1.x == o2和o2.x == o1这两个条件。如果o1和o2没有其他代码引用,那么它们就不应该继续存在。但它们的引用计数都是1。

Python中使用了某些启发式算法(heuristics)来加速垃圾回收。例如,越晚创建的对象更有可能被回收。对象被创建之后,垃圾回收器会分配它们所属的代(generation)。每个对象都会被分配一个代,而被分配更年轻代的对象是优先被处理的。

问题11

将下面的函数按照执行效率高低排序。它们都接受由0至1之间的数字构成的列表作为输入。这个列表可以很长。一个输入列表的示例如下:[random.random() for i in range(100000)]。你如何证明自己的答案是正确的。

def f1(lIn):
    l1 = sorted(lIn)
    l2 = [i for i in l1 if i<0.5]
    return [i*i for i in l2]
def f2(lIn):
    l1 = [i for i in lIn if i<0.5]
    l2 = sorted(l1)
    return [i*i for i in l2]
def f3(lIn):
    l1 = [i*i for i in lIn]
    l2 = sorted(l1)
    return [i for i in l1 if i<(0.5*0.5)]
Nach dem Login kopieren

答案

按执行效率从高到低排列:f2、f1和f3。要证明这个答案是对的,你应该知道如何分析自己代码的性能。Python中有一个很好的程序分析包,可以满足这个需求。

import cProfile
lIn = [random.random() for i in range(100000)]
cProfile.run(&#39;f1(lIn)&#39;)
cProfile.run(&#39;f2(lIn)&#39;)
cProfile.run(&#39;f3(lIn)&#39;)
Nach dem Login kopieren

为了向大家进行完整地说明,下面我们给出上述分析代码的输出结果:

>>> cProfile.run(&#39;f1(lIn)&#39;)
         4 function calls in 0.045 seconds
   Ordered by: standard name
   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.009    0.009    0.044    0.044 <stdin>:1(f1)
        1    0.001    0.001    0.045    0.045 <string>:1(<module>)
        1    0.000    0.000    0.000    0.000 {method &#39;disable&#39; of &#39;_lsprof.Profiler&#39; objects}
        1    0.035    0.035    0.035    0.035 {sorted}
>>> cProfile.run(&#39;f2(lIn)&#39;)
         4 function calls in 0.024 seconds
   Ordered by: standard name
   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.008    0.008    0.023    0.023 <stdin>:1(f2)
        1    0.001    0.001    0.024    0.024 <string>:1(<module>)
        1    0.000    0.000    0.000    0.000 {method &#39;disable&#39; of &#39;_lsprof.Profiler&#39; objects}
        1    0.016    0.016    0.016    0.016 {sorted}
>>> cProfile.run(&#39;f3(lIn)&#39;)
         4 function calls in 0.055 seconds
   Ordered by: standard name
   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.016    0.016    0.054    0.054 <stdin>:1(f3)
        1    0.001    0.001    0.055    0.055 <string>:1(<module>)
        1    0.000    0.000    0.000    0.000 {method &#39;disable&#39; of &#39;_lsprof.Profiler&#39; objects}
        1    0.038    0.038    0.038    0.038 {sorted}
Nach dem Login kopieren

为什么提这个问题?

定位并避免代码瓶颈是非常有价值的技能。想要编写许多高效的代码,最终都要回答常识上来——在上面的例子中,如果列表较小的话,很明显是先进行排序更快,因此如果你可以在排序前先进行筛选,那通常都是比较好的做法。其他不显而易见的问题仍然可以通过恰当的工具来定位。因此了解这些工具是有好处的。

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

Das obige ist der detaillierte Inhalt vonSchriftliche Python-Testfragen (aktuell 2017) Python-Interviewfragen, schriftliche Testfragen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage