常见python语法面试题

1、迭代器和生成器函数区别? 

答:(1)迭代器是一个更抽象的概念,任何对象,如果它的类有 next 方法和 iter
方法返回自己本身。对于 string、list、dict、tuple 等这类容器对象,使用 for 循
环遍历是很方便的。在后台 for 语句对容器对象调用 iter()函数,iter()是 python
的内置函数。iter()会返回一个定义了 next()方法的迭代器对象,它在容器中逐个
访问容器内元素,next()也是 python 的内置函数。在没有后续元素时,next()会
抛出一个 StopIteration 异常 
(· 2)生成器(Generator)是创建迭代器的简单而强大的工具。它们写起来就像
是正规的函数,只是在需要返回数据的时候使用 yield 语句。每次 next()被调用
时,生成器会返回它脱离的位置(它记忆语句最后一次执行的位置和所有的数据
值) 
区别:生成器能做到迭代器能做的所有事,而且因为自动创建了__iter__()和 next()
方法,生成器显得特别简洁,而且生成器也是高效的,使用生成器表达式取代列表
解析可以同时节省内存。除了创建和保存程序状态的自动方法,当发生器终结时,
还会自动抛出 StopIteration 异常 
 

2、迭代器的实现? 

答: 
class Squares(object): 
    def __init__(self, start, stop): 
        self.start = start 
        self.stop = stop 
    def __iter__(self): 
        return self 
    def next(self): 
        if self.start >= self.stop: 
            raise StopIteration 
        current = self.start * self.start 
        self.start += 1 
        return current 
 

3、输入目录,输出打印 全部文件以及文件夹 

答: 
#encoding=utf-8 
import os 
directory = raw_input("pls enter dir:") 
list_dirs = os.listdir(directory)  
for df in list_dirs: 
 path = os.path.join(directory, df)  
 print path 
 

4、os.path 和 sys.path 区别 

答: os.path 是一个模块,用来处理目录、路径相关的模块。  
sys.path 是一个列表,返回解释器相关的目录列表、环境变量、注册表等初始化
信息 
 

5、range 和 xrange 区别 

答:range 会直接生成一个 list 对象,而 xrange 则不会直接生成一个 list,而是
每次调用返回其中的一个值,xrange 是一个生成器 
 

6、装饰器: 求函数执行时间,打印日志 

答: 
def benchmark(func): 
    """ 
    装饰器打印一个函数的执行时间 
    """ 
    import time 
    def wrapper(*args, **kwargs): 
        t = time.clock() 
        res = func(*args, **kwargs) 
        print func.__name__, time.clock()-t 
        return res 
    return wrapper 
def logging(func): 
    """ 
    装饰器记录函数日志 
    """ 
    def wrapper(*args, **kwargs): 
        res = func(*args, **kwargs) 
        print func.__name__, args, kwargs 
        return res 
    return wrapper 
@benchmark 
@logging 
def reverse_string(string): 
    return str(string) 
 

7、import 方法:导入顺序 

答:推荐所有的模块在 Python 模块的开头部分导入。 而且最好按照这样的顺
序: 
1. Python 标准库模块 
2. Python 第三方模块 
3. 应用程序自定义模块 
 

8、python 里如何实现 tuple 和 list 的转换 

答:可以通过 python 内建函数去转换 
A=(1,2,3) 
B = list(A) 
C = tuple(B) 
 

9、如何用 python 来进行查询和替换一个文本字符串 

答:可以通过 string 类型里的 find()函数实现查找,replace()函数去替换 
 

10、python 正则匹配里 search()和 match()的区别? 

答:re.match() 从第一个字符开始找, 如果第一个字符就不匹配就返回 None, 不
继续匹配. 用于判断字符串开头或整个字符串是否匹配,速度快. 
re.search() 会整个字符串查找,直到找到一个匹配 
 

11、python 里如何生成随机数 

答:通过 random 模块,使用例如 random.randint,random.randrange 函数 
 

12、python 里如何拷贝一个对象 

答:python 里面有深拷贝浅拷贝之说,可以使用 copy 模块里的 copy 函数实现
浅拷贝,copy.deepcopy 实现深拷贝 
 

13、如何在一个 function 里设置一个全局变量 

答:通过在函数中指定 global 关键字 
a = 2 
def func(): 
 global a 
 print a 
func() 
 

14、怎样在 python 中拼接字符串 

答:可以直接通过字符串相加操作,s=”123”,s+”234”,或者两变量相加 l=”456”,s+l 
 

