常用模块

  1. lambda
  2. sysmathrandomdate timeJSON
  3. len()
  4. split()
  5. re

Q35、当Python退出时,为什么不清除所有分配的内存?

  1. Python退出时,尤其是那些对其他对象具有循环引用的Python模块或者从全局名称空间引用的对象并没有被解除分配或释放。
  2. 无法解除分配C库保留的那些内存部分。
  3. 退出时,由于拥有自己的高效清理机制,Python会尝试取消分配/销毁其他所有对象。
  1. Python GC主要使用引用计数(reference counting)来跟踪和回收垃圾。在引用计数的基础上,通过“标记-清除”(mark and sweep)解决容器对象可能产生的循环引用问题,通过“分代回收”(generation collection)以空间换时间的方法提高垃圾回收效率。
  2. 1 引用计数
  3. PyObject是每个对象必有的内容,其中ob_refcnt就是做为引用计数。当一个对象有新的引用时,它的ob_refcnt就会增加,当引用它的对象被删除,它的ob_refcnt就会减少.引用计数为0时,该对象生命就结束了。
  4. 优点:
  5. 简单
  6. 实时性
  7. 缺点:
  8. 维护引用计数消耗资源
  9. 循环引用
  10. 2 标记-清除机制
  11. 基本思路是先按需分配,等到没有空闲内存的时候从寄存器和程序栈上的引用出发,遍历以对象为节点、以引用为边构成的图,把所有可以访问到的对象打上标记,然后清扫一遍内存空间,把所有没标记的对象释放。
  12. 3 分代技术
  13. 分代回收的整体思想是:将系统中的所有内存块根据其存活时间划分为不同的集合,每个集合就成为一个“代”,垃圾收集频率随着“代”的存活时间的增大而减小,存活时间通常利用经过几次垃圾回收来度量。
  14. Python默认定义了三代对象集合,索引数越大,对象存活时间越长。
  15. 举例: 当某些内存块M经过了3次垃圾收集的清洗之后还存活时,我们就将内存块M划到一个集合A中去,而新分配的内存都划分到集合B中去。当垃圾收集开始工作时,大多数情况都只对集合B进行垃圾回收,而对集合A进行垃圾回收要隔相当长一段时间后才进行,这就使得垃圾收集机制需要处理的内存少了,效率自然就提高了。在这个过程中,集合B中的某些内存块由于存活时间长而会被转移到集合A中,当然,集合A中实际上也存在一些垃圾,这些垃圾的回收会因为这种分代的机制而被延迟。

Q49、深拷贝和浅拷贝有什么区别?

  1. 在创建新实例类型时使用浅拷贝,并保留在新实例中复制的值。浅拷贝用于复制引用指针,就像复制值一样。
  2. 这些引用指向原始对象,并且在类的任何成员中所做的更改也将影响它的原始副本。浅拷贝允许更快地执行程序,
  3. 它取决于所使用的数据的大小。
  4. 深拷贝用于存储已复制的值。深拷贝不会将引用指针复制到对象。它引用一个对象,并存储一些其他对象指向的
  5. 新对象。原始副本中所做的更改不会影响使用该对象的任何其他副本。由于为每个被调用的对象创建了某些副本,
  6. 因此深拷贝会使程序的执行速度变慢。

Q50、如何在Python中实现多线程?

  1. Python有一个多线程库,但是用多线程来加速代码的效果并不是那么的好,
  2. Python有一个名为Global Interpreter LockGIL)的结构。GIL确保每次只能执行一个“线程”。
  3. 一个线程获取GIL执行相关操作,然后将GIL传递到下一个线程。
  4. 虽然看起来程序被多线程并行执行,但它们实际上只是轮流使用相同的CPU核心。
  5. 所有这些GIL传递都增加了执行的开销。这意味着多线程并不能让程序运行的更快。

