1. 谈谈对C、 C++、 Java、 C#、 PHP、 Python等编程语⾔的认识?

2. 谈谈你了解的python种类以及相关特点?

Cpython
    Python的官方版本,使用C语言实现,使用最为广泛,CPython实现会将源文件(py文件)转换成字节码文件(pyc文件),然后运行在Python虚拟机上。

Jyhton
    Python的Java实现,Jython会将Python代码动态编译成Java字节码,然后在JVM上运行。

IronPython
    Python的C#实现,IronPython将Python代码编译成C#字节码,然后在CLR上运行。(与Jython类似)

PyPy(特殊)
    Python实现的Python,将Python的字节码字节码再编译成机器码。

RubyPython、Brython ...

以上除PyPy之外,其他的Python的对应关系和执行流程如下:

面试pytest问题 pyrhon面试题_机器码

PyPy,在Python的基础上对Python的字节码进一步处理,从而提升执行速度!

面试pytest问题 pyrhon面试题_面试pytest问题_02

3. pep8规范

PEP8 Python 编码规范

一 代码编排
1 缩进。4个空格的缩进(编辑器都可以完成此功能),不使用Tap,更不能混合使用Tap和空格。
2 每行最大长度79,换行可以使用反斜杠,最好使用圆括号。换行点要在操作符的后边敲回车。
3 类和top-level函数定义之间空两行;类中的方法定义之间空一行;函数内逻辑无关段落之间空一行;其他地方尽量不要再空行。

二 文档编排
1 模块内容的顺序:模块说明和docstring—import—globals&constants—其他定义。其中import部分,又按标准、三方和自己编写顺序依次排放,之间空一行。
2 不要在一句import中多个库,比如import os, sys不推荐。
3 如果采用from XX import XX引用库,可以省略‘module.’,都是可能出现命名冲突,这时就要采用import XX。

三 空格的使用
总体原则,避免不必要的空格。
1 各种右括号前不要加空格。
2 逗号、冒号、分号前不要加空格。
3 函数的左括号前不要加空格。如Func(1)。
4 序列的左括号前不要加空格。如list[2]。
5 操作符左右各加一个空格,不要为了对齐增加空格。
6 函数默认参数使用的赋值符左右省略空格。
7 不要将多句语句写在同一行,尽管使用‘;’允许。
8 if/for/while语句中,即使执行语句只有一句,也必须另起一行。

四 注释
总体原则,错误的注释不如没有注释。所以当一段代码发生变化时,第一件事就是要修改注释!
注释必须使用英文,最好是完整的句子,首字母大写,句后要有结束符,结束符后跟两个空格,开始下一句。如果是短语,可以省略结束符。
1 块注释,在一段代码前增加的注释。在‘#’后加一空格。段落之间以只有‘#’的行间隔。比如:

# Description : Module config.
# 
# Input : None
#
# Output : None
2 行注释,在一句代码后加注释。比如:x = x + 1 # Increment x
但是这种方式尽量少使用。
3 避免无谓的注释。

五 文档描述
1 为所有的共有模块、函数、类、方法写docstrings;非共有的没有必要,但是可以写注释(在def的下一行)。
2 如果docstring要换行,参考如下例子,详见PEP 257

"""Return a foobang

Optional plotz says to frobnicate the bizbaz first.

"""
六 命名规范
总体原则,新编代码必须按下面命名风格进行,现有库的编码尽量保持风格。
1 尽量单独使用小写字母‘l’,大写字母‘O’等容易混淆的字母。
2 模块命名尽量短小,使用全部小写的方式,可以使用下划线。
3 包命名尽量短小,使用全部小写的方式,不可以使用下划线。
4 类的命名使用CapWords的方式,模块内部使用的类采用_CapWords的方式。
5 异常命名使用CapWords+Error后缀的方式。
6 全局变量尽量只在模块内有效,类似C语言中的static。实现方法有两种,一是__all__机制;二是前缀一个下划线。
7 函数命名使用全部小写的方式,可以使用下划线。
8 常量命名使用全部大写的方式,可以使用下划线。
9 类的属性(方法和变量)命名使用全部小写的方式,可以使用下划线。
9 类的属性有3种作用域public、non-public和subclass API,可以理解成C++中的public、private、protected,non-public属性前,前缀一条下划线。
11 类的属性若与关键字名字冲突,后缀一下划线,尽量不要使用缩略等其他方式。
12 为避免与子类属性命名冲突,在类的一些属性前,前缀两条下划线。比如:类Foo中声明__a,访问时,只能通过Foo._Foo__a,避免歧义。如果子类也叫Foo,那就无能为力了。
13 类的方法第一个参数必须是self,而静态方法第一个参数必须是cls。