15、实现 string->float,但要逐个字符的去解析,不能调用已有的函数 

答: def my_float(s): 
    ''‘字符串转换成 float''' 
    value = 0.0 
    dot_position = 0 
    status = False 
    for ch in s: 
        if ch != '.' : 
            value = value*10 + (ord(ch) - 48)  
            if not status: 
                dot_position += 1 
        else: 
            status = True 
    return value/(10 ** (len(s)-dot_position-1)) 
 

16、python 中 yield 的用法 

答:yield 简单说来就是一个生成器,生成器是这样一个函数,它记住上一次返
回时在函数体中的位置。对生成器函数的第二次(或第 n 次)调用跳转至该函
数中间,而上次调用的所有局部变量都保持不变。 
 

17、xrange 和 range 的区别 

答:xrange 用法与 range 完全相同,所不同的是生成的不是一个 list 对象,而
是一个生成器。Xrange 不会上来就开辟一个空间,循环用 xrange 比较好 

 
18、map(),reduce()的用法 

答:(1)map(function, sequence[, sequence, ...]) -> list 
function:是一个函数 
sequence:是一个或多个序列,取决于 function 需要几个参数 
返回值是一个 list 
(2)reduce(function, sequence[, initial]) -> value 
function:该函数有两个参数 
sequence:序列可以是 str,tuple,list 
initial:固定初始值 

 
19、一句话的乘阶函数 

答:reduce(lambda x,y: x*y, range(1,n+1)) 
 

20、介绍一下 except 的用法和作用 

答:except: #捕获所有异常 
except: <异常名>: #捕获指定异常 
except:<异常名 1,异常名 2):捕获异常 1 或者异常 2 
except:<异常名>,<数据>:捕获指定异常及其附加的数据 
except:<异常名1,异常名2>:<数据>:捕获异常名1或者异常名2,及附加的数据库 
 

21、简述 python 是如何进行内存管理机制和引用计数 

答:Python 作为一种动态类型的语言,其对象和引用分离,Python 采取了一种
相对简单的垃圾回收机制,即引用计数。 
 垃圾回收(Garbage Collection)python 提供了 del 方法来删除某个变量,它的作
用是让某个对象引用数减少 1。当某个对象引用数变为 0 时并不是直接将它从内
存空间中清除掉,而是采用垃圾回收机制 gc 模块,当这些引用数为 0 的变量规
模达到一定规模,就自动启动垃圾回收,将那些引用数为 0 的对象所占的内存空
间释放。这里 gc 模块采用了分代回收方法,将对象根据存活的时间分为三“代”,
所有新建的对象都是 0 代,当 0 代对象经过一次自动垃圾回收,没有被释放的对
象会被归入 1 代,同理 1 代归入 2 代。每次当 0 代对象中引用数为 0 的对象超
过 700 个时,启动一次 0 代对象扫描垃圾回收,经过 10 次的 0 代回收,就进行
一次 0 代和 1 代回收,1 代回收次数超过 10 次,就会进行一次 0 代、1 代和 2
代回收。而这里的几个值是通过查询 get_threshold()返回(700,10,10)得到的。此
外,gc 模块还提供了手动回收的函数,即 gc.collect() 
引用计数(reference counting),针对可以重复利用的内存缓冲区和内存,python
使用了一种引用计数的方式来控制和判断某快内存是否已经没有再被使用。即每
个对象都有一个计数器 count,记住了有多少个变量指向这个对象,当这个对象
的引用计数器为 0 时,假如这个对象在缓冲区内,那么它地址空间不会被释放,
而是等待下一次被使用,而非缓冲区的该释放就释放。这里通过 sys 包中的
getrefcount()来获取当前对象有多少个引用。 
 

22、什么是 lambda 函数?它有什么好处? 

答:lambda 函数是一个可以接收任意多个参数(包括可选参数)并且返回单个表
达式值的函数 
1、lambda 函数比较轻便,即用即仍,很适合需要完成一项功能,但是此功能只
在此一处使用,连名字都很随意的情况下; 
 
2、匿名函数,一般用来给 filter,map 这样的函数式编程服务; 

3、作为回调函数,传递给某些应用,比如消息处理 

23、python 是如何进行类型转换的? 

答:Python 提供了将变量或值从一种类型转换成另一种类型的内置函数 
int(x [,base ])         将 x 转换为一个整数   
long(x [,base ])        将 x 转换为一个长整数   
float(x )               将 x 转换到一个浮点数   
complex(real [,imag ])  创建一个复数   
str(x )                 将对象 x 转换为字符串   
repr(x )                将对象 x 转换为表达式字符串   
eval(str )              用来计算在字符串中的有效 Python 表达式,并返回一个
对象   
tuple(s )               将序列 s 转换为一个元组   
list(s )                将序列 s 转换为一个列表   
chr(x )                 将一个整数转换为一个字符   
unichr(x )              将一个整数转换为 Unicode 字符   
ord(x )                 将一个字符转换为它的整数值   
hex(x )                 将一个整数转换为一个十六进制字符串   
oct(x )                 将一个整数转换为一个八进制字符串 
 

24、python 中 pass 语句的作用是什么? 

答:pass 语句什么也不做,一般作为占位符或者创建占位程序,pass 语句不会
执行任何操作,pass 在软件设计阶段也经常用来作为接口设计,实现相应的重
写实现 
 

25、如何知道一个 python 对象的类型? 

答:通过 type()获取对象的类型,也可通过 isinstance()去判断对象是否是某类型 
 

26、@(decorator)的作用是什么? 

答:装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典
的有插入日志、性能测试、事务处理等。装饰器是解决这类问题的绝佳设计,有
了装饰器,我们就可以抽离出大量函数中与函数功能本身无关的雷同代码并继续
重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能 

 
27、Python 有哪些数据结构 

答:序列:列表、元祖 
 映射:字典 
 集合:set 
 

28、io 密集型和 cpu 密集型区别 

答:io 密集型:系统运作,大部分的状况是 CPU 在等 I/O (硬盘/内存) 的读/
写 
Cpu 密集型:大部份时间用来做计算、逻辑判断等 CPU 动作的程序称之 CPU 密
集型 
 

29、Python 特殊语法:filter、map、reduce、lambda 

答: 
filter(...) 
filter(function or None, sequence) -> list, tuple, or string 
function:接受一个参数,返回布尔值 True 或 False 
sequence:序列可以是 str,tuple,list 
filter 函数会对序列参数 sequence 中的每个元素调用 function 函数,最后返回的
结果包含调用结果为 True 的元素。 
map(...) 
        map(function, sequence[, sequence, ...]) -> list 
function:是一个函数 
sequence:是一个或多个序列,取决于 function 需要几个参数 
返回值是一个 list 
参数序列中的每一个元素分别调用 function 函数,返回包含每次 function 函数返
回值的 list 
reduce(...) 
reduce(function, sequence[, initial]) -> value 
function:该函数有两个参数 
sequence:序列可以是 str,tuple,list 
initial:固定初始值 
reduce 依次从 sequence 中取一个元素,和上一次调用 function 的结果做参数再
次调用 function。 第一次调用 function 时,如果提供 initial 参数,会以 sequence
中的第一个元素和 initial 作为参数调用 function,否则会以序列 sequence 中的
前两个元素做参数调用 function。 注意 function 函数不能为 None 
lambda 
python lambda 会创建一个函数对象,但不会把这个函数对象赋给一个标识符 
 
 

31、谈谈你对面向对象的理解 

答:  面向对象是相对于面向过程而言的。面向过程语言是一种基于功能分析的、
以算法为中心的程序设计方法;而面向对象是一种基于结构分析的、以数据为中
心的程序设计思想。在面向对象语言中有一个有很重要东西,叫做类。 
面向对象有三大特性:封装、继承、多态。 

 
32、交换两个变量的值 

答:a,b = b,a 
 

33、对于一个字符串进行逐字符或逐词的反转 

答: 
def string_reverse(string):   
return string[::-1] 
 
 

34、and or 作为三目运算符时需要注意哪些事项 

答:注意 and 是左右同时满足真,or 是从左到右,只要左边出现真就不会去判
断后面一个条件 
>>> True and 1 or 0 

>>> False and 1 or 0 

>>> True and "Fire" or "Water" 
'Fire' 
>>> False and "Fire" or "Water" 
'Water' 
 
 

35、对于 dict 的 items() 与 iteritems()有什么区别 

答:在 python2 中,dict.items(): 返回一个的 dictionary’s ( key,value ) 对的列
表。 
dict.iteritems(): 返回一个迭代器 通过 dictionary’s ( key,value ) 对 
>>> d={1:'one',2:'two',3:'three'} 
>>> type(d.items()) 
<type 'list'> 
>>> type(d.iteritems()) 
<type 'dictionary-itemiterator'> 
注意:在 python3 中不存在 iteritems 属性,只有 items 属性,并且返回的是列
表,如果需要其返回迭代器那么,需要显示转换 iter(d.items()) 
 

36、如何用 python 实现单例模式 

答:这只是其中的一种实现方式 
 
 class Singleton(object):   
      def __new__(cls, *args, **kw):   
          if not hasattr(cls, '_instance'):   
              cls._instance = super(Singleton, cls).__new__(cls, *args, **kw)   
          return cls._instance      
 class MyClass(Singleton):   
      a = 1   
     
 one = MyClass()   
 two = MyClass()   
 
 

37、有两个 list,写出对应组合生成一个 dict 的方法 如 name = ['a','b'] age = [18,19] 

答: 
dict(zip(name,age)) 
 
 

38、写出一个函数,给定参数 n,生成含有 n 个元素值为 1~n 的数组,元素顺序随机,但值不重复。 

答: 
#encoding=utf-8 
import random 
 
def getList(n): 
 setlist = [] 
 while len(setlist) < n: 
  num = random.randint(1,n) 
  if num not in setlist: 
   setlist.append(num) 
 return setlist 
 
setlist = getList(20) 
print setlist 

 
40、设计实现遍历目录与子目录,抓取.pyc 文件 

答: 
import os 
res = [] 
for root,directory,files in os.walk("./"): 
    print root 
    for filename in files:   
        name, suf = os.path.splitext(filename)   
        if suf == ".pyc":   
            res.append(os.path.join(root, filename))   
print res 
 
 

41、域名解析的过程 

答:1.现在我有一台计算机,通过 ISP 接入了互联网,那么 ISP 就会给我分配一
个 DNS 服务器,这个 DNS 服务器不是权威服务器,而是相当于一个代理的 dns
解析服务器,他会帮你迭代权威服务器返回的应答,然后把最终查到 IP 返回给
你。 
2.现在的我计算机要向这台 ISPDNS 发起请求查询 www.baidu.com 这个域名了,
(经网友提醒:这里其实准确来说不是 ISPDNS,而应该是用户自己电脑网络设置
里的 DNS,并不一定是 ISPDNS。比如也有可能你手工设置了 8.8.8.8) 
3.ISPDNS 拿到请求后,先检查一下自己的缓存中有没有这个地址,有的话就直
接返回。这个时候拿到的 ip 地址,会被标记为非权威服务器的应答。 
4.如果缓存中没有的话,ISPDNS 会从配置文件里面读取 13 个根域名服务器的地
址(这些地址是不变的,直接在 BIND 的配置文件中), 
5.然后像其中一台发起请求。 
6.根服务器拿到这个请求后,知道他是 com.这个顶级域名下的,所以就会返回
com 域中的 NS 记录,一般来说是 13 台主机名和 IP。 
7.然后 ISPDNS 向其中一台再次发起请求,com 域的服务器发现你这请求是
baidu.com 这个域的,我一查发现了这个域的 NS,那我就返回给你,你再去查。
 
8.ISPDNS 不厌其烦的再次向 baidu.com 这个域的权威服务器发起请求,
baidu.com 收到之后,查了下有 www 的这台主机,就把这个 IP 返回给你了, 
9.然后 ISPDNS 拿到了之后,将其返回给了客户端,并且把这个保存在高速缓存
中。 
 

42、请写出一段 Python 代码实现删除一个 list 里面的重复元素 

答: 
方法一: 
ids = [1,2,3,3,4,6,6,7] 
new_ids = [] 
for id in ids: 
    if id not in new_ids: 
        new_ids.append(id) 

print new_ids 
方法二: 
import itertools 
ids.sort() 
it = itertools.groupby(ids) 
new_ids5 = [] 
for k, g in it: 
    new_ids5.append(k) 
print new_ids5 
方法三: 
new_ids3 = list(set(ids)) 
new_ids3.sort(ids.index) 
print new_ids3 
    方法四: 
ids = [1, 2, 3, 3, 4, 6, 6, 7] 
new_ids4 = reduce(lambda x, y: x if y in x else x + [y], [[], ] + ids) 
print new_ids4 
 
 

43、现有一个文件 url.txt,每一行都是一个网站名(例如:map.baidu.com)请用 Python 读取这个文件并且使用正则表达式匹配简单的以“www.”开头,以“.com”或者".edu"或者".gov"作结尾的web 域名,然后输出到另一个文件中(上机) 

答: 
#encoding=utf-8 
def isDomain(line): 
 l = len(line) 
 if line.startswith("www") or line[:l-1].endswith(".com") or 
line[:l-1].endswith(".edu") or line[:l-1].endswith(".gov"): 
  return True 
 else: 
  return False 
def getDomain(filename,destname): 
 fr = open(filename,"r+") 
 fw = open(destname,"w+") 
 file_object = fr.readlines() 
 for line in file_object: 
  print line 
  if isDomain(line):  
   fw.write(line)  
 fr.close() 
 fw.close() 
 return None  
getDomain("source.txt","dest.txt") 
 
 
 

44、两个序列 a,b,大小都为 n,序列元素的值任意整形数,无序:要求:通过交换 a,b 中的元素,使[序列 a 元素的和]与[序列 b 元素的和]之间的差最小。(上机) 

答: 
求解思路: 
1. 求出两个序列的差 num = sum(a) – sum(b) 
2. 假如交换了 a 中的 i,下表和 b 中的 j 下表的元素,则交换后的差为: 
num’ = (sum(a) – a[i] + b[j]) – (sum(b) – b[j] + a[i]) 
num’ = sum(a) – sum(b) – 2(a[i] - b[j]) 
num’ = num-2(a[i] - b[j]) 
3. 那么由此我们可以得出,假设 a[i]-b[j]=x,那么 num’ = num-2x 
所以,我们去一直寻找 i 和 j,使得 x 在(0,num)之间,就将其交换,最后直到不
出这样的 i 和 j 
代码如下: 
#encoding=utf-8 
def convertMin(list1,list2): 
 if len(list1) != len(list2): 
  return 
 sum1 = sum(list1) 
 sum2 = sum(list2) 
 if sum1 < sum2: 
  list1,list2 = list2,list1 
 temp = True 
 length = len(list1) 
 while temp: 
  temp = False 
  for i in xrange(length): 
   for j in xrange(length): 
    print "123" 
    sumindex = list1[i] - list2[j] 
    sumall = sum(list1) - sum(list2) 
    if (sumindex < sumall) and (sumindex > 0): 
     temp = True 
     list1[i],list2[j] = list2[j],list1[i] 
a = [3,2,5,7,5,9] 
b = [1,2,3,2,6,7] 
convertMin(a,b) 
print "---------", 
print a,b 
 

45、什么时候用 is 什么时候用 == 

答:(1)== is for value equality. Use it when you would like to know if two objects 
have the same value. 
(2)is is for reference equality. Use it when you would like to know if two 
references refer to the same object. 
可以根据缓存整型数据的范围-5~257 来理解: 
>>> a = 500 
>>> b = 500 
>>> a == b 
True 
>>> a is b 
False 
>>> c = 200 
>>> d = 200 
>>> c == d 
True 
>>> c is d 
True 

 
46、python 新类和旧类的区别 

答:Python 2.x 中默认都是经典类,只有显式继承了 object 才是新式类 
Python 3.x 中默认都是新式类,不必显式的继承 object 
1.新式类对象可以直接通过__class__属性获取自身类型:type,类型的统一 
2. 继承搜索的顺序发生了改变,经典类多继承属性搜索顺序: 先深入继承树左
侧,再返回,开始找右侧;新式类多继承属性搜索顺序: 先水平搜索,然后再向上
移动 
3. 新式类增加了__slots__内置属性, 可以把实例属性的种类锁定到__slots__规定
的范围之中 
 

47、python 中闭包函数的理解 

答:对于内部函数 g,它能引用到外部函数 f 的局部变量 n,而且即使 f 已经返
回。把这种现象就称为闭包, 当函数 f 的生命周期结束之后,n 这个变量依然存
在,因为它被闭包引用了,所以不会被回收。和闭包相关的就是 __closure__ 属
性 
 

48、请写出一段 Python 代码实现分组一个 list 里面的元素,比如[1,2,3,...100]变成 [[1,2,3],[4,5,6]....] 

答: 
[a[i:i+3] for i in xrange(0,len(a),3)] 
 
 

49、用过装饰器吗,怎么实现装饰器,function 怎么调用的? 

答: 
a) 用过, 装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较
为经典的有插入日志、性能测试、事务处理等。装饰器是解决这类问题的绝佳设
计,有了装饰器,我们就可以抽离出大量函数中与函数功能本身无关的雷同代码
并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。
b) 举例: 
import time 
def timeit(func): 
    def wrapper(): 
        start = time.clock() 
        func() 
        end =time.clock() 
        print 'used:', end - start 
    return wrapper 
@timeit 
def foo(): 
    print 'in foo()' 
foo() 
利用装饰器 functools.wraps(func),返回装饰器里真的函数名 
import time 
import functools   
def timeit(func): 
    @functools.wraps(func) 
    def wrapper(): 
        start = time.clock() 
        func() 
        end =time.clock() 
        print 'used:', end - start 
    return wrapper 
@timeit 
def foo(): 
    print 'in foo()' 
foo() 
print foo.__name__ 
首先注意第 5 行,如果注释这一行,foo.__name__将是'wrapper'。另外相信你也
注意到了,这个装饰器竟然带有一个参数。实际上,他还有另外两个可选的参数,
assigned 中的属性名将使用赋值的方式替换,而 updated 中的属性名将使用
update 的方式合并,你可以通过查看 functools 的源代码获得它们的默认值。对
于这个装饰器,相当于 wrapper = functools.wraps(func)(wrapper) 
 
 

50、在 Python 中,类和对象有什么区别?对象如何访问类的方法?类(不是对象)在创建时做了什么? 

答:a) python 里一切都是对象,实例是对象,类是对象,元类也是对象.  
i. 类是对象的模板或蓝图,类是对象的抽象化,对象是类的实例化。类不代表
具体的事物,而对象表示具体的事物。 
ii. 类本身也是一个对象,通过使用关键字class创建类时,Python解析器会自动创
建一个对象(对象名为类名),自身拥有创建对象(类实例)的能力,但是本质仍是一个
对象可以做如下操作 
1. 你可以将它赋值给一个变量 
2. 你可以拷贝它 
3. 你可以为它增加属性 
4. 你可以将它作为函数参数进行传递 
5. 运行时动态创建类,也可以通过 type(“testobj”,(object,),{})手动创建 
b) 类(class)是抽象的模板, 在 python 中,一个对象的特征也称为属性
(attribute)。它所具有的行为也称为方法(method)结论:对象=属性+方法 
c) 实例(instance)是是根据类创建出来的一个个具体的”对象”,每个对象都有相
同的方法,但数据不同 
d) 对象可以在创建类时,通过定义构造函数__init__()方法来进行初始化,实例化
对象时进行传参. 
e) 元类是类的类,可以称为类工厂, type 就是 Python 的内建元类,元类可以创建
类(对象),type,str,int,都是元类可以通过__class__查看,所有元类都是从一个类创建
而来,就是 type.通过 int.__class__.__class__查看结果<type ‘type’> 
f) 对象可以通过实例化类,然后直接用.的方式调用类方法 
 

51、python sentry 实时日志 

答:Sentry 是一个实时的事件日志和聚合平台,基于 Django 构建,其专注于
错误监控以及提取一切事后处理所需信息而不依赖于麻烦的用户反馈。 
Sentry 可以帮助你将 Python 程序的所有 exception 自动记录下来,然后在一
个好用的 UI 上呈现和搜索。处理 exception 是每个程序的必要部分,所以 
Sentry 也几乎可以说是所有项目的必备组件 
无论测试如何完善的程序,bug 总是免不了会存在的,有些 bug 不是每次都会
出现,测试时运行好好的代码可能在某个用户使用时就歇菜了,可是当程序在用
户面前崩溃时,你是看不到错误的,当然你会说:”Hey, 我有记日志呢”。 但是说
实话,程序每天每时都在产生大量的日志,而且分布在各个服务器上,并且如果
你有多个服务在维护的话,日志的数量之多你是看不过来的吧。等到某天某个用
户实在受不了了,打电话来咆哮的时候,你再去找日志你又会发现日志其实没什
么用:缺少上下文,不知道用户什么操作导致的异常,异常太多(从不看日志的
缘故)不知如何下手 等等。 
       Sentry 就是来帮我们解决这个问题的,它是一款精致的 Django 应用,目
的在于帮助开发人员从散落在多个不同服务器上毫无头绪的日志文件里发掘活
跃的异常,继而找到潜在的臭虫。 
       Sentry 是一个日志平台, 它分为客户端和服务端,客户端(目前客户端有
Python, PHP,C#, Ruby 等多种语言)就嵌入在你的应用程序中间,程序出现异常就
向服务端发送消息,服务端将消息记录到数据库中并提供一个 web 节目方便查
看。Sentry 由 python 编写,源码开放,性能卓越,易于扩展,目前著名的用户
有 Disqus, Path, mozilla, Pinterest 等 
 
 

52、说明 os,sys 不同,并举例常用的模块用法? 

答:os 与 sys 模块的不同的官方解释: 
os: This module provides a portable way of using operating system dependent 
functionality.  
提供一种方便的使用操作系统函数的方法。 
sys:This module provides access to some variables used or maintained by the 
interpreter and to functions that interact strongly with the interpreter. 
翻译:提供访问由解释器使用或维护的变量和在与解释器交互使用到的函数。 
os 常用方法 
os.remove()删除文件   
os.rename()重命名文件   
os.walk()生成目录树下的所有文件名   
os.chdir()改变目录   
os.mkdir/makedirs 创建目录/多层目录   
os.rmdir/removedirs 删除目录/多层目录   
os.listdir()列出指定目录的文件   
os.getcwd()取得当前工作目录   
os.chmod()改变目录权限   
os.path.basename()去掉目录路径,返回文件名   
os.path.dirname()去掉文件名,返回目录路径   
os.path.join()将分离的各部分组合成一个路径名   
os.path.split()返回(dirname(),basename())元组   
os.path.splitext()(返回 filename,extension)元组   
os.path.getatime\ctime\mtime 分别返回最近访问、创建、修改时间   
os.path.getsize()返回文件大小   
os.path.exists()是否存在   
os.path.isabs()是否为绝对路径   
os.path.isdir()是否为目录   
os.path.isfile()是否为文件   
sys 常用方法 
sys.argv           命令行参数 List,第一个元素是程序本身路径     
sys.modules.keys() 返回所有已经导入的模块列表     
sys.exc_info()     获取 当 前 正 在 处 理的 异 常 类 ,exc_type 、 exc_value、
exc_traceback 当前处理的异常详细信息     
sys.exit(n)        退出程序,正常退出时 exit(0)     
sys.hexversion     获取 Python 解释程序的版本值,16 进制格式如:0x020403F0     
sys.version        获取 Python 解释程序的版本信息     
sys.maxint         最大的 Int 值     
sys.maxunicode     最大的 Unicode 值     
sys.modules        返回系统导入的模块字段,key 是模块名,value 是模块     
sys.path           返回模块的搜索路径,初始化时使用 PYTHONPATH 环境变
量的值     
sys.platform       返回操作系统平台名称     
sys.stdout         标准输出    
sys.stdin          标准输入    
sys.stderr         错误输出    
sys.exc_clear()    用来清除当前线程所出现的当前的或最近的错误信息    
sys.exec_prefix    返回平台独立的 python 文件安装的位置    
sys.byteorder      本 地字节 规则的指 示器, big-endian 平台的值 是
'big',little-endian 平台的值是'little'    
sys.copyright      记录 python 版权相关的东西    
sys.api_version    解释器的 C 的 API 版本    
sys.version_info     
因此,sys 模块区别于 os 模块,sys 模块提供了一系列的函数和变量,用于操控
python 的运行时环境, 而 os 提供了访问操作系统底层的接口. 
 

53、deepcopy 和 copy 的区别? 

答: 
copy.copy 浅拷贝 只拷贝父对象,不会拷贝对象的内部的子对象。 
2. copy.deepcopy 深拷贝 拷贝对象及其子对象 
一个很好的例子: 
import copy 
a = [1, 2, 3, 4, ['a', 'b']]  #原始对象 
 
b = a  #赋值,传对象的引用 
c = copy.copy(a)  #对象拷贝,浅拷贝 
d = copy.deepcopy(a)  #对象拷贝,深拷贝 
 
a.append(5)  #修改对象 a 
a[4].append('c')  #修改对象 a 中的['a', 'b']数组对象 
 
print 'a = ', a 
print 'b = ', b 
print 'c = ', c 
print 'd = ', d 
 
输出结果: 
a =  [1, 2, 3, 4, ['a', 'b', 'c'], 5] 
b =  [1, 2, 3, 4, ['a', 'b', 'c'], 5] 
c =  [1, 2, 3, 4, ['a', 'b', 'c']] 
d =  [1, 2, 3, 4, ['a', 'b']] 

 
54、python、cython、pypy 的联系与区别? 

答:就算是使用了 numpy 等包,再做了大量的代码优化工作,python 的运算速
度仍然没法令人满意。这样看来,python 要摆脱“开发快、运行慢”这种身份还得
依靠 Cython、Numba 和 Pypy,还有 llvmpy、pyston、PyCUDA 等等编译阶段的
优化工具。那么从多快省(通用性、速度、易用性)多角度出发,这些解决方案
中谁才是最优秀的? 
比较而言,Cython 更麻烦一点,因为你要用一种混合语言来改写 
PyPy,不修改就可以直接跑程序,而且提速很大。我在现在的项目中用了 PyPy,
RAM-Heavy 的程序,是 CPython 的数十倍。然后我用 Rust 重写了一下(速
度类似 Go,也接近 C++ 了),速度竟然只快了一倍……(当然现在加上多线程
和黑科技优化以后,速度比 Python 版本快了上百倍了) 
Cython: 一个 Python 的超集,能够调用 C 语言的函数 
a) 目标: 允许你为你的Python代码写C扩展 b) 允许你为你的Python代码加入
静态类型,运行编译并达到接近 C 语言的性能。 c) 这个跟 PyPy 比较类似,但
是不是一样的。使用这个的时候,在提交给编译器之前必须用户代码里面写好 d) 
这些特殊代码。如果使用 PyPy 的话,你写的还是普通形式的 Python 代码,编译
器会帮你处理一切优化的工作。 
Numba: 将 JIT 加入到被注解的 Python 代码中,简单来讲就是,你给它一些提示,
它就会优化加速你这段代码。 
Numba 是 Anaconda 发行版(一系列数据分析和管理的软件包)的一部分。 
IPython: 跟我们讨论过的其他版本完全不一样。这是一个 Python 的计算环境。
为一些 GUI 工具集和浏览器体验等提供支持 
JIT 编译器,英文写作 Just-In-Time Compiler,中文意思是即时编译器 例如, 被
JIT(及时编译)采用的通用方法: 
标识被经常执行的字节码。 
把其编译成本地的机器码。 
缓存该结果。 
当同样的的字节码再次被执行的时候,会取预编译的机器码,得到好处(例如速
度提升)。 
这是关于 PyPy 的用处: 把 JIT 代入 Python 语言 (参看前面成果的附录).当然也有
其他目的: PyPy 目标是成为一个 
 

55、有没有用过 with statement,有什么好处? 

答:用来代替传统的 try...finally 语法的。 
class Sample: 
    def __enter__(self): 
        print "In __enter__()" 
        return "Foo" 
 
    def __exit__(self, type, value, trace): 
        print "In __exit__()" 
 
def get_sample(): 
    return Sample() 
 
with get_sample() as sample: 
    print "sample:", sample 
file = open("/tmp/foo.txt") 
try: 
    data = file.read() 
finally: 
    file.close() 
 
with open("/tmp/foo.txt") as file: 
    data = file.read() 
enter()方法被执行 
enter()方法返回的值 - 这个例子中是"Foo",赋值给变量'sample' 
执行代码块,打印变量"sample"的值为 "Foo" 
exit()方法被调用 with 真正强大之处是它可以处理异常。可能你已经注意到
Sample 类的 exit 方法有三个参数- val, type 和 trace。这些参数在异常处理中相
当有用。 
 

56、Python 中的可变数据类型和不可变数据类型 

答:不可变类型:string,integer,tuple 
>>> var1 = 1 
>>> var2 = var1 
>>> var1,var2 
(1, 1) 
>>> id(var1),id(var2) #同指同一内存区域,id 相同 
(21200672, 21200672) 
>>> var1 += 1 
>>> var1,var2 
(2, 1) 
>>> id(var1),id(var2)#由于 var1,var2 数据不可变的,对 var1+1 后,申请另外一
块区域,id(var1)变了,id(var2)不变,对此区域 ref 数字-1 
(21200660, 21200672) 
>>> 
可变类型:list,dict 
>>> lst1 = [1,2,3] 
>>> lst2 = lst1 
>>> lst1,lst2 
([1, 2, 3], [1, 2, 3]) 
>>> id(lst1),id(lst2) 
(28497360, 28497360) 
>>> lst1.append(4)#可变类型的,append 后,address 会保持不变 
>>> lst1,lst2 
([1, 2, 3, 4], [1, 2, 3, 4]) 
>>> id(lst1),id(lst2)#lst1,lst2 一直指向同一区域 
(28497360, 28497360) 

猜你喜欢

转载自blog.csdn.net/weixin_42369926/article/details/80875374