14、列举 Python2和Python3的区别?

  1. 1print
  2. python2中,print被视为一个语句而不是一个函数,python3中,print()被视为一个函数
  3. 2、整数的除法
  4. python2中,键入的任何不带小数的数字,将被视为整数的编程类型。比如5/2=2,解决方法: 5.0/2.0=2.5
  5. python3中,整数除法变得更直观 5/2=2.5
  6. 3Unicode
  7. Python 2 默认使用 ASCII 字母表;Python 3 默认使用 Unicode
  8. 4、后续发展
  9. Python 2.7 将在 2020 年失去后续的支持,
  10. Python 3 将继续开发更多的功能和修复更多的错误。

17、xrange和range的区别?

  1. range 函数说明,range([start,] stop[, step]),根据startstop指定的范围以及step设定的步长,生成一个列表。
  2. xrange:函数说明,xrange 用法与 range 完全相同,所不同的是生成的不是一个list对象,而是一个生成器。
  3. 1rangexrange都是在循环中使用,输出结果一样。
  4. 2range返回的是一个list对象,而xrange返回的是一个生成器对象(xrange object)。
  5. 3xrange则不会直接生成一个list,而是每次调用返回其中的一个值,内存空间使用极少,因而性能非常好。
  6. 注意:Python 3.x已经去掉xrange,全部用range代替。

21、lambda表达式格式以及应用场景?

  1. lambda表达式,通常是在需要一个函数,但是又不想费神去命名一个函数的场合下使用,也就是指匿名函数。
  2. add = lambda x, y : x+y
  3. print(add(1,2)) # 结果为3
  4. 应用在函数式编程中 应用在闭包中

24、is和==的区别

  1. is是对比地址(id),==是对比值

26、Python垃圾回收机制?

  1. PythonGC模块主要运用了“引用计数”(reference counting)来跟踪和回收垃圾。在引用计数的基础上,还可以通过“标记-清除”(mark and sweep)解决容器对象可能产生的循环引用的问题。通过“分代回收”(generation collection)以空间换取时间来进一步提高垃圾回收的效率。

29、列举常见的内置函数?

  1. 简单的内置函数
  2. len 求长度
  3. min 求最小值
  4. max 求最大值
  5. sorted 排序
  6. reversed 反向
  7. sum 求和
  8. 进制转换
  9. bin 转为二进制
  10. oct 转为八进制
  11. hex 转为十六进制
  12. ord 字符转ASCII
  13. chr ASCII码字符
  14. 高级内置函数
  15. enumerate 返回一个可以枚举的对象,常用于生成可迭代的字典
  16. eval 将字符串的内容当成表达式计算
  17. exec 执行print编译过的字符串
  18. filter 过滤器,第一个参数是函数名,第二个参数为可迭代对象,把函数返回True的参数帅选出来并组成一个列表。
  19. map 同样是过滤,与filter不同的是它得到的是函数的返回值。
  20. zip 将两个对象逐一匹配,常用于生成字典

30、filter、map、reduce的作用?

  1. 这里如果用filter的话,说明匿名函数lambda给出的是个筛选条件,从119中筛选出奇数来,但这里如果用map的话,就好像变成了它判断对错的条件,只打印truefalse
  2. reduce这样的累加函数,并不是很常用,在python3中已将其从全局空间移除,现被放置在functools的模块里,用之前需要引入 from functools import reduce

34、re的match和search区别?

  1. re.match()从开头开始匹配string
  2. re.search()从anywhere 来匹配string

35、什么是正则的贪婪匹配?

  1. 贪婪匹配:正则表达式一般趋向于最大长度匹配,也就是所谓的贪婪匹配
  2. 非贪婪匹配:就是匹配到结果就好,就少的匹配字符
  3. 默认是贪婪模式;在量词后面直接加上一个问号?就是非贪婪模式

38、def func(a,b=[]) 这种写法有什么坑?

  1. 因为b是可变参数,每次调用这个方法b不会每次都初始化为[],而是调用相同的[]。