七 编码建议
1 编码中考虑到其他python实现的效率等问题,比如运算符‘+’在CPython(Python)中效率很高,都是Jython中却非常低,所以应该采用.join()的方式。
2 尽可能使用‘is’‘is not’取代‘==’,比如if x is not None 要优于if x。
3 使用基于类的异常,每个模块或包都有自己的异常类,此异常类继承自Exception。
4 异常中不要使用裸露的except,except后跟具体的exceptions。
5 异常中try的代码尽可能少。比如:

try:
value = collection[key]
except KeyError:
return key_not_found(key)
else:
return handle_value(value)
要优于

try:
# Too broad!
return handle_value(collection[key])
except KeyError:
# Will also catch KeyError raised by handle_value()
return key_not_found(key)
6 使用startswith() and endswith()代替切片进行序列前缀或后缀的检查。比如

Yes: if foo.startswith(‘bar’):优于
No: if foo[:3] == ‘bar’:
7 使用isinstance()比较对象的类型。比如
Yes: if isinstance(obj, int): 优于
No: if type(obj) is type(1):
8 判断序列空或不空,有如下规则
Yes: if not seq:
if seq:
优于
No: if len(seq)
if not len(seq)
9 字符串不要以空格收尾。
10 二进制数据判断使用 if boolvalue的方式。

4. 字节码和机器码的关系和区别?

机器码(machine code),学名机器语言指令,有时也被称为原生码(Native Code),是电脑的CPU可直接解读的数据。

字节码是一种中间状态(中间码)的二进制代码(文件)。需要直译器转译后才能成为机器码。

什么是机器码
  机器码
  机器码(machine code),学名机器语言指令,有时也被称为原生码(Native Code),是电脑的CPU可直接解读的数据。

  通常意义上来理解的话,机器码就是计算机可以直接执行,并且执行速度最快的代码。

  用机器语言编写程序,编程人员要首先熟记所用计算机的全部指令代码和代码的涵义。手编程序时,
  程序员得自己处理每条指令和每一数据的存储分配和输入输出,还得记住编程过程中每步所使用的工作单元处在何种状态。这是一件十分繁琐的工作,
  编写程序花费的时间往往是实际运行时间的几十倍或几百倍。而且,编出的程序全是些0和1的指令代码,直观性差,还容易出错。
  现在,除了计算机生产厂家的专业人员外,绝大多数的程序员已经不再去学习机器语言了。

  机器语言是微处理器理解和使用的,用于控制它的操作二进制代码。
  8086到Pentium的机器语言指令长度可以从1字节到13字节。
  尽管机器语言好像是很复杂的,然而它是有规律的。
  存在着多至100000种机器语言的指令。这意味着不能把这些种类全部列出来。
  总结:机器码是电脑CPU直接读取运行的机器指令,运行速度最快,但是非常晦涩难懂,也比较难编写,一般从业人员接触不到。

什么是字节码
  字节码
  字节码(Bytecode)是一种包含执行程序、由一序列 op 代码/数据对 组成的二进制文件。字节码是一种中间码,它比机器码更抽象,需要直译器转译后才能成为机器码的中间代码。

  通常情况下它是已经经过编译,但与特定机器码无关。字节码通常不像源码一样可以让人阅读,而是编码后的数值常量、引用、指令等构成的序列。

  字节码主要为了实现特定软件运行和软件环境、与硬件环境无关。字节码的实现方式是通过编译器和虚拟机器。编译器将源码编译成字节码,
  特定平台上的虚拟机器将字节码转译为可以直接执行的指令。字节码的典型应用为Java bytecode。

  字节码在运行时通过JVM(JAVA虚拟机)做一次转换生成机器指令,因此能够更好的跨平台运行。

  总结:字节码是一种中间状态(中间码)的二进制代码(文件)。需要直译器转译后才能成为机器码。

