分享
分享赚钱 收藏 举报 版权申诉 / 44

类型python面试题精选.doc

  • 上传人:精品资料
  • 文档编号:11010374
  • 上传时间:2020-01-31
  • 格式:DOC
  • 页数:44
  • 大小:78.93KB
  • 配套讲稿:

    如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。

    特殊限制:

    部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。

    关 键  词:
    python面试题精选.doc
    资源描述:

    1、问题 1到底什么是 Python?你可以在回答中与其他技术进行对比(也鼓励这样做)。答案下面是一些关键点: Python 是一种解释型语言,Python 代码在运行之前不需要编译。 Python 是动态类型语言,在声明变量时,不需要说明变量的类型。 Python 非常适合面向对象的编程(OOP),因为它支持通过组合(composition)与继承(inheritance)的方式定义类(class)。Python 中没有访问说明符 public 和 private, 在 Python 语言中,函数是第一类对象(first-class objects)。这指的是它们可以被指定给变量,函数既能返回函

    2、数类型,也可以接受函数作为输入。类(class)也是第一类对象。 Python 代码编写快,但是运行速度比编译语言通常要慢。ython 允许加入基于 C 语言编写的扩展,因此我们能够优化代码,消除瓶颈,这点通常是可以实现的。numpy 就是一个很好地例子,它的运行速度真的非常快,因为很多算术运算其实并不是通过 Python 实现的。 Python 用途非常广泛网络应用,自动化,科学建模,大数据应用,等等。它也常被用作“胶水语言”,帮助其他语言和组件改善运行状况。 Python 让困难的事情变得容易,因此程序员可以专注于算法和数据结构的设计,而不用处理底层的细节。问题 2补充缺失的代码def p

    3、rint_directory_contents(sPath):“这个函数接受文件夹的名称作为输入参数,返回该文件夹中文件的路径,以及其包含文件夹中文件的路径。“# 补充代码答案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特别要注意以下几

    4、点: 命名规范要统一。如果样本代码中能够看出命名规范,遵循其已有的规范。 递归函数需要递归并终止。确保你明白其中的原理,否则你将面临无休无止的调用栈(callstack)。 我们使用 os 模块与操作系统进行交互,同时做到交互方式是可以跨平台的。你可以把代码写成 sChildPath = sPath + / + sChild,但是这个在 Windows 系统上会出错。 熟悉基础模块是非常有价值的,但是别想破脑袋都背下来,记住 Google是你工作中的良师益友。 如果你不明白代码的预期功能,就大胆提问。 坚持 KISS 原则!保持简单,不过脑子就能懂!为什么提这个问题: 说明面试者对与操作系统交

    5、互的基础知识 递归真是太好用啦问题 3阅读下面的代码,写出 A0,A1 至 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 A0A3 = A0s for s in A0A4 = i for i in A1 if i in A3A5 = i:i*i for i in A1A6 = i,i*i for i in A1答案A0 = a: 1, c: 3, b: 2, e: 5, d: 4A1 = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9A2 = A3 = 1, 3

    6、, 2, 5, 4A4 = 1, 2, 3, 4, 5A5 = 0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81A6 = 0, 0, 1, 1, 2, 4, 3, 9, 4, 16, 5, 25, 6, 36, 7, 49, 8, 64, 9, 81问题 4Python 和多线程(multi-threading)。这是个好主意码?列举一些让 Python代码以并行方式运行的方法。答案Python 并不支持真正意义上的多线程。Python 中提供了多线程包,但是如果你想通过多线程提高代码的速度,使用多线程包并不是个好

    7、主意。Python 中有一个被称为 Global Interpreter Lock(GIL)的东西,它会确保任何时候你的多个线程中,只有一个被执行。线程的执行速度非常之快,会让你误以为线程是并行执行的,但是实际上都是轮流执行。经过 GIL 这一道关卡处理,会增加执行的开销。这意味着,如果你想提高代码的运行速度,使用 threading 包并不是一个很好的方法。不过还是有很多理由促使我们使用 threading 包的。如果你想同时执行一些任务,而且不考虑效率问题,那么使用这个包是完全没问题的,而且也很方便。但是大部分情况下,并不是这么一回事,你会希望把多线程的部分外包给操作系统完成(通过开启多个

    8、进程),或者是某些调用你的 Python 代码的外部程序(例如 Spark 或 Hadoop),又或者是你的 Python 代码调用的其他代码(例如,你可以在 Python 中调用 C 函数,用于处理开销较大的多线程工作)。问题 5你如何管理不同版本的代码?答案:版本管理!GIT, SVN问题 6下面代码会输出什么:def f(x,l=):for i in range(x):l.append(i*i)print lf(2)f(3,3,2,1)f(3)答案:0, 13, 2, 1, 0, 1, 40, 1, 0, 1, 4呃?第一个函数调用十分明显,for 循环先后将 0 和 1 添加至了空列表

    9、 l 中。l 是变量的名字,指向内存中存储的一个列表。第二个函数调用在一块新的内存中创建了新的列表。l 这时指向了新生成的列表。之后再往新列表中添加 0、1、2和 4。很棒吧。第三个函数调用的结果就有些奇怪了。它使用了之前内存地址中存储的旧列表。这就是为什么它的前两个元素是 0 和 1 了。不明白的话就试着运行下面的代码吧:l_mem = l = l_mem # the first callfor i in range(2):l.append(i*i)print l # 0, 1l = 3,2,1 # the second callfor i in range(3):l.append(i*i)

    10、print l # 3, 2, 1, 0, 1, 4l = l_mem # the third callfor i in range(3):l.append(i*i)print l # 0, 1, 0, 1, 4问题 7monkey patch (猴子补丁)用来在运行时动态修改已有的代码,而不需要修改原始代码。简单的 monkey patch 实现:python #coding=utf-8 def originalFunc(): print this is original function! def modifiedFunc(): modifiedFunc=1 print this is m

    11、odified function! def main(): originalFunc() if _name_=_main_: originalFunc=modifiedFunc main() python 中所有的东西都是 object,包括基本类型。查看一个 object 的所有属性的方法是:dir(obj)函数在 python 中可以像使用变量一样对它进行赋值等操作。查看属性的方法:print locals() print globals() 问题 8这两个参数是什么意思:*args,*kwargs?我们为什么要使用它们?答案如果我们不确定要往函数中传入多少个参数,或者我们想往函数中以列表

    12、和元组的形式传参数时,那就使要用*args;如果我们不知道要往函数中传入多少个关键词参数,或者想传入字典的值作为关键词参数时,那就要使用*kwargs。args 和 kwargs 这两个标识符是约定俗成的用法,你当然还可以用*bob 和*billy,但是这样就并不太妥。下面是具体的示例:def f(*args,*kwargs): print args, kwargsl = 1,2,3t = (4,5,6)d = a:7,b:8,c:9f()f(1,2,3) # (1, 2, 3) f(1,2,3,“groovy“) # (1, 2, 3, groovy) f(a=1,b=2,c=3) # ()

    13、 a: 1, c: 3, b: 2f(a=1,b=2,c=3,zzz=“hi“) # () a: 1, c: 3, b: 2, zzz: hif(1,2,3,a=1,b=2,c=3) # (1, 2, 3) a: 1, c: 3, b: 2f(*l,*d) # (1, 2, 3) a: 7, c: 9, b: 8f(*t,*d) # (4, 5, 6) a: 7, c: 9, b: 8f(1,2,*t) # (1, 2, 4, 5, 6) f(q=“winning“,*d) # () a: 7, q: winning, c: 9, b: 8f(1,2,*t,q=“winning“,*d) #

    14、(1, 2, 4, 5, 6) a: 7, q: winning, c: 9, b: 8def f2(arg1,arg2,*args,*kwargs): print arg1,arg2, args, kwargsf2(1,2,3) # 1 2 (3,) f2(1,2,3,“groovy“) # 1 2 (3, groovy) f2(arg1=1,arg2=2,c=3) # 1 2 () c: 3f2(arg1=1,arg2=2,c=3,zzz=“hi“) # 1 2 () c: 3, zzz: hif2(1,2,3,a=1,b=2,c=3) # 1 2 (3,) a: 1, c: 3, b:

    15、2f2(*l,*d) # 1 2 (3,) a: 7, c: 9, b: 8f2(*t,*d) # 4 5 (6,) a: 7, c: 9, b: 8f2(1,2,*t) # 1 2 (4, 5, 6) f2(1,1,q=“winning“,*d) # 1 1 () a: 7, q: winning, c: 9, b: 8f2(1,2,*t,q=“winning“,*d) # 1 2 (4, 5, 6) a: 7, q: winning, c: 9, b: 8为什么提这个问题?有时候,我们需要往函数中传入未知个数的参数或关键词参数。有时候,我们也希望把参数或关键词参数储存起来,以备以后使用。有

    16、时候,仅仅是为了节省时间。问题 9下面这些是什么意思:classmethod, staticmethod, property?回答背景知识这些都是装饰器(decorator)。装饰器是一种特殊的函数,要么接受函数作为输入参数,并返回一个函数,要么接受一个类作为输入参数,并返回一个类。标记是语法糖(syntactic sugar),可以让你以简单易读得方式装饰目标对象。my_decoratordef my_func(stuff):do_thingsIs equivalent todef my_func(stuff):do_thingsmy_func = my_decorator(my_func)

    17、你可以在本网站上找到介绍装饰器工作原理的教材。真正的答案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(ar

    18、gs,kwargs)classmethoddef class_method(*args,*kwargs):print “calling class_method(0,1)“.format(args,kwargs)staticmethoddef static_method(*args,*kwargs):print “calling static_method(0,1)“.format(args,kwargs)propertydef some_property(self,*args,*kwargs):print “calling some_property getter(0,1,2)“.forma

    19、t(self,args,kwargs)return self._some_propertysome_property.setterdef some_property(self,*args,*kwargs):print “calling some_property setter(0,1,2)“.format(self,args,kwargs)self._some_property = args0propertydef some_other_property(self,*args,*kwargs):print “calling some_other_property getter(0,1,2)“.

    20、format(self,args,kwargs)return self._some_other_propertyo = MyClass()# 未装饰的方法还是正常的行为方式,需要当前的类实例(self)作为第一个参数。o.normal_method # o.normal_method() # normal_method(,),)o.normal_method(1,2,x=3,y=4) # normal_method(, 1, 2),y: 4, x: 3)# 类方法的第一个参数永远是该类o.class_method# o.class_method()# class_method(,),)o.cl

    21、ass_method(1,2,x=3,y=4)# class_method(, 1, 2),y: 4, x: 3)# 静态方法(static method)中除了你调用时传入的参数以外,没有其他的参数。o.static_method# o.static_method()# static_method(),)o.static_method(1,2,x=3,y=4)# static_method(1, 2),y: 4, x: 3)# property 是实现 getter 和 setter 方法的一种方式。直接调用它们是错误的。# “只读”属性可以通过只定义 getter 方法,不定义 sette

    22、r 方法实现。o.some_property# 调用 some_property 的 getter(,(),)# properties are nice# “属性”是很好的功能o.some_property()# calling some_property getter(,(),)# Traceback (most recent call last):# File “, line 1, in # TypeError: str object is not callableo.some_other_property# calling some_other_property getter(,(),)

    23、# VERY nice# o.some_other_property()# calling some_other_property getter(,(),)# Traceback (most recent call last):# File “, line 1, in # TypeError: str object is not callableo.some_property = “groovy“# calling some_property setter(,(groovy,),)o.some_property# calling some_property getter(,(),)# groo

    24、vyo.some_other_property = “very groovy“# Traceback (most recent call last):# File “, line 1, in # AttributeError: cant set attributeo.some_other_property# calling some_other_property getter(,(),)问题 10阅读下面的代码,它的输出结果是什么?class A(object):def go(self):print “go A go!“def stop(self):print “stop A stop!“de

    25、f pause(self):raise Exception(“Not Implemented“)class B(A):def go(self):super(B, self).go()print “go B go!“class C(A):def go(self):super(C, self).go()print “go C go!“def stop(self):super(C, self).stop()print “stop C stop!“class D(B,C):def go(self):super(D, self).go()print “go D go!“def stop(self):su

    26、per(D, self).stop()print “stop D stop!“def pause(self):print “wait D wait!“class E(B,C): passa = A()b = B()c = C()d = D()e = E()# 说明下列代码的输出结果a.go()b.go()c.go()d.go()e.go()a.stop()b.stop()c.stop()d.stop()e.stop()a.pause()b.pause()c.pause()d.pause()e.pause()答案输出结果以注释的形式表示:a.go()# go A go!b.go()# go A

    27、go!# go B go!c.go()# go A go!# go C go!d.go()# go A go!# go C go!# go B go!# go D go!e.go()# go A go!# go C go!# go B go!a.stop()# stop A stop!b.stop()# stop A stop!c.stop()# stop A stop!# stop C stop!d.stop()# stop A stop!# stop C stop!# stop D stop!e.stop()# stop A stop!a.pause()# . Exception: Not

    28、 Implementedb.pause()# . Exception: Not Implementedc.pause()# . Exception: Not Implementedd.pause()# wait D wait!e.pause()# .Exception: Not Implemented问题 11阅读下面的代码,它的输出结果是什么?class Node(object):def _init_(self,sName):self._lChildren = self.sName = sNamedef _repr_(self):return “.format(self.sName)def

    29、append(self,*args,*kwargs):self._lChildren.append(*args,*kwargs)def print_all_1(self):print selffor oChild in self._lChildren:oChild.print_all_1()def print_all_2(self):def gen(o):lAll = o,while lAll:oNext = lAll.pop(0)lAll.extend(oNext._lChildren)yield oNextfor oNode in gen(self):print oNodeoRoot =

    30、Node(“root“)oChild1 = Node(“child1“)oChild2 = Node(“child2“)oChild3 = Node(“child3“)oChild4 = Node(“child4“)oChild5 = Node(“child5“)oChild6 = Node(“child6“)oChild7 = Node(“child7“)oChild8 = Node(“child8“)oChild9 = Node(“child9“)oChild10 = Node(“child10“)oRoot.append(oChild1)oRoot.append(oChild2)oRoo

    31、t.append(oChild3)oChild1.append(oChild4)oChild1.append(oChild5)oChild2.append(oChild6)oChild4.append(oChild7)oChild3.append(oChild8)oChild3.append(oChild9)oChild6.append(oChild10)# 说明下面代码的输出结果oRoot.print_all_1()oRoot.print_all_2()答案oRoot.print_all_1()会打印下面的结果:oRoot.print_all_1()会打印下面的结果:为什么提这个问题?因为对

    32、象的精髓就在于组合(composition)与对象构造(object construction)。对象需要有组合成分构成,而且得以某种方式初始化。这里也涉及到递归和生成器(generator)的使用。生成器是很棒的数据类型。你可以只通过构造一个很长的列表,然后打印列表的内容,就可以取得与 print_all_2 类似的功能。生成器还有一个好处,就是不用占据很多内存。有一点还值得指出,就是 print_all_1 会以深度优先(depth-first)的方式遍历树(tree),而 print_all_2 则是宽度优先(width-first)。有时候,一种遍历方式比另一种更合适。但这要看你的应用

    33、的具体情况。问题 12简要描述 Python 的垃圾回收机制(garbage collection)。答案这里能说的很多。你应该提到下面几个主要的点: Python 在内存中存储了每个对象的引用计数(reference count)。如果计数值变成 0,那么相应的对象就会消失,分配给该对象的内存就会释放出来用作他用。 偶尔也会出现引用循环(reference cycle)。垃圾回收器会定时寻找这个循环,并将其回收。举个例子,假设有两个对象 o1 和 o2,而且符合o1.x = o2 和 o2.x = o1 这两个条件。如果 o1 和 o2 没有其他代码引用,那么它们就不应该继续存在。但它们的引

    34、用计数都是 1。 Python 中使用了某些启发式算法(heuristics)来加速垃圾回收。例如,越晚创建的对象更有可能被回收。对象被创建之后,垃圾回收器会分配它们所属的代(generation)。每个对象都会被分配一个代,而被分配更年轻代的对象是优先被处理的。问题 13将下面的函数按照执行效率高低排序。它们都接受由 0 至 1 之间的数字构成的列表作为输入。这个列表可以很长。一个输入列表的示例如下:random.random() for i in range(100000)。你如何证明自己的答案是正确的。def f1(lIn):l1 = sorted(lIn)l2 = i for i in

    35、 l1 if i 0 print filter(lambda s:s and len(s.strip()0, test, None, , str, , END) 装饰器:给函数添加新功能,并简化该函数调用;无参数装饰器示例:python view plain copydef log(f): def fn(*args, *kw): #*args,*kw 保证对任意个数参数都能正常调用print call + f._name_ + (). return f(*args, *kw) return fn log #调用日志装饰器 def factorial(n): return reduce(lamb

    36、da x,y: x*y, range(1, n+1) print factorial(10) call factorial(). 3628800 带参数装饰器示例:python view plain copydef log(prefix): def log_decorator(f): def wrapper(*args, *kw): print %s %s(). % (prefix, f._name_) return f(*args, *kw) return wrapper return log_decorator log(DEBUG)#DEBUG 为给装饰器传入的参数 def test():

    37、 pass print test() 执行结果 DEBUG test(). None 利用 functool.wraps 作用在返回的新函数上,使得调用装饰器以后不改变原函数的信息python view plain copyimport time, functools def performance(unit): def perf_decorator(f): functools.wraps(f) def wrapper(*args, *kw): t1 = time.time() r = f(*args, *kw) t2 = time.time() t = (t2 - t1) * 1000 if

    38、 unit=ms else (t2 - t1) print call %s() in %f %s % (f._name_, t, unit) return r return wrapper return perf_decorator performance(ms) def factorial(n): return reduce(lambda x,y: x*y, range(1, n+1) print factorial._name_ 偏函数:functools.partial(f,f 的默认参数) 减少需要提供给 f 的参数python view plain copyimport functo

    39、ols int2 = functools.partial(int, base=2) int2(1000000) 64 python 装饰器作用:为已存在的函数添加功能:参考:https:/ 两个 list 求交集,并集,差集在 python 中,数组可以用 list 来表示。如果有两个数组,分别要求交集,并集与差集,怎么实现比较方便呢? 当然最容易想到的是对两个数组做循环,即写两个 for 循环来实现。这种写法大部分同学应该都会,而且也没有太多的技术含量,本博主就不解释了。这里给大家使用更为装 bility 的一些方法。老规矩,talk is cheap,show me the code#!/

    40、usr/bin/env python#coding:utf-8Created on 2016 年 6 月 9 日author: lei.wangdef diff(listA,listB):#求交集的两种方式retA = i for i in listA if i in listBretB = list(set(listA).intersection(set(listB)print “retA is: “,retAprint “retB is: “,retB#求并集retC = list(set(listA).union(set(listB)print “retC1 is: “,retC#求差集

    41、,在 B 中但不在 A 中retD = list(set(listB).difference(set(listA)print “retD is: “,retDretE = i for i in listB if i not in listAprint “retE is: “,retEdef main():listA = 1,2,3,4,5listB = 3,4,5,6,7diff(listA,listB)if _name_ = _main_:main()让 code run 起来retA is: 3, 4, 5retB is: 3, 4, 5retC1 is: 1, 2, 3, 4, 5, 6

    42、, 7retD is: 6, 7retE is: 6, 7python 类变量和实例变量class Person:name=p1=Person()p2=Person()p1.name.append(1)print p1.name # 1print p2.name # 1print Person.name # 1class Test(object): num_of_instance = 0 def _init_(self, name): self.name = name Test.num_of_instance += 1 if _name_ = _main_: print Test.num_of

    43、_instance t1 = Test(jack) print Test.num_of_instance t2 = Test(lucy) print t1.name , t1.num_of_instance print t2.name , t2.num_of_instance class Person:name=“aaa“p1=Person()p2=Person()p1.name=“bbb“print p1.name # bbbprint p2.name # aaaprint Person.name # aaa类变量就是供类使用的变量,实例变量就是供实例使用的.这里 p1.name=“bbb“

    44、是实例调用了类变量,这其实和上面第一个问题一样,就是函数传参的问题,p1.name 一开始是指向的类变量 name=“aaa“,但是在实例的作用域里把类变量的引用改变了,就变成了一个实例变量,self.name 不再引用Person 的类变量 name 了.可以看看下面的例子:123456789class Person:name=p1=Person()p2=Person()p1.name.append(1)print p1.name # 1print p2.name # 1print Person.name # 1python 推导式列表推导式(list) 提供一种方便的列表创建方法,返回一个

    45、列表。格式:用中括号括起来,中间用 for 语句,后面跟 if 语句用作判读,满足条件的传到 for语句前面用作构建先的列表.li=i*2 for i in range(10) if i % 2 = 0print (li)0, 4, 8, 12, 16字典推导式(dic) 格式:d = key: value for (key, value) in iterablemca=“a“:1, “b“:2, “c“:3, “d“:4dicts=v:k for k,v in mca.items()Python 中单下划线和双下划线_foo: 在一个模块中以单下划线开头的变量和函数被默认当作内部函数,如果使

    46、用 from a_module import * 导入时,这部分变量和函数不会被导入。不过值得注意的是,如果使用 import a_module 这样导入模块,仍然可以用 a_module._some_var 这样的形式访问到这样的对象。 一种约定,用来指定变量私有.程序员用来指定私有变量的一种方式._foo: 这个有真正的意义:解析器用_classname_foo 来代替这个名字,以区别和其他类相同的命名. 双下划线开头的命名形式在 Python 的类成员中使用表示名字改编 (Name Mangling),即如果有一 Test 类里有一成员 _x,那么 dir(Test) 时会看到 _Tes

    47、t_x 而非 _x。这是为了避免该成员的名称与子类中的名称冲突。但要注意这要求该名称末尾没有下划线._foo_: 一种约定,Python 内部的名字 ,用来区别其他用户自定义的命名,以防冲突. 双下划线开头双下划线结尾的是一些 Python 的“ 魔术”对象,如类成员的 _init_、_del_、_add_、_getitem_ 等,以及全局的 _file_、_name_ 等。 Python 官方推荐永远不要将这样的命名方式应用于自己的变量或函数,而是按照文档说明来使用。class MyClass():def _init_(self):self._superprivate = “Hello“self._semiprivate = “, world!“mc = MyClass()print mc._superprivateTraceback (most recent

    展开阅读全文
    提示  道客多多所有资源均是用户自行上传分享,仅供网友学习交流,未经上传用户书面授权,请勿作他用。
    关于本文
    本文标题:python面试题精选.doc
    链接地址:https://www.docduoduo.com/p-11010374.html
    关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

    道客多多用户QQ群:832276834  微博官方号:道客多多官方   知乎号:道客多多

    Copyright© 2025 道客多多 docduoduo.com 网站版权所有世界地图

    经营许可证编号:粤ICP备2021046453号    营业执照商标

    1.png 2.png 3.png 4.png 5.png 6.png 7.png 8.png 9.png 10.png



    收起
    展开