46、请用代码简答实现stack 。

  1. class Stack(object):
  2. def __init__(self,item=[]):
  3. self.item = []
  4. if len(item):
  5. for i in item:
  6. self.item.append(i)
  7. def push(self,item):
  8. self.item.append(item)
  9. def pop(self):
  10. if self.isempty():
  11. rais exception("stack is empty")
  12. else:
  13. data = self.top()
  14. self.item.pop()
  15. return data
  16. def top(self):
  17. return self.item[-1]
  18. def clear(self):
  19. del self.item
  20. def isempty(self):
  21. return item.size() ==0
  22. def size(self):
  23. return len(self.item)
  24. def showList(self):
  25. print(self.item)

48、简述 生成器、迭代器、可迭代对象 以及应用场景?

  1. 迭代器理解
  2. 迭代是Python最强大的功能之一,是访问集合元素的一种方式。
  3. 迭代器是一个可以记住遍历的位置的对象。
  4. 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
  5. 迭代器有两个基本的方法:iter() next()。
  6. 字符串,列表或元组对象都可用于创建迭代器:
  7. 任何实现了__iter____next__()方法的对象都是迭代器。__iter__返回迭代器自身,__next__返回容器中的下一个值
  8. 实现方法:
  9. class iterdemo():
  10. def __init__(self):
  11. self.number=1
  12. #重写 __iter__方法 说明有可以迭代的能力( iterable)
  13. def __iter__(self):
  14. print("__iter__")
  15. return self
  16. #重写 __next__方法 说明是 迭代器 (iterator)
  17. def __next__(self):
  18. print("__next__")
  19. self.number += 1
  20. return self.number
  21. =================================================
  22. 生成器:
  23. 生成器是一种特殊的迭代器,它的返回值不是通过return而是用yield
  24. 生成器算得上是Python语言中最吸引人的特性之一,生成器其实是一种特殊的迭代器,不过这种迭代器更加优雅。它不需要再像上面的类一样写__iter__()和__next__()方法了,只需要一个yiled关键字。 生成器一定是迭代器(反之不成立)
  25. 方式一:
  26. gen =(x+2 for x in range(10))
  27. print(gen)
  28. 方式二:
  29. #每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。
  30. def number():
  31. number=1
  32. print("number=",number)
  33. yield number
  34. number+=1
  35. print("number=", number)
  36. yield number
  37. number += 1
  38. n = number()#调用一个生成器函数,返回的是一个迭代器对象。
  39. print(n)
  40. 结果是: <generator object number at 0x005E4F60>说明是生成器
  41. 如果把yield删除掉
  42. 结果是: number= 1
  43. None
  44. 说明是普通的函数而已
  45. 调用
  46. print(next(n))
  47. print(next(n))
  48. 调用2次的结果是:
  49. number= 1
  50. 1
  51. number= 2
  52. 2
  53. 但是再调用一次
  54. print(next(n))就会有异常StopIteration 没有已经没有迭代项了