5. 运算符:

1. 求结果: 2 & 5
2. 求结果: 2 ^ 5
上述两个为位运算符
print(2 & 5)  # 10 & 101 => 000 => 0
#先把两个数换算成二进制的数字,每个位数分别进行相加,如果都为1,则为1,有一个为0,则为零

print(2 ^ 5)  # 10 ^ 101 => 111 => 1*2**0+1*2**1+1*2**2=1+2+4=7

#先把两个数换算成二进制的数字,每个位数分别进行相加,如果一个为0,一个为1,则为1,有一个为0,则为零
3. 求结果: 1 or 3
4. 求结果: 1 and 3
5. 求结果: 0 and 2 and 1
6. 求结果: 0 and 2 or 1
7. 求结果: 0 and 2 or 1 or 4
8. 求结果: 0 or Flase and 1
print(1 or 3)  # 1
print(1 and 3)  # 3
print(0 and 2 and 1)  # 0
print(0 and 2 or 1)  # 1
print(0 and 2 or 1 or 4)  # 1
print(0 or False and 1)  # Flase

6. 三元运算写法和应用场景?

主要用在if语句中来简化代码

7.Python3和Python2的区别?

参考:https:
/
/
www.cnblogs.com
/
kendrick
/
p
/
7478304.html

8. 用一行代码代码实现数值交换:

a = 1
 b = 2

a,b=b,a

9.谈谈Python的深浅拷?以及实现方法和应用场景。

Python采用基于值得内存管理模式,赋值语句的执行过程是:首先把等号右侧标识的表达式计算出来,然后在内存中找一个位置把值存放进去,最后创建变量并指向这个内存地址。Python中的变量并不直接存储值,而是存储了值的内存地址或者引用
简单地说,浅拷贝只拷贝一层(如果有嵌套),深拷贝拷贝所有层。

一层的情况:

import copy
 
# 浅拷贝
 
li1 = [1, 2, 3]
li2 = li1.copy()
li1.append(4)
print(li1, li2)  # [1, 2, 3, 4] [1, 2, 3]
 
# 深拷贝
 
li1 = [1, 2, 3]
li2 = copy.deepcopy(li1)
li1.append(4)
print(li1, li2)  # [1, 2, 3, 4] [1, 2, 3]

多层的情况:

import copy
 
# 浅拷贝
 
li1 = [1, 2, 3,[4,5],6]
li2 = li1.copy()
li1[3].append(7)
print(li1, li2)  # [1, 2, 3, [4, 5, 7], 6] [1, 2, 3, [4, 5, 7], 6]
 
# 深拷贝
 
li1 = [1, 2, 3,[4,5],6]
li2 = copy.deepcopy(li1)
li1[3].append(7)
print(li1, li2)  # [1, 2, 3, [4, 5, 7], 6] [1, 2, 3, [4, 5], 6]

10. python2和python3中的int和long区别?

python3去除了long类型,现在只有一种整型——int,但它的行为就像python2版本的long

11. 布尔值为False的常用值都有那些?

False    None    0   ""    ()    []   {}

12. range和xrange区别

xrange 用法与 range 完全相同,所不同的是生成的不是一个list对象,而是一个生成器。

xrange 和 range 这两个基本上都是在循环的时候用,

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

 

在python2中:

range([start,] stop[, step]),根据start与stop指定的范围以及step设定的步长,生成一个序列

>>> range(5)
[0, 1, 2, 3, 4]
>>> range(1,5)
[1, 2, 3, 4]
>>> range(0,6,2)
[0, 2, 4]

xrange用法与range完全相同,所不同的是生成的不是一个数组,而是一个生成器。

>>> xrange(5)
xrange(5)
>>> list(xrange(5))
[0, 1, 2, 3, 4]
>>> xrange(1,5)
xrange(1, 5)
>>> list(xrange(1,5))
[1, 2, 3, 4]
>>> xrange(0,6,2)
xrange(0, 6, 2)
>>> list(xrange(0,6,2))
[0, 2, 4]