49、用Python实现一个二分查找的函数。

  1. def binary_search(lis, num):
  2. left = 0
  3. right = len(lis) - 1
  4. while left <= right: #循环条件
  5. mid = (left + right) / 2 #获取中间位置,数字的索引(序列前提是有序的)
  6. if num < lis[mid]: #如果查询数字比中间数字小,那就去二分后的左边找,
  7. right = mid - 1 #来到左边后,需要将右变的边界换为mid-1
  8. elif num > lis[mid]: #如果查询数字比中间数字大,那么去二分后的右边找
  9. left = mid + 1 #来到右边后,需要将左边的边界换为mid+1
  10. else:
  11. return mid #如果查询数字刚好为中间值,返回该值得索引
  12. return -1 #如果循环结束,左边大于了右边,代表没有找到
  13. lis = [11, 32, 51, 21, 42, 9, 5, 6, 7, 8]
  14. print(lis)
  15. lis.sort()
  16. print(lis)
  17. while 1:
  18. num = int(input('输入要查找的数:'))
  19. res = binary_search(lis, num)
  20. print(res)
  21. if res == -1:
  22. print('未找到!')
  23. else:
  24. print('找到!')
  25. 2.递归算法
  26. def binary_search(lis, left, right, num):
  27. if left > right: #递归结束条件
  28. return -1
  29. mid = (left + right) / 2
  30. if num < lis[mid]:
  31. right = mid -1
  32. elif num > lis[mid]:
  33. left = mid + 1
  34. else:
  35. return mid
  36. return binary_search(lis, left, right, num)
  37. #这里之所以会有return是因为必须要接收值,不然返回None
  38. #回溯到最后一层的时候,如果没有return,那么将会返回None
  39. lis = [11, 32, 51, 21, 42, 9, 5, 6, 7, 8]
  40. print(lis)
  41. lis.sort()
  42. print(lis)
  43. while 1:
  44. num = int(input('输入要查找的数:'))
  45. res = binary_search(lis, 0, len(lis)-1,num)
  46. print(res)
  47. if res == -1:
  48. print('未找到!')
  49. else:
  50. print('找到!')

50、谈谈你对闭包的理解?

  1. 在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了一个闭包。
  2. 一般情况下,在我们认知当中,如果一个函数结束,函数的内部所有东西都会释放掉,还给内存,局部变量都会消失。但是闭包是一种特殊情况,如果外函数在结束的时候发现有自己的临时变量将来会在内部函数中用到,就把这个临时变量绑定给了内部函数,然后自己再结束。
  3. ---------------------
  4. def outer(a):
  5. b = 10
  6. def inner():
  7. print(a+b)
  8. return inner

51、os和sys模块的作用?

  1. os模块负责程序与操作系统的交互,提供了访问操作系统底层的接口;
  2. sys模块负责程序与python解释器的交互,提供了一系列的函数和变量,用于操控python的运行时环境。
  3. 详细:https://blog.csdn.net/qq_38276669/article/details/83687738

52、如何生成一个随机数?

  1. #python中利用random获取一个0到1的随机浮点数
  2. a = random.random()
  3. print(a)
  4. #python中利用random获取一定范围内的(10到20)的随机浮点数
  5. b = random.uniform(10,20)
  6. print(b)
  7. #python利用random获取一定范围内(10到20)的随机整数
  8. c = random.randint(10,20)
  9. print(c)
  10. #python利用random从列表集合中获取一个随机值
  11. list = [5,'hello',9,'xiong_it',3,'Python']
  12. d = random.choice(list)
  13. print(d)

53、如何使用python删除一个文件?

  1. 使用python删除一个文件或文件夹,需要使用os模块。
  2. import os
  3. os.remove(path) # path是文件的路径,如果这个路径是一个文件夹,则会抛出OSError的错误,这时需用用rmdir()来删除
  4. os.rmdir(path) # path是文件夹路径,注意文件夹需要时空的才能被删除
  5. os.unlink('F:\新建文本文档.txt') # unlink的功能和remove一样是删除一个文件,但是删除一个删除一个正在使用的文件会报错。
  6. import os
  7. path = 'F:/新建文本文档.txt' # 文件路径
  8. if os.path.exists(path): # 如果文件存在
  9. # 删除文件,可使用以下两种方法。
  10. os.remove(path)
  11. #os.unlink(path)
  12. else:
  13. print('no such file:%s'%my_file) # 则返回文件不存在
  14. import os
  15. os.removedirs(path) # 递归地删除目录。如果子目录成功被删除,则将会成功删除父目录,子目录没成功删除,将抛异常。
  16. import os
  17. for root, dirs, files in os.walk(top, topdown=False):
  18. for name in files:
  19. os.remove(os.path.join(root, name))
  20. for name in dirs:
  21. os.rmdir(os.path.join(root, name))
  22. 另一种方法
  23. import shutil
  24. shutil.rmtree()