由上面的示例可以知道:要生成很大的数字序列的时候,用xrange会比range性能优很多,因为不需要一上来就开辟一块很大的内存空间,这两个基本上都是在循环的时候用。

在 Python 3 中,range() 是像 xrange() 那样实现,xrange()被抛弃。

13. 字符串、列表、元组、字典每个常用的5个方法?

字符串:index/find/lower/upper/split/strip/replace/isspace/join

s='hello world'
print(s.split(' ')) #分割
print(s.upper())#变大写
print(s.lower())#变小写
print(s.format()) #字符串的拼接
print(s.index('h')) #求所在的索引

列表:extend/append/reverse/insert/pop/remove/sort/clean/count

元组:coutt/index

字典:get/pop/popitem/key/value/update/fromkey

14. lambda表达式格式以及应用场景?

简单来说,编程中提到的 lambda 表达式,通常是在需要一个函数,但是又不想费神去命名一个函数的场合下使用,也就是指匿名函数,lambda是一个表达式。

map(lambda x: x*x, [x for x in range(10)])

#上述结果是一个生成器

这个写法要好过:

def sq(x):
    return x * x
 
map(sq, [y for y in range(10)])

#map函数的结果是一个生成器

因为后者多定义了一个(污染环境的)函数,尤其如果这个函数只会使用一次的话。而且第一种写法实际上更易读,因为那个映射到列表上的函数具体是要做什么,非常一目了然。如果你仔细观察自己的代码,会发现这种场景其实很常见:你在某处就真的只需要一个能做一件事情的函数而已,连它叫什么名字都无关紧要。Lambda 表达式就可以用来做这件事。

15. 求结果

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

结果:

[6,6,6,6]

#这个的原因是 Python 的闭包的后期绑定导致的 late binding,这意味着在闭包中的变量是在内部函数被调用的时候被查找。所以结果是,当任何 num()
 返回的函数被调用,在那时,i 的值是在它被调用时的周围作用域中查找,到那时,无论哪个返回的函数被调用,for 循环都已经完成了,i 最后的值是 3,
因此,每个返回的函数num 的值都是 3。因此一个等于 2 的值被传递进以上代码,它们将返回一个值 6 (比如: 3 x 2)。

16. pass的作用?

pass是空语句,是为了保持程序结构的完整性。pass 不做任何事情,一般用做占位语句。

17. 求结果:

v = dict.fromkeys(['k1', 'k2'], [])
v['k1'].append(666)
print(v)
v['k1'] = 777
print(v)
{'k1': [666], 'k2': [666]}
{'k1': 777, 'k2': [666]}

18. *args和**kwargs作用?

这是一种特殊的语法,*args和**kwargs可以用来传递不确定长度的位置参数和关键字参数

19. is和==的区别

is 是用来判断两个对象是否是同一个对象

==是用来判断两个对象的值是否相等

20. 用一行代码实现9*9乘法表

print('\n'.join('  '.join(['{}*{}={}'.format(i,j,i*j) for i in range(1,j+1)])for j in range(1,10)))

21. 如何安装第三方模块?以及用过哪些第三方模块?

安装方式:

pip install SomePackage[==version]   # 在线安装制定版本
 
pip install SomePackage.whl          # 通过whl文件离线安装扩展库
 
pip install -r requirements.txt      # 安装requirements.txt文件中制定的模块

用过的第三方模块:requests,pymysql,DbUtils,SQLAlchemy等

22. 常用模块都有那些?

os,sys,time,json,time,random

23. re的match和search区别?

re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。

re.search 扫描整个字符串并返回第一个成功的匹配。

24. 什么是正则的贪婪匹配?

贪婪匹配:在满足匹配时,匹配尽可能长的字符串,默认情况下,采用贪婪匹配

非贪婪匹配是在贪婪匹配的基础上在量词的后面加上一个问号即可

例如:

import re

l='abcbcac'
#贪婪匹配
ret=re.search('ab.*c',l).group()
print(ret) #abcbcac
#非贪婪匹配
ret1=re.search('ab.*?c',l).group()
print(ret1)#abc

25. 求结果:

a. [ i % 2 for i in range(10) ]
b. ( i % 2 for i in range(10) )

结果:

[0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
<generator object <genexpr> at 0x000001DCF62E70F8>

26. 求结果:

a. 1 or 2

b. 1 and 2

c. 1 < (2==2)

d. 1 2 == 2

结果:

>>> 1 or 2
1
>>> 1 and 2
2
>>> 1 < (2==2)
False
>>> 1 < 2 == 2
True

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

def func(a, b=[]):
    b.append(a)
    return b
 
 
s = func(1)
print(s)  # [1]
s = func(1)
print(s)  # [1, 1]
 
# 第二次调用的时候 b的初始值是[1]了

#定义函数的时候,如果参数中含有可变数据类型的话,需要注意这个数据的变化

28. 如何实现 “1,2,3” 变成 [‘1’,’2’,’3’]

print("1,2,3".split(','))

29. 如何实现[‘1’,’2’,’3’]变成[1,2,3]

[int(x) for x in ['1','2','3']]

30. 内置函数:map、reduce、filter的用法和区别?

 map:遍历序列,对序列中每个元素进行操作,最终获取新的序列。

每个元素增加100:

li = [11, 22, 33]
new_list = map(lambda a: a + 100, li)

 

filter:对于序列中的元素进行筛选,最终获取符合条件的序列

def is_odd(x):
    return x % 2 == 1


filter(is_odd, [1, 4, 6, 7, 9, 12, 17])

#过滤出其中的偶数,得到的结果也是一个生成器

 

reduce() 函数会对参数序列中元素进行累积。

语法

reduce() 函数语法:

reduce(function, iterable[, initializer])

参数

  • function -- 函数,有两个参数
  • iterable -- 可迭代对象
  • initializer -- 可选,初始参数

返回值

返回函数计算结果

>>>def add(x, y) :            # 两数相加
...     return x + y
... 
>>> reduce(add, [1,2,3,4,5])   # 计算列表和:1+2+3+4+5
15
>>> reduce(lambda x, y: x+y, [1,2,3,4,5])  # 使用 lambda 匿名函数
15

31. 如何用一行代码生成[1,4,9,16,25,36,49,64,81,100]

print([i*i for i in range(1,11)])

32. 用一行代码实现删除列表中重复的值。

print(list(set(['1','1','2','2'])))

33. 如何在函数中设置一个全局变量

#用关键字global
def num():
    global n
    n=10
    return n

print(num())

 34.请用Python代码简答实现stack。

1.栈stack通常的操作:

Stack() 建立一个空的栈对象
push() 把一个元素添加到栈的最顶层
pop() 删除栈最顶层的元素,并返回这个元素
peek()  返回最顶层的元素,并不删除它
isEmpty()  判断栈是否为空
size()  返回栈中元素的个数

这里使用python的list对象模拟栈的实现,具体代码如下:

class Stack:
  """模拟栈"""
  def __init__(self):
    self.items = []
     
  def isEmpty(self):
    return len(self.items)==0
   
  def push(self, item):
    self.items.append(item)
   
  def pop(self):
    return self.items.pop() 
   
  def peek(self):
    if not self.isEmpty():
      return self.items[len(self.items)-1]
     
  def size(self):
    return len(self.items) 
s=Stack()
print(s.isEmpty())
s.push(4)
s.push('dog')
print(s.peek())
s.push(True)
print(s.size())
print(s.isEmpty())
s.push(8.4)
print(s.pop())
print(s.pop())
print(s.size())

35. 常用字符串格式化有哪些?

1.占位符%

2.format

36. 如何理解生成器和迭代器?

生成器:

Python使用生成器对延迟操作提供了支持。所谓延迟操作,是指在需要的时候才产生结果,而不是立即产生结果。这也是生成器的主要好处

生成器本质上还是一个迭代器

迭代器:

面试pytest问题 pyrhon面试题_字节码_03

迭代器是用可迭代对象的通过obj.__iter__()方法得到的结果

1、为何要有迭代器?

对于序列类型:字符串、列表、元组,我们可以使用索引的方式迭代取出其包含的元素。
但对于字典、集合、文件等类型是没有索引的,若还想取出其内部包含的元素,则必须找出一种不依赖于索引的迭代方式,这就是迭代器

37. 用Python实现一个二分查找的函数。

l = [2,3,5,10,15,16,18,22,26,30,32,35,41,42,43,55,56,66,67,69,72,76,82,83,88]

def search(num,l,start=None,end=None):
    start = start if start else 0
    end = end if end else len(l) - 1
    mid = (end - start)//2 + start
    if start > end:
        return None
    elif l[mid] > num :
        return search(num,l,start,mid-1)
    elif l[mid] < num:
        return search(num,l,mid+1,end)
    elif l[mid] == num:
        return mid

38. 求结果:

a = (1)

    print(a)
 #1 a是一个数字
b = (1,)

    print(b ) #(1,) b是一个元组

39. 谈谈你对闭包的理解?

闭包概念:

#内部函数包含对外部作用域而非全局作用域的引用
def counter():
            n=0
            def incr():
                nonlocal n
                x=n
                n+=1
                return x
            return incr

        c=counter()
        print(c())
        print(c())
        print(c())
        print(c.__closure__[0].cell_contents) #查看闭包的元素

闭包的作用:延迟计算

#闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域
#应用领域:延迟计算(原来我们是传参,现在我们是包起来)
    from urllib.request import urlopen

    def index(url):
        def get():
            return urlopen(url).read()
        return get

    baidu=index('http://www.baidu.com')
    print(baidu().decode('utf-8'))

装饰器就是闭包函数的一种应用场景

40. python递归的最大层数是多少?

默认是998,但是可以修改

41. 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版本
总结:
os模块负责程序与操作系统的交互,提供了访问操作系统底层的接口;sys模块负责程序与python解释器的交互,提供了一系列的函数和变量,用于操控python的运行时环境。

42. 谈谈你对面向对象的理解?以及三大特性是如何理解?

面向对象是把万物都看作对象的一种思想,把具有相同属性的对象抽象成一个类。这样的好处是可以让程序结构化和模块化。这种思想主要是用在大型软件的设计上,因为大型软件需要很好的扩展性,而面向对象的特点就是扩展性比较好

(面向对象是以分类的眼光看待世界中事物的一种方式,将有相同特征的事物进行归纳。面向对象的思想主要是针对大型软件设计而提出的,使得软件设计更加灵活,能够很好地支持代码复用和设计复用,代码具有更好地可读性和可扩展性,大大降低了软件开发的难度,面向对象程序设计的一个关键性观念是将数据以及数据的额操作封装在一起,组成一个相互依存、不可分割的整体(对象),不同的对象之间用过消息的机制来通信或者同步。对于相同的对象(instance)进行分类、抽象后,得出共同特征而形成了类(class),面向对象程序设计的关键就是如何合理地定义这些类并且组织多个类之间的关系。)

python中一切皆对象,函数也是对象,类也是对象。

封装,对数据的封装,对对象的封装。

继承,一般用于在一个已有的设计良好的类基础上进行二次开发,通过内置函数super()或者“基类名.方法名()”的方式实现这一目的。

多态:是指基类的同一方法在不同的派生类对象中具有不同的表现和行为。

43. 如何生成一个随机数?

import random
 
print(random.random())          # 用于生成一个0到1的随机符点数: 0 <= n < 1.0
print(random.randint(1, 1000))  # 用于生成一个指定范围内的整数

44. 如何使用python删除一个文件?

#使用os.remove(文件路径)

import os
file = r'D:\test.txt'
if os.path.exists(file):
    os.remove(file)
    print('delete success')
else:
    print('no such file:%s' % file)

45.面向对象深度优先和广度优先是什么?

Python的类可以继承多个类,Python的类如果继承了多个类,那么其寻找方法的方式有两种

当类是经典类时,多继承情况下,会按照深度优先方式查找

当类是新式类时,多继承情况下,会按照广度优先方式查找

简单点说就是:经典类是纵向查找,新式类是横向查找

典类和新式类的区别就是,在声明类的时候,新式类需要加上object关键字。在python3中默认全是新式类

46. 面向对象中super的作用?

用于子类继承父类的方法

#普通继承和super继承是一样的。但是其实它们的内部运行机制不一样,这一点在多重继承时体现得很明显。在super机制里可以保证公共父类仅被执行一次,至于执行的顺序,
是按照mro进行的(E.__mro__)。
注意super继承只能用于新式类,用于经典类时就会报错。
新式类:必须有继承的类,如果没什么想继承的,那就继承object
经典类:没有父类,如果此时调用super就会出现错误:『super() argument 1 must be type, not classobj』

47. 是否使用过functools中的函数?其作用是什么?

用于装饰器中

面试pytest问题 pyrhon面试题_Python_04

面试pytest问题 pyrhon面试题_机器码_05

面试pytest问题 pyrhon面试题_Python_06

import functools
 
 
def deco(func):
    @functools.wraps(func)  # 加在最内层函数正上方
    def wrapper(*args, **kwargs):
        return func(*args, **kwargs)
 
    return wrapper
 
 
@deco
def index():
    '''哈哈哈哈'''
    x = 10
    print('from index')
 
 
print(index.__name__)
print(index.__doc__)
 
# 加@functools.wraps
# index
# 哈哈哈哈
 
# 不加@functools.wraps
# wrapper
# None

示例

48. 如何判断是函数还是方法?

print(isinstance(obj.func, FunctionType))   # False
print(isinstance(obj.func, MethodType))    # True

面试pytest问题 pyrhon面试题_机器码_05

面试pytest问题 pyrhon面试题_Python_06

class Foo(object):
    def __init__(self):
        self.name = 'lcg'
 
    def func(self):
        print(self.name)
 
 
obj = Foo()
print(obj.func)  # <bound method Foo.func of <__main__.Foo object at 0x000001ABC0F15F98>>
 
print(Foo.func)  # <function Foo.func at 0x000001ABC1F45BF8>
 
# ------------------------FunctionType, MethodType------------#
 
 
from types import FunctionType, MethodType
 
obj = Foo()
print(isinstance(obj.func, FunctionType))  # False
print(isinstance(obj.func, MethodType))  # True
 
print(isinstance(Foo.func, FunctionType))  # True
print(isinstance(Foo.func, MethodType))  # False
 
# ------------------------------------------------------------#
obj = Foo()
Foo.func(obj)  # lcg
 
obj = Foo()
obj.func()  # lcg
 
"""
注意:
    方法,无需传入self参数
    函数,必须手动传入self参数
"""

示例

49. 静态方法和类方法区别?

尽管 classmethod 和 staticmethod 非常相似,但在用法上依然有一些明显的区别。classmethod 必须有一个指向类对象的引用作为第一个参数,而 staticmethod 可以没有任何参数。

面试pytest问题 pyrhon面试题_机器码_05

面试pytest问题 pyrhon面试题_Python_06

class Num:
    # 普通方法:能用Num调用而不能用实例化对象调用   
    def one():  
        print ('1')
 
    # 实例方法:能用实例化对象调用而不能用Num调用
    def two(self):
        print ('2')
 
    # 静态方法:能用Num和实例化对象调用
    @staticmethod 
    def three():  
        print ('3')
 
    # 类方法:第一个参数cls长什么样不重要,都是指Num类本身,调用时将Num类作为对象隐式地传入方法   
    @classmethod 
    def go(cls): 
        cls.three() 
 
Num.one()          #1
#Num.two()         #TypeError: two() missing 1 required positional argument: 'self'
Num.three()        #3
Num.go()           #3
 
i=Num()                
#i.one()           #TypeError: one() takes 0 positional arguments but 1 was given         
i.two()            #2      
i.three()          #3
i.go()             #3

示例

50. 列举面向对象中的特殊成员以及应用场景?

__call__

__new__

__init__

__doc__

__class__

__del__

__dict__

__str__

在falsk源码用到......

51. 1、2、3、4、5 能组成多少个互不相同且不重复的三位数?

60个

题意理解:组成后的数值不相同,且组合的三个位数之间数字不重复。

使用python内置的排列组合函数(不放回抽样排列)

product 笛卡尔积  (有放回抽样排列)

permutations 排列  (不放回抽样排列)

combinations 组合,没有重复  (不放回抽样组合)

combinations_with_replacement 组合,有重复  (有放回抽样组合)

import itertools
 
print(len(list(itertools.permutations('12345', 3))))  # 60

52. 什么是反射?以及应用场景?

反射的核心本质就是以字符串的形式去导入个模块,利用字符串的形式去执行函数。

(可以通过发射去找到里面的方法)

Django中的路由系统就是用发射实现的

53. metaclass作用?以及应用场景?

元类(metaclass)就是创建类的东西

可以用来定制类

引用场景:Django的orm

54. 用尽量多的方法实现单例模式。

通过1.import

2.__new__

55. 装饰器的写法以及应用场景。

用来给函数执行前后添加一些功能

面试pytest问题 pyrhon面试题_机器码_05

面试pytest问题 pyrhon面试题_Python_06

import time
def timmer(func):
    def wrapper(*args,**kwargs):
        start_time=time.time()
        res=func(*args,**kwargs)
        stop_time=time.time()
        print('run time is %s' %(stop_time-start_time))
        return res
    return wrapper

@timmer
def foo():
    time.sleep(3)
    print('from foo')
foo()

无参装饰器

面试pytest问题 pyrhon面试题_机器码_05

面试pytest问题 pyrhon面试题_Python_06

def auth(driver='file'):
    def auth2(func):
        def wrapper(*args,**kwargs):
            name=input("user: ")
            pwd=input("pwd: ")

            if driver == 'file':
                if name == 'egon' and pwd == '123':
                    print('login successful')
                    res=func(*args,**kwargs)
                    return res
            elif driver == 'ldap':
                print('ldap')
        return wrapper
    return auth2

@auth(driver='file')
def foo(name):
    print(name)

foo('egon')
复制代码

有参装饰器

无参装饰器在用户登录 认证中常见

有参装饰器在flask的路由系统中见到过

@app.route('/')
def index():
    return 'Hello World!

def route(self, rule, **options):
    def decorator(f):
        endpoint = options.pop("endpoint", f.__name__)
        self.add_url_rule(rule, endpoint, f, **options)
        return f
    return decorator

56. 异常处理写法以及如何主动抛出异常(应用场景)?

try:
    pass
except:
    pass

try:
    fh = open("testfile", "w")
    try:
        fh.write("这是一个测试文件,用于测试异常!!")
    finally:
        print "关闭文件"
        fh.close()
except IOError:
    print "Error: 没有找到文件或读取文件失败"

 

raise主动抛出一个异常

inputValue=input("please input a int data :")
if type(inputValue)!=type(1):
    raise ValueError
else:
    print inputValue

57. 什么是面向对象的mro?

mro就是方法解析顺序。

对于支持继承的编程语言来说,其方法(属性)可能定义在当前类,也可能来自于基类,所以在方法调用时就需要对当前类和基类进行搜索以确定方法所在的位置。而搜索的顺序就是所谓的「方法解析顺序」(Method Resolution Order,或MRO)。对于只支持单继承的语言来说,MRO 一般比较简单;而对于 Python 这种支持多继承的语言来说,MRO 就复杂很多

print(str.__mro__)  # (<class 'str'>, <class 'object'>)

58. isinstance作用以及应用场景?

用于判断一个对象是否是一个类或者其子类的实例。

class A:
    pass
 
 
class b(A):
    pass
 
 
class c(b):
    pass
 
 
bb = b()
 
print(isinstance(bb, A))  # True
print(isinstance(bb, b))  # True
print(isinstance(bb, c))  # False

59. 什么是断言?应用场景?

python assert断言是声明其布尔值必须为真的判定,如果发生异常就说明表达示为假

比如我想测试 a==1。就可以用断言。如果我的猜想错误就会抛出异常,可以用于测试一段表达式是否成立。

>>> a = 1
>>> assert a==1
>>> assert a==2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError

 应用场景:一般就是用于测试,人总会犯错。在不确定一个表达式是否城区的是

60. 写函数,实现功能

Given an array of integers, return indices of the two numbers such that they add up to a specific target.
 
You may assume that each input would have exactly one solution.
 
Example:
 
Given nums = [2, 7, 11, 15], target = 9,
 
Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].

问题是要从列表中找到两个整数,使得两数之和等于目标值,输出该两数的索引。

nums = [2, 7, 11, 15]
target = 9
 
 
def func(nums, target):
    for i in nums:
        for n in nums:
            if i + n == target:
                return [nums.index(i), nums.index(n)]
 
 
print(func(nums, target))  # [0, 1]