55、Python面向对象中的继承有什么特点?

  1. 1:在继承中基类的构造(__init__()方法)不会被自动调用,它需要在其派生类的构造中亲自专门调用。
  2. 2:在调用基类的方法时,需要加上基类的类名前缀,且需要带上self参数变量。区别于在类中调用普通函数时并不需要带上self参数
  3. 3Python总是首先查找对应类型的方法,如果它不能在派生类中找到对应的方法,它才开始到基类中逐个查找,即先在本类中查找调用的方法,找不到才去基类中找。
  4. 如果在继承元组中列了一个以上的类,那么它就被称作“多重继承”
  5. 私有属性的访问方法:
  6. 例子中的 __money就是私有属性,需要用setget方法进行访问。

56、面向对象深度优先和广度优先是什么?

  1. MRO即方法解析顺序(method resolution order),用于判断子类调用的属性来自于哪个父类。在Python2.3之前,MRO是基于深度优先算法的,自2.3开始使用C3算法,定义类时需要继承object,这样的类称为新式类,否则为旧式类
  2. --------------------------------------------
  3. 经典类采用深度优先搜索
  4. class P1:
  5. def foo(self):
  6. print 'p1-foo'
  7. class P2 :
  8. def foo(self):
  9. print 'p2-foo'
  10. def bar(self):
  11. print 'p2-bar'
  12. class C1 (P1,P2):
  13. pass
  14. class C2 (P1,P2):
  15. def bar(self):
  16. print 'C2-bar'
  17. class D(C1,C2):
  18. pass
  19. d = D()
  20. d.foo() # 输出 p1-foo
  21. d.bar() # 输出 p2-bar
  22. 实例d调用foo()时,搜索顺序是 D => C1 => P1
  23. 实例d调用bar()时,搜索顺序是 D => C1 => P1 => P2
  24. 经典类的搜索方式:从左到右,深度优先
  25. ---------------------------------------
  26. 新式类采用广度优先搜索
  27. class P1(object):
  28. def foo(self):
  29. print 'p1-foo'
  30. class P2(object):
  31. def foo(self):
  32. print 'p2-foo'
  33. def bar(self):
  34. print 'p2-bar'
  35. class C1 (P1,P2):
  36. pass
  37. class C2 (P1,P2):
  38. def bar(self):
  39. print 'C2-bar'
  40. class D(C1,C2):
  41. pass
  42. d=D()
  43. d.foo() # 输出 p1-foo
  44. d.bar() # 输出 c2-bar
  45. 实例d调用foo()时,搜索顺序是 D => C1 => C2 => P1
  46. 实例d调用bar()时,搜索顺序是 D => C1 => C2

57、面向对象中super的作用?

image.png

  1. class Bicycle(object):
  2. def __init__(self, name):
  3. self.name = name
  4. def run(self):
  5. print('我是%s的run方法'%self.name)
  6. class E_Bicycle(Bicycle): # 继承自行车
  7. def __init__(self, name, age):
  8. super().__init__(name) # 调用父类的name属性
  9. self.age = age
  10. def run(self):
  11. super().run() # 调用父类的run方法
  12. print('被主人改装%s年了'%(self.age)
  13. b = Bicycle()
  14. b.run()
  15. e_b = E_Bicycle('电动车', 3)
  16. e_b.run()
  17. ---------------------------------------------------
  18. super() 函数是用于调用父类(超类)的一个方法。
  19. super 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。
  20. MRO 就是类的方法解析顺序表, 其实也就是继承父类方法时的顺序表。
  21. 以下是 super() 方法的语法:
  22. super(type[, object-or-type])
  23. 参数
  24. type -- 类。
  25. object-or-type -- 类,一般是 self
  26. Python3.x Python2.x 的一个区别是: Python 3 可以使用直接使用 super().xxx 代替 super(Class, self).xxx :
  27. ----------------------------------------
  28. super不是一个关键字,也是不是有函数,他是一个类
  29. super()的作用不是查找父类,而是找MRO列表的上一个类
  30. super()和父类没有任何实质性的关系,只是有时候能调用到父类而已。
  31. 在单继承的情况下,super()永远调用的是父类/父对象
  32. super()多用于菱形继承
  33. 格式:
  34. super().方法() #python3的格式

58、是否使用过functools中的函数?其作用是什么?

  1. functools用于高阶函数:指那些作用于函数或者返回其他函数的函数。通常情况下,只要是可以被当做函数调用的对象就是这个模块的目标。
  2. -------------------------------
  3. partial
  4. 首先是partial函数,它可以重新绑定函数的可选参数,生成一个callablepartial对象
  5. update_wrapper
  6. 接着是update_wrapper函数,它可以把被封装函数的__name____module____doc__ __dict__都复制到封装函数去:
  7. wraps
  8. 再有是wraps函数,它将update_wrapper也封装了进来
  9. total_ordering
  10. 最后至于total_ordering函数则给予类丰富的排序方法,使用装饰器简化了操作。如果使用必须在类里面定义一个__lt__(),__le__(), __gt__(), __ge__()。应该给类添加一个__eq__() 方法。

59、列举面向对象中带爽下划线的特殊方法,如:new、init

  1. 类的特殊成员方法
  2. __doc__ :打印类的描述信息
  3. __init__初始化魔术对象,当一个对象被实例化是自动触发
  4. __new__ 当一个对象被实例化前自动触发,通过传递参数判断对象是否被创建或其他
  5. __del__当一个对象没有任何引用是被触发,回收内存
  6. __call__将对象当作函数调用时触发
  7. __module__:表示当前操作的对象在那个模块
  8. __class__:表示当前操作的对象的类是什么
  9. __str__:如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值

60、如何判断是函数还是方法?

通过类方法调用为函数,通过实例化对象调用为方法

  1. 什么是函数?什么是方法?
  2. def func():
  3. pass
  4. class Foo(object):
  5. def func(self):
  6. pass
  7. # 执行方式一
  8. # obj = Foo()
  9. # obj.func() # 方法
  10. # 执行方式二
  11. # Foo.func(123) # 函数
  12. from types import FunctionType,MethodType
  13. # obj = Foo()
  14. # print(isinstance(obj.func,FunctionType)) # False
  15. # print(isinstance(obj.func,MethodType)) # True
  16. print(isinstance(Foo.func,FunctionType)) # True
  17. print(isinstance(Foo.func,MethodType)) # False

61、静态方法和类方法区别?

  1. 实例方法,类方法,静态方法都可以通过实例或者类调用,只不过实例方法通过类调用时需要传递实例的引用(python 3可以传递任意对象,其他版本会报错)。
  2. 三种方法从不同层次上来对方法进行了描述:实例方法针对的是实例,类方法针对的是类,他们都可以继承和重新定义,而静态方法则不能继承,可以认为是全局函数。

62、列举面向对象中的特殊成员以及应用场景

  1. 魔术方法 用于在某一时刻调用时
  2. `__str__`魔术方法:
  3. 1. 在打印某个对象的时候,会调用这个对象的`__str__`方法,打印这个方法的返回值。
  4. 2. 如果在使用`str(obj)`这个函数的时候,也会调用`__str__`方法。
  5. `__repr__`魔术方法:
  6. 1. `__repr__`魔术方法是用来表述某个对象在内存中的展示形式。
  7. 2. 如果在终端直接输入一个对象,然后按回车,那么将会执行这个对象的`__repr__`方法。
  8. 3. 如果你将几个对象扔到一个容器中(比如:列表),那么你在打印这个容器的时候,会依次调用这个容器中的元素的`__repr__`方法。如果没有实现这个`__repr__`方法,那么得到的将是一个`类名+地址`的形式,这种形式的是不好理解的。
  9. `__dict__`魔术属性:
  10. 1. 用来获取用户自定义的属性,以及这个属性对应的值。返回的是一个字典。
  11. 2. 和`dir`函数做一个区分。`dir`函数返回的是这个对象上拥有的所有属性,包括`Python`内置的属性和用户自己添加的,并且只是获取属性名字,不会获取这个属性对应的值。

64、什么是反射?以及应用场景?

  1. 反射就是通过字符串的形式,导入模块;通过字符串的形式,去模块寻找指定函数,并执行。利用字符串的形式去对象(模块)中操作(查找/获取/删除/添加)成员,一种基于字符串的事件驱动!
  2. 1. getattr()函数是Python自省的核心函数,具体使用大体如下:
  3. class A:
  4. def __init__(self):
  5. self.name = 'twiss'
  6. #self.age='24'
  7. def method(self):
  8. print"method print"
  9. Instance = A()
  10. print getattr(Instance , 'name, 'not find') #如果Instance 对象中有属性
  11. name则打印self.name的值,否则打印'not find'
  12. print getattr(Instance , 'age', 'not find') #如果Instance 对象中有属性
  13. age则打印self.age的值,否则打印'not find'
  14. print getattr(a, 'method', 'default') #如果有方法method,否则打印其地址,
  15. 否则打印default
  16. print getattr(a, 'method', 'default')() #如果有方法method,运行函数并
  17. 打印None否则打印default
  18. 2. hasattr(object, name)
  19. 说明:判断对象object是否包含名为name的特性(hasattr是通过调用getattr(ojbect, name)
  20. 是否抛出异常来实现的)
  21. 3. setattr(object, name, value)
  22. 这是相对应的getattr()。参数是一个对象,一个字符串和一个任意值。字符串可能
  23. 会列出一个现有的属性或一个新的属性。这个函数将值赋给属性的。该对象允许它提供
  24. 。例如,setattr(x,“foobar”,123)相当于x.foobar = 123。
  25. 4. delattr(object, name)
  26. 与setattr()相关的一组函数。参数是由一个对象(记住python中一切皆是对象)和一
  27. 个字符串组成的。string参数必须是对象属性名之一。该函数删除该obj的一个由string
  28. 指定的属性。delattr(x, 'foobar')=del x.foobar

67、metaclass作用?以及应用场景?

  1. 元类就是创建类这种对象的东西
  2. python在执行带class语句的时候,会初始化一个类对象放在内存里面。例如这里会初始化一个Trick对象
  3. 这个对象(类)自身拥有创建对象(通常我们说的实例,但是在python中还是对象)的能力。
  4. 1.类由type创建,创建类时,type__init__方法自动执行,类() 执行type __call__方法(类的__new__方法,类的__init__方法)
  5. 2.对象由类创建,创建对象时,类的__init__方法自动执行,对象()执行类的 __call__ 方法

68、用尽量多的方法实现单例模式。

  1. 单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。
  2. 比如,某个服务器程序的配置信息存放在一个文件中,客户端通过一个 AppConfig 的类来读取配置文件的信息。如果在程序运行期间,有很多地方都需要使用配置文件的内容,也就是说,很多地方都需要创建 AppConfig 对象的实例,这就导致系统中存在多个 AppConfig 的实例对象,而这样会严重浪费内存资源,尤其是在配置文件内容很多的情况下。事实上,类似 AppConfig 这样的类,我们希望在程序运行期间只存在一个实例对象。
  3. 实现单例模式的几种方式
  4. 使用模块
  5. 其实,Python 的模块就是天然的单例模式,因为模块在第一次导入时,会生成 .pyc 文件,当第二次导入时,就会直接加载 .pyc 文件,而不会再次执行模块代码。因此,我们只需把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了。如果我们真的想要一个单例类,可以考虑这样做
  6. class Singleton(object):
  7. def foo(self):
  8. pass
  9. singleton = Singleton()
  10. 将上面的代码保存在文件 mysingleton.py 中,要使用时,直接在其他文件中导入此文件中的对象,这个对象即是单例模式的对象
  11. from a import singleton

69、装饰器的写法以及应用场景。

  1. 装饰器是一个工厂函数,接受一个函数作为参数,然后返回一个新函数,
  2. 其闭包中包含被装饰的函数。有了装饰器,
  3. 可以提取大量函数中与本身功能无关的类似代码 ( 这块在Flask中用于定义路由的@app.route,就是一个很好的例子),达到代码重用的目的。
  4. 可应用于插入日志、性能测试、事务处理等方面。
  5. ---------------------
  6. def deco(func):
  7. def warpper(*args, **kwargs):
  8. print(‘start‘)
  9. func(*args, **kwargs)
  10. print(‘end‘)
  11. return warpper
  12. @deco
  13. def myfunc(parameter):
  14. print("run with %s" % parameter)
  15. myfunc("something")

71、什么是面向对象的mro

  1. Method Resolution Order 用来制作一个继承关系的列表
  2. MRO列表的制作原则:
  3. 1.子类永远在父类的前面
  4. 2.如果继承了多个父类,那么按照()中的顺序在列表中摆放
  5. 3.如果多个类同时继承了一个父类,孙子类中只会选取第一个父类中的父类的该方法

74、json序列化时,可以处理的数据类型有哪些?如何定制支持datetime类型?

  1. 函数 描述
  2. json.dumps Python 对象编码成 JSON 字符串
  3. json.loads 将已编码的 JSON 字符串解码为 Python 对象
  4. 如果你要处理的是文件而不是字符串,你可以使用 json.dump() json.load() 来编码和解码JSON数据。例如:
  5. # 写入 JSON 数据
  6. with open('data.json', 'w') as f:
  7. json.dump(data, f)
  8. # 读取数据
  9. with open('data.json', 'r') as f:
  10. data = json.load(f)
  1. #字符串、字典、列表、数字、布尔值、None、、自定义class类
  2. import json
  3. import datetime
  4. class MyEncoder(json.JSONEncoder):
  5. def default(self, o): # o是数据类型
  6. if isinstance(o, datetime.datetime)
  7. return o.strftime('%Y-%m-%d')
  8. else:
  9. return super(MyEncoder, self).default(o)

75、json序列化时,默认遇到中文会转换成unicode,如果想要保留中文怎么办?

  1. json.dumps(jsonData,ensure_ascii=False);

76、什么是断言?应用场景?

  1. 在没完善一个程序之前,我们不知道程序在哪里会出错,与其让它在运行最崩溃,不如在出现错误条件时就崩溃,这时候就需要assert断言的帮助
  2. python assert断言是声明其布尔值必须为真的判定,如果发生异常就说明表达示为假。可以理解assert断言语句为raise-if-not,用来测试表示式,其返回值为假,就会触发异常。
  3. 断言条件为真时,代码继续执行,负责抛出异常,这个异常通常不会去捕获他,我们设置一个断言目的就是要求必须实现某个条件。
  4. assert True

77、有用过with statement吗?它的好处是什么?

  1. with语句的作用是通过某种方式简化异常处理
  2. 自动管理文件关闭

78、使用代码实现查看列举目录下的所有文件。

  1. # 1递归方法
  2. def print_directory_contents(sPath):
  3. import os
  4. for sChild in os.listdir(sPath):
  5. sChildPath = os.path.join(sPath,sChild)
  6. if os.path.isdir(sChildPath):
  7. print_directory_contents(sChildPath)
  8. else:
  9. print(sChildPath)
  10. print_directory_contents('./test/')
  11. #2
  12. tapath = './test/'
  13. for i in os.listdir(tapath):
  14. print(i)

79、简述 yield和yield from关键字。

  1. yield 的作用就是把一个函数变成一个生成器, 带有yield的函数不再是一个普通的函数。python解释器会将其视为一个generator
  2. yield:生成器函数关键字
  3. yield from:相当于 for i in obj yield i
  4. def a():
  5. yield 1
  6. def b():
  7. yield from a()