最新面试题-python基础篇

目录

1、为什么学习Python?

1
2

语言本身简洁,优美,功能超级强大,跨平台,从桌面应用,web开发,自动化测试运维,爬虫,人工智能,大数据处理都能做

2、通过什么途径学习的Python? 3、Python和Java、PHP、C、C#、C++等其他语言的对比? 4、简述解释型和编译型编程语言

1
2
3

-编译型(需要编译器,相当于用谷歌翻译):编译型语言在程序执行之前,有一个单独的编译过程,将程序翻译成机器语言,以后执行这个程序的时候,就不用再进行翻译了。       编译型语言执行速度快,不依赖语言环境运行,跨平台差,如c,C++执行速度快,调试麻烦
-解释型(需要解释器,相当于同声传译):解释型语言,是在运行的时候将程序翻译成机器语言,所以运行速度相对于编译型语言要慢。          解释型跨平台好,一份代码,到处使用,缺点是执行速度慢,依赖解释器运行,如python,JAVA执行速度慢,调试方便

5、Python解释器种类以及特点?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19

1、CPython 
CPython是使用最广且被的Python解释器。当我们从Python官方网站下载并安装好Python 2.7后,我们就直接获得了一个官方版本的解释器:cPython.这个解释器是用c语言
开发的,所以叫CPython。在命令行下运行python就是启动cPython解释器。

2、IPython
IPython是基于cPython之上的一个交互式解释器,也就是说,Ipython只是在交互方式上有所增强,但是执行Python代码的功能和cPython是完全一样的。好比很多国产浏览器
虽然外观不同,但内核其实都是调用了IE。CPython用>>>作为提示符,而rPython用In[序号]:作为提示符。

3、PyPy 
PyPy是另一个python解释器,它的目标是执行速度。PyPy采用Jr技术,对python代码进行动态编译(注意不是解释),所以可以显著提高Python代码的执行速度。
绝大部分Python代码都可以在PyPy下运行,但是PyPy和CPython有一些是不同的,这就导致相同的Python代码在两种解释器下执行可能会有不同的结果。如果你的代码要放到
PyPy下执行,就需要了解PyPy和cPython的不同点。

4、Jython
Jython是运行在Java平台上的Python解释器,可以直接把Python代码编译成Java字节码执行。

5、IronPython 
IronPython和Jython类似,只不过IronPython是运行在微软.Net平台上的Python解释器,可以直接把Python代码编译成.Net的字节码。

6、位和字节的关系? –8 bit = 1 bytes 7、b、B、KB、MB、GB 的关系? –8bit = 1B , 1024B =1K , 1024KB = 1MB ,1024MB=1GB

8、请至少列举5个 PEP8 规范(越多越好)。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12

-使用apace(空格)来表示缩进,而不要用tab(制表符)
-和语法相关的每一层缩进都要用4个空格来表示
-每行的字符数不应超过79
-对于占据多行的长表达式来说,除了首行之外的其余各行都应该在通常的缩进级别之上再加上4个空格
-文件中函数与类之间应该用两个空行隔开
-在同一个类中,各方法之间应该用一个空行隔开
-函数、变量及属性应该用小写字母来拼写,各单词之间以下划线相连,例如:lowercase_underscore
-类中的实例方法(instance method),应该把首个参数命名为se1f,以表示该对象自身
-类方法(class method)的首个参数,应该命名为c1s,以表示该类自身
-不要通过检测长度的方法(如if len(somelist)--0)来判断somelist是否为]或”等空值,而是应该采用if not
|somelist,它会假定:空值会自动评估为False

9、进制之间的相互转换:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19

#二进制转换成十进制:
v1 = '0b1111011'
print(int(v1,2))      # 123
#十进制转换成二进制:
v2 = 123
print(bin(v2))        # 0b1111011
#八进制转换成十进制:
v3 = '0o36'
print(int(v3, 8))     # 30
#十进制转换成八进制:
v4 = 30
print(oct(v4))         # 0o36
#十六进制转换成十进制:
v5 = '0x12'
print(int(v5, 16))     # 18
#十进制转换成十六进制:
v6 = 18
print(hex(v6))         # 0x12

10、请编写一个函数实现将IP地址转换成一个整数。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

'''
  如 10.3.9.12 转换规则为:
          10            00001010
           3            00000011
           9            00001001
          12            00001100
  再将以上二进制拼接起来计算十进制结果:00001010 00000011 00001001 00001100 = ?
'''

def ip_int_bin():

    inp = input('请输入一个IP地址:').strip()
    l_ip = inp.split('.')  # 将每一位放到列表中
    s_bin = ''
    for i in l_ip:
        i_bin = '0000'+bin(int(i))[2:]
        s_bin += i_bin  # 将每一位变成二进制形式,将四位转换的二进制数进行拼接
    s_int = int(s_bin, 2)   # 将拼接后的二进制转换成十进制数
    return s_int

print(ip_int_bin())

'''
请输入一个IP地址:10.3.9.12
42141964
'''

11求结果:

1
2
3
4
5
6
7
8

v1 = 1 or 3               # 1
v2 = 1 and 3              # 3
v3 = 0 and 2 and 1        # 0
v4 = 0 and 2 or 1         # 1
v5 = 0 and 2 or 1 or 4    # 1
v6 = 0 or False and 1     # False
v7 = 1 < 2 ==2            # True

12、ascii、unicode、utf-8、gbk 区别?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19

ascii
8位一个字节,1个字节表示一个字符.即: 2 ** 8 = 256,所以ASCII码最多只能表示256个字符.

unicode
俗称万国码,把所有的语言统一到一个编码里.解决了ascii码的限制以及乱码的问题.
unicode码一般是用两个字节表示一个字符,特别生僻的用四个字节表示一个字符.

utf-8
新的问题出现了,如果统一成unicode编码,乱码问题从此消失了.但是如果你写的文本基本上都是英文的,
用Unicode编码比ascii编码需要多一倍的存储空间,在存储和传输上十分不方便.
utf-8应用而生,它是一个"可变长的编码方式",如果是英文字符,则采用ascii编码,占用一个字节.
如果是常用汉字,就占用三个字节,如果是生僻的字就占用4~6个字节.

gbk
国内版本,一个中文字符 == 两个字节 英文是一个字节

1,各个编码之间的二进制,是不能互相识别的,会产生乱码。
2,文件的存储,传输,不能是unicode(只能是utf-8 utf-16 gbk gbk2312 aseii等)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

ascii
在计算机内部,所有信息最终都是一个二进制值。每一个二进制位(oit),有0和1两种状态,因此,8个二进制位可以组合出256种状态,这被称为字节(byte)。
上个世纪60年代,美国制定了一套字符编码,对英文字符与二进制之间做了联系,这被称为ASCII码,一直沿用至今。
ASCTI码一共规定了128个字符,比如SPACE是32,A是65,这128个符号只咱用了一个字节的后面七位,最前面的一位统一规定为0。

unicode:
世界上有多种编码方法,同一个二进制数字可以被解释称不同的符号。因此,在打开一个文本文件时候,就必须知道它的编码方式,用错误的编码方式打开,就会出现乱码。
Unicode编码,这是一种所有符号的编码。
Unicode显然是一个巨大的集合,现在的规模可以容纳100多万个符号。每个符号的编码都不一样,比如U+0041表示英语的大写字母A,U+4e25表示汉字严。
在Unicode庞大的字符集的优势下,还存在一个问题,比如一个汉字,“严”的Unicode是十六进制4e25,转成二进制足足有15位,也就是,这个符号需要2个字节,
表示其他字符还存在3个字节或者更多。计算机怎么区别三个字节表示的是同一个符号而不是分开表示三个|呢?如果Unicode统一规定,每个符号用3个字节表示,
但是某些字母显然不需要3个,那么就浪费了空间,文本文件大小超出了很多,这显然是不合理的。直到UTF8字符编码出现了。

utf-8
UTF8的最大特点是,它是一种变长编码,可以使用1-4个字节表示一个符号,根据不同的符号来变化字节长度。
UTF8编码规则只有两条:
1)对于单字节的符号,字节的第一位设为0,后面的7位为这个符号的unicode码。因此,对于英文字母,UTF8编码和ASCIr编码是相同的。
2)对于非单字节(假设字节长度为N)的符号,第一个字节的前位都设为1,第N+1设为0,后面字节的前两位一律设为10,剩下的没有提及的二进制,全部为这个符号的Unicode码。

gbk:
GBk编码是对GB2312的扩展,完全兼容6B2312,采用双字节编码方案,剔出xx7码位,共23940个码位,共收录汉字和图形符号21886个,GBK编码方案于199s年12月15日发布。
它几乎完美支持汉字,因此经常会遇见GBK与unicode的转换。

13、字节码和机器码的区别?

1
2

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

14、列举 Python2和Python3的区别?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

py2
>>>print("hello","world")
(.hel1o',‘world')
#py3
>>>print("hello","world")
hello world 

py2:inputIraw()
py3:input()

1/2的结果
py2:返回0
py3:返回0.5

py2:默认编码ascii
py3:默认编码utf-8

字符串
py2:unicode类型表示字符串序列,str类型表示字节序列
py3:str类型表示字符串序列,byte类型表示字节序列
py2中函数用关键字globa1声明某个变量为全局变量,但是在嵌套函数中,想要给一个变量声明为非局部变量是没法实现的。
py3中,新增了关键字nonloca1,使得非局部变量成为可能

15、用一行代码实现数值交换:

1
2
3
4

a=1
b=2
a,b = b,a

16、Python3和Python2中 int 和 long的区别?

1
2
3

python2:    int() #整型    long()# 长整型
python3:   没有long类型,  只有int类型(这两种类型被整合到一起了)

17、xrange和range的区别?

1
2
3
4
5
6
7

xrange和range的用法相同
不同的是:
    range(5)  # [0,1,2,3,4] 生成的是一个列表
    xrange(5) # xrange(5)  生成的是一个生成器,通过list(xrange(5)) 就能看到结果了
xrange做循环的性能比range好,尤其是返回很大的时候。
注意:现在的python3中将以前的range取消了,而将xrange重新命名成了range!所以我现在看到的range其实本质上还是xrange。

18、文件操作时:xreadlines和readlines的区别?

1
2
3

readlines()是把文件的全部内容读到内存,并解析成一个list,当文件的体积很大的时候,需要占用很多内存;
xreadlines()则直接返回一个iter(file)迭代器,在Python 2.3之后已经不推荐这种表示方法了,直接使用for循环迭代文件对象

19、列举布尔值为False的常见值?

1
2

0, [], (), {}, '',False, None

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

1
2
3
4
5
6
7

'''
lambda表达式,通常是在需要一个函数,但是又不想费神去命名一个函数的场合下使用,也就是指匿名函数。
通常配合一些内置函数使用
'''
add = lambda x, y: x + y
print(add(1,2)) #3

21、pass的作用?

1
2

pass一般用作占位语句,是用来帮正程序结构的完整性,是一个空语句,不做任何事情。

22、*arg和**kwarg作用

1
2
3

*args是位置参数,可传入0或者多个参数,元祖形式。
**kwargs是关键字参数,可传入0或者多个参数,字典形式。

23、is和==的区别

1
2
3

is 比较的是id
== 比较的是值

24、简述Python的深浅拷贝以及应用场景?(*****)

1
2
3
4

copy():浅copy,浅拷贝指仅仅拷贝数据集合的第一层数据
deepcopy():深copy,深拷贝指拷贝数据集合的所有层
所以对于只有一层的数据集合来说深浅拷贝的意义是一样的,比如字符串,数字,还有仅仅一层的字典 列表 元祖等. 对于以上数据深浅拷贝的意义是一样的 因为数据类型中只有一层
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18

-  copy.copy 浅拷贝 只拷贝父对象不会拷贝对象的内部的子对象
-  copy.deepcopy 深拷贝 拷贝对象及其子对象
举例说明
    import copy
    l1 = [1,2,3,4,['a','b']]
    a = l1  #赋值,传对象的引用
    b = copy.copy(l1)  #对象拷贝,浅拷贝
    c = copy.deepcopy(l1) #对象拷贝,深拷贝
    a.append(5)  #修改对象a
    a[4].append('c')  #修改a列表里面列表
    print('a=',a)  #a= [1, 2, 3, 4, ['a', 'b', 'c'], 5]
    print('b=',b)  #b= [1, 2, 3, 4, ['a', 'b', 'c']]
    print('c=',c)  #c= [1, 2, 3, 4, ['a', 'b']]

    明显的可以看出
        浅拷贝只拷贝父对象不会拷贝对象的内部的子对象
        深拷贝拷贝对象及其子对象

25、Python垃圾回收机制?(*****)

1
2
3

Python的GC模块主要运用了“引用计数”(reference counting)来跟踪和回收垃圾。在引用计数的基础上,还可以通过“标记-清除”(mark and sweep)
解决容器对象可能产生的循环引用的问题。通过“分代回收”(generation collection)以空间换取时间来进一步提高垃圾回收的效率。 
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17

垃圾回收机制是自动帮助我们管理内存,清理垃圾的一种工具,python中有以下三种回收机制:
1) 引用计数
当一个对象的引用被创建或者复制时,对象的引用计数加1;
当一个对象的引用被销毁时,对象的引用计数减1;
当对象的引用计数减少为0时,就意味着对象已经没有被任何人使用了,可以将其所占用的内存释放了。
优点:简单、直观         
缺点:维护引用计数需要消耗一定的资源;循环应用时,无法回收。也正是因为这个原因,才需要通过标记-清除和分代收集机制来辅助引用计数机制。

2) 标记-清除
“标记-清除”不改动真实的引用计数,而是将集合中对象的引用计数复制一份副本,改动该对象应用的副本。
对于副本做任何的改动,都不会影响到对象生命周期的维护。

3) 分代回收
将系统中的所有内存块根据其存活时间划分为不同的集合,每一个集合就成为一个“代”,垃圾收集的频率随着“代”的存活时间的增大而减小。
也就是说,活的越长的对象,就越不可能是垃圾,就应该减少对它的垃圾收集频率。
那么如何来衡量这个存活时间:通常是利用几次垃圾收集动作来衡量,如果一个对象经过的垃圾收集次数越多,可以得出:该对象存活时间就越长。

26、Python的可变类型和不可变类型?

1
2
3
4

可变不可变指的是内存中的值是否可以被改变,
不可变类型:内存中的值发生改变,内存地址也发生改变。有数字、字符串、元组
可变类型:内存中的值发生改变,但内存地址不变。主要有列表、字典

27、说一下字典和json的区别

1
2
3

字典是一种数据结构,json是一种数据的表现形式
字典的key值只要是能hash的就行,json必须是字符串

28、求下列输出结果:

1
2
3
4
5
6

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

29、求结果:

1
2
3
4

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

30、列表取值问题

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13

# 长度5
list=['a','b','c','d','e']

# 从索引为10的下标开始取值,一直取到后面所有值,没有不会报错,返回None
print(list[10:])

# print(list[10]) #报错 index out of range

'''
代码将输出[],不会产生IndexError错误。
就像所期望的那样,尝试用超出成员的个数的index来获取某个列表的成员。例如,尝试获取list[10]和之后的成员,会导致IndexError。
'''

31、下面这段代码的输出结果是什么?请解释?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13

def extend_list(val,list1=[]):
    list1.append(val)
    return list1
list1=extend_list(10)
list2=extend_list(123,[])
list3=extend_list('a')
print(f'listl--->{list1}')  # listl--->[10, 'a']
print(f'list2--->{list2}')  # list2--->[123]
print(f'list3--->{list3}')  # list3--->[10, 'a']
'''
新的默认列表只在函数被定义的那一刻创建一次。当extendList被没有指定特定参数list调用时,这组list的值随后将被使用。这是因为带有默认参数的表达式在函数被定义的时候被计算,不是在调用的时候被计算。因此list1和list3是在同一个默认列表上进行操作(计算)的。而list2是在一个分离的列表上进行操作(计算)的。(通过传递一个自有的空列表作为列表参数的数值)。
'''

32、将以下3个函数按照执行效率由高到低排序

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72

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)]

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

'''

import random
import  cProfile
lIn = [random.random() for i in range(100000)]
cProfile.run('f1(lIn)')
cProfile.run('f2(lIn)')
cProfile.run('f3(lIn)')

'''
 7 function calls in 0.058 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    0.056    0.056 01 数据类型.py:169(f1)
        1    0.013    0.013    0.013    0.013 01 数据类型.py:171(<listcomp>)
        1    0.007    0.007    0.007    0.007 01 数据类型.py:172(<listcomp>)
        1    0.002    0.002    0.058    0.058 <string>:1(<module>)
        1    0.000    0.000    0.058    0.058 {built-in method builtins.exec}
        1    0.035    0.035    0.035    0.035 {built-in method builtins.sorted}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}


         7 function calls in 0.043 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    0.040    0.040 01 数据类型.py:174(f2)
        1    0.007    0.007    0.007    0.007 01 数据类型.py:175(<listcomp>)
        1    0.010    0.010    0.010    0.010 01 数据类型.py:177(<listcomp>)
        1    0.003    0.003    0.042    0.042 <string>:1(<module>)
        1    0.000    0.000    0.043    0.043 {built-in method builtins.exec}
        1    0.022    0.022    0.022    0.022 {built-in method builtins.sorted}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}


         7 function calls in 0.132 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    0.125    0.125 01 数据类型.py:179(f3)
        1    0.021    0.021    0.021    0.021 01 数据类型.py:180(<listcomp>)
        1    0.030    0.030    0.030    0.030 01 数据类型.py:182(<listcomp>)
        1    0.007    0.007    0.132    0.132 <string>:1(<module>)
        1    0.000    0.000    0.132    0.132 {built-in method builtins.exec}
        1    0.073    0.073    0.073    0.073 {built-in method builtins.sorted}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
'''

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

'''

数学类型
aba(a):求取绝对值。aba(-1)max(list):求取1ist最大值。max([1,2,3])
min(1ist):求取1ist最小值,min([1,2,3])sum(1ist):求取14st元素的和。sum((1,2,31)>>>6
sorted(list):排序,返回排序后的1iat。
1en(1ist):1ist长度,1en([1,2,3])
divmod{a,b):获取商和余数。divmod(5,2)>>>(2,1)pow(a,b):获取乘方数,pow(2,3)>>>8
round(a,b):获取指定位数的小数。a代表浮点数,b代表要保留的位数。round(3.1415926,2)>>>3.14
range(a[,b]):成一个a到b的数组,左闭右开。range(1,10)>>>[1,2,3,4,5,6,7,8,9]

类型转换
int(str):转换为int型,int("1")>>>1
float(int/str):将int型或字符型转换为浮点型。float("1')>>>1.0
str(int):转换为字符型。str(1)>>>1.
bool(int):转换为布尔类型。stx(0)>>>False str(None)>>>False bytea(str,code):接收一个字符串,与所要编码的格式,返回一个字节流类型,bytes('abc','utf-8]>>>b'abc'bytes(u'爬虫”,’utf-8')>>>
b'VXxe7\×88\xac\xeB\x99\xab'
1ist(iterable):转换为1ist。1ist((1,2,3])>>>[1,2,3]
iter(iterable):返回一个可送代的对象。iter([1,2,3])>>><list iterator object at 0x0000000003813800>
dict(iterable):转换为dict。dtct(t('a',1),('b*,2),('c',3)])>>>('a':1,'b':2,'c':3)
enumerate(iterable):返回一个枚举对象。
tuple(iterable):转换为tuple。tuple([1,2,31)>>>(1,2,3)
set(iterable):转换为aet。set((1,4,2,4,3,51)>>>{1,2,3,4,5 set((1:'a',2:'b',3:'c"))>>>(1,2,3)
hex(int):转换为16进制。hex(1024)>>>10×400oct(int):转换为8进制。oct(1024)>>>‘002000
bin(int):转换为2进制。bin(1024)>>>·0b10000000000
chr(int):转换数字为相应ASCI码字符。chr(65)>>>'A’
ord(atx):转换aASCI字符为相应的数字。ord('A)>>>65

相关操作
eval();执行一个表达式,或字符串作为运算,eval('1+1)>>>2
exec():执行python语句。exec('print("python")]>>>Python filter(func,iterable):通过判断函数fun,筛选符合条件的元素。filter(lambda x:x>3,[1,2,3,4,5,6])>>><filter object at 0x0000000003813828>
map(func,*iterable):将func用于每个iterable对象。map(lambda a,b:a+b,[1,2,3,41,[5,6,7])>>>[6,8,10]
zip(*iterable):将iterable分组合并。返回一个2ip对象。14et(z1p([1,2,3],[4,5,6]))>>>[(1,4),(2,5),(3,6)1
type():返回一个对象的类型。
id():返回一个对象的唯一标识值。
hash(object);返回一个对象的hash值,具有相网值的object具有相同的hash值。hash('python')>>>7070808359261009780
help():调用系统内置的帮助系统。
isinstance():判断一个对象是否为该类的一个实例。
issubclass():判断一个类是否为另一个类的子类。
globals():返回当前全局变量的字典。
next(iterator,default1):接收一个选代器,返回迭代器中的数值,如果设置了default,则当选代器中的元素遍历后,输出default内容。
reversed(sequence):生成一个反转序列的送代器。reversed("abc')>>>'c','b','a']
'''

34、filter、map、reduce的作用?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17

#通过判断函数fun,筛选符合条件的元素。
res = filter(lambda x:x>=2, [0,1,2,3,])
print(res)       # <filter object at 0x03749070>
print(list(res)) # [2, 3]

# map操作其实执行的是一个映射。它可以自动地将一个序列当中的内容通过制定的函数映射成另一个序列,
# 从而避免显式地使用循环来调用,在很多场景下可以大大地简化代码的编写,可以很方便地将一个序列整体转变成另一个结果。
res = map(lambda x: x + 'xxx', ['1','2'])
print(res)        # <map object at 0x036345B0>
print(list(res))  # ['1xxx', '2xxx']

# reduce 它也是规定一个映射,不过不是将一个元素映射成一个结果。而是将两个元素归并成一个结果。
# 并且它并不是调用一次,而是依次调用,直到最后只剩下一个结果为止。
from functools import reduce
res = reduce(lambda x,y: x+y,range(1,100))
print(res)  #4950

35、一行代码实现9*9乘法表?

1
2

print('\n'.join(['\t'.join([f"{i}x{j}={i*j}" for j in range(1,i+1)]) for i in range(1,10) ]))
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

#方式一
for i in range(1,10):
    for j in range(1,i+1):
        print('%s*%s=%s'%(i,j,i*j),end=" ")
    print()
#方式二:左上三角形
for i in range(1,10):
    for j in range(i,10):
        print("%d*%d=%d"%(i,j,i*j),end=" ")
    print("")

'''
1*1=1 
2*1=2 2*2=4 
3*1=3 3*2=6 3*3=9 
4*1=4 4*2=8 4*3=12 4*4=16 
5*1=5 5*2=10 5*3=15 5*4=20 5*5=25 
6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36 
7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49 
8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64 
9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81 

1*1=1  1*2=2  1*3=3  1*4=4  1*5=5  1*6=6  1*7=7  1*8=8  1*9=9 
2*2=4  2*3=6  2*4=8  2*5=10 2*6=12 2*7=14 2*8=16 2*9=18 
3*3=9  3*4=12 3*5=15 3*6=18 3*7=21 3*8=24 3*9=27 
4*4=16 4*5=20 4*6=24 4*7=28 4*8=32 4*9=36 
5*5=25 5*6=30 5*7=35 5*8=40 5*9=45 
6*6=36 6*7=42 6*8=48 6*9=54 
7*7=49 7*8=56 7*9=63 
8*8=64 8*9=72 
9*9=81 
'''

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

1
2
3

pip3 install 模块名称
beautifulsoup\Pillow\celery\django_redis\alipay\itsdangerous

37、至少列举8个常用模块都有那些?

1
2

time;re;os;sys;datetime;hashlib;json;random; math; request

38、re的match和search区别?

1
2

re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。

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

1
2

正则表达式一般趋向于最大长度匹配,也就是所谓的贪婪匹配。

40、求结果: a. [ i % 2 for i in range(10) ] b. ( i % 2 for i in range(10) )

 1
 2
 3
 4
 5
 6
 7
 8
 9
10

print([i % 2 for i in range(10)])
print((i % 2 for i in range(10))) # 生成器,帮我们节省内存,可以循环取值
print(list(i % 2 for i in range(10))) # 生成器,帮我们节省内存,可以循环取值

'''
[0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
<generator object <genexpr> at 0x01143FB0>
[0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
'''

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17

def func(a,b = []):
    b.append(1)
    print(a,b)

func(2)
func(2)
func(2)

'''
    2 [1]
    2 [1, 1]
    2 [1, 1, 1]
    函数的默认参数是一个list 当第一次执行的时候实例化了一个list 
    第二次执行还是用第一次执行的时候实例化的地址存储 
    所以三次执行的结果就是 [1, 1, 1] 想每次执行只输出[1] ,默认参数应该设置为None
'''

42、如何实现 “1,2,3” 变成 [‘1’,’2’,’3’] ?

1
2
3
4

a = "1,2,3"
li = a.split(',')   # split返回分割后的字符串列表
print(li)  #['1', '2', '3']

43、如何实现[‘1’,’2’,’3’]变成[1,2,3] ?

1
2
3
4

li = ['1','2','3']
lis = list(map(lambda x:int(x),li))
print(lis)   # [1, 2, 3]

44、比较: a = [1,2,3] 和 b = [(1),(2),(3) ] 以及 c = [(1,),(2,),(3,) ] 的区别?

1
2
3
4

a = [1,2,3]正常的列表
b = [(1),(2),(3)] 虽然列表的每个元素加上了括号,但是当括号内只有一个元素并且没有逗号时,其数据类型是元素本身的数据类型
c = [(1,),(2,),(3,)]列表中的元素类型都是元组类型

45、如何用一行代码生成[1,4,9,16,25,36,49,64,81,100] ? 写一个列表生成式,产生一个公差为11的等差数列?(*****)

1
2
3
4
5
6
7
8

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

'''
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
[0, 11, 22, 33, 44, 55, 66, 77, 88, 99]
'''

46、现有字典dict={‘a’:24,‘g’:52,‘i’:12,‘k’:33}请按字典中的value值进行排序?(*****)

1
2

print(sorted(dict.items(),key = lambda x:x[1]))

47、存入字典里的数据有没有先后排序?

1
2

存入的数据不会自动排序,可以使用sort函数对字典进行排序

48、字典推导式?

1
2

dict = {key:value for {key,value} in iterable}

49、dict的items()方法与iteritems()的不同

1
2
3

items方法作用:把字典中每对 key 和 value 组成一个元组,并把这些元组放在列表中返回。因为字典是无序的,所以用items方法返回的字典的所有项也是没有顺序的。
iteritems方法作用:与items方法大致相同,只是它的返回值不是列表,而是一个迭代器。

在python2.x中,iteritems()用于返回本身字典列表操作后的送代器[Returns an iterator on all items(key/value pairs)】,不占用颤外的内。 在Python 3.x里面,iteritems()方法已经废除了。在3.x里用items()替换iteritemas(),可以用于for 来循环遍历。

50、请按list1中元素的age由大到小排序(*****)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10

list1=[
    {'name':'a','age':20},
    {'name':'b','age':30},
    {'name':'c','age':25}
]
# 参数1:迭代器对象
# 参数2:key=匿名函数
# 参数3: reverse=True -->倒序,False-->升序 , 默认升序
sorted(list1,key=lambda x:x['age'],reverse=True)

51、请反转字符串“aStr”?

1
2

print("aStr"[::-1])

52、给定两个列表,怎么找出他们相同的元素和不同的元素?

1
2
3
4
5
6
7
8
9

list1=[1,2,3]
list2=[3,4,5]
set1=set(list1)
set2=set(list2)
print(set1&set2)           # {3}
print(list(set1&set2))     # [3]
print(set1^set2)           # {1, 2, 4, 5}
print(list(set1^set2))     # [1, 2, 4, 5]

53、一行Python代码实现删除list中重复的元素 ?

1
2
3
4
5
6
7
8

l1 = ['b','c','d','b','c','a','a']
# 1)通过内置方法set实现
l2 = list(set(l1))      # set 天然去重
print(l2)               #['d', 'c', 'b', 'a']

l2.sort(key=l1.index)   # 去重后保留原来顺序
print(l2)               #['b', 'c', 'd', 'a']

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

1
2
3
4
5

字符串:split, reverse, upper, lower, join, replace, strip...
列表:append, pop, remove, count, index, insert, sort...
元组:index, count, len, dir, cmp
字典:get , keys, values, pop, clear, update, items, popitems

55、如何打乱一个排好序的list对象?

1
2
3
4
5

import random
alist = [1,2,3,4,5]
random.shuffle(alist)
print(alist) #[3, 5, 2, 4, 1]

56、从0-99这100个数中随机抽出10个,要求不能重复,可以设计数据结构(*****)

sample(list, k)返回一个长度为k新列表,新列表存放list所产生k个随机唯一的元素

1
2
3
4
5
6
7
8

import random
print(random.sample(range(0,99),10))
1 )random().randint() 返回0<=n<1之间的随机实数n
2 )choice(seq) 从序列seq中返回随机的元素
3 )getrandbits(n) 以长整型形式返回n个随机位
4 )shuffle(seq[, random]) 原地指定seq序列
5 )sample(seq, n) 从序列seq中选择n个随机且独立的元素

57、如何在函数中设置一个全局变量 ?

1
2

使用python的内置语法 globals 全局变量

58、logging模块的作用?以及应用场景?

1
2
3
4
5
6

logging模块的作用:
1、程序调试
2、了解软件程序运行情况,是否正常
3、软件程序运行故障分析与问题定位
应用场景:网站的运维工作,程序实时监控

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# Stack():创建一个新的空栈
class Stack():
    def __init__(self):
        self.items = []

    # 判断栈是否为空
    def is_empty(self):
        return self.items == []

    # 添加一个新的元素,item到栈顶
    def push(self, item):
        self.items.append(item)

    # 弹出栈顶元素
    def pop(self):
        return self.items.pop()

    # 返回栈顶元素
    def peek(self):
        return self.items[len(self.items) - 1]

    # 返回栈的元素个数
    def size(self):
        return len(self.items)

60、常用字符串格式化哪几种?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11

name = '张三’

1)占位符,%s,%d
s1="%s 你好"%name

2)format 
s2='{}你好’.format(name)

3)f-string(python3.6之后才有的特性)
s3=f'{name}你好’

61、请简述字符串驻留机制

1
2
3

对于短字符串,将其赋值给多个不同的对象时,内存中只有一个副本,多个对象共享该副本。长字符串不遵守驻留机制。
驻留适用范围:由数字,字符和下划线(_)组成的python以及整数[-5,256]

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

1
2
3
4

迭代器:迭代器是访问可迭代对象的工具
生成器:生成器是一种函数,用关键字 yield 来返回值,这种函数叫生成器函数,函数被调用时会返回一个生成器对象,生成器本质上还是一个迭代器。
装饰器:装饰器是一个在不改变原函数执行方式的前提下,给函数增添新的功能的函数。

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

data = [1, 3, 6, 7, 9, 12, 14, 16, 17, 18, 20, 21, 22, 23, 30, 32, 33, 35]

def binary_search(dataset,find_num):
    if len(dataset) > 1:
        mid = int(len(dataset) / 2)
        if dataset[mid] == find_num:  # find it
            print("找到数字", dataset[mid])
        elif dataset[mid] > find_num:  # 找的数在mid左面
            print("\033[31;1m找的数在mid[%s]左面\033[0m" % dataset[mid])
            return binary_search(dataset[0:mid], find_num)
        else:  # 找的数在mid右面
            print("\033[32;1m找的数在mid[%s]右面\033[0m" % dataset[mid])
            return binary_search(dataset[mid + 1:], find_num)
    else:
        if dataset[0] == find_num:  # find it
            print("找到数字啦", dataset[0])
        else:
            print("没的分了,要找的数字[%s]不在列表里" % find_num)

binary_search(data,20)
'''
找的数在mid[18]右面
找的数在mid[30]左面
找的数在mid[22]左面
找的数在mid[21]左面
找到数字啦 20
'''

63、os和sys模块的作用?

1
2
3

os模块负责程序与操作系统的交互,提供了访问操作系统底层的接口;
sys模块负责程序与python解释器的交互,提供了一系列的函数和变量,用于操控python的运行时环境。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85

os 常用方法


os.remove(‘path/filename’) 删除文件

os.rename(oldname, newname) 重命名文件

os.walk() 生成目录树下的所有文件名

os.chdir('dirname') 改变目录

os.mkdir/makedirs('dirname')创建目录/多层目录

os.rmdir/removedirs('dirname') 删除目录/多层目录

os.listdir('dirname') 列出指定目录的文件

os.getcwd() 取得当前工作目录

os.chmod() 改变目录权限

os.path.basename(‘path/filename’) 去掉目录路径,返回文件名

os.path.dirname(‘path/filename’) 去掉文件名,返回目录路径

os.path.join(path1[,path2[,...]]) 将分离的各部分组合成一个路径名

os.path.split('path') 返回( 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版本

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

1
2
3

import random
random.randint(0,99)

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

1
2

os.remove(path),删除文件path。如果path是一个目录,抛出osError错误。如果要删除目录,请使用rmdir()方法。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10

#使用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)

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12

'''
题意理解:组成后的数值不相同,且组合的三个位数之间数字不重复。
使用python内置的排列组合函数(不放回抽样排列)
product 笛卡尔积  (有放回抽样排列)
permutations 排列  (不放回抽样排列)
combinations 组合,没有重复  (不放回抽样组合)
combinations_with_replacement 组合,有重复  (有放回抽样组合)
'''
import itertools

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

67、什么是反射?以及应用场景?(*****)

1
2
3

在绝大多数语言中都有反射机制的存在,可以用字符串的形式去获取对象的属性,调用对象的方法(但是不能去访问方法),python中一切皆对象,都可以使用反射
flask配置文件以及Django中间件都用到了反射

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

1
2
3
4

元类(metaclass):指定当前类由谁来创建,类的metaclass 默认是type。我们也可以指定类的metaclass值。
应用用场景:Wtform中实例化自定义form类是执行了其元类的__call__方法。
          Django的orm

69、什么是闭包,谈谈你对闭包的理解?(*****)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 闭包函数(closure function)指的是定义在一个函数内部的函数,并且该函数包含对外部函数作用域中名字的引用,该函数就称为闭包函数
# 闭包函数是 名称空间与作用域、函数对象、函数嵌套的结合体

# 如下inner函数:
def outer():
    num=1 
    def inner():
        print(num)#内层函数中不存在num但可以访问到外层的num 
    return inner#基于函数对象的概念我们可以将内层函数返回到外界使用,从而打破函数调用的层级限制

func=outer()#func ==inner func指向的是inner的内存地址,但是func本身确实一个全局变量,可以在任意位置调用func
num=-1000
func() #输出结果:1
# 对闭包的理解:
'''
闭包是函数式编程的重要语法结构。闭包也是一种组织代码的结构,它提高了代码的可重复使用性。当一个内嵌函数引用外部作用域的变量我们就得到了一个闭包。
创建闭包必须满足一下几点:
  1、必须要一个内嵌函数
  2、内嵌函数必须引用外部函数中的变量
  3、外部函数的返回值必须是内嵌函数
'''

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15

'''
在不修改原函数及其调用方式的情况下对原函数的功能进行扩展
当我们写登录认证的时候,好多页面都得判断带没带cookie,如果带了就可以访问,这时候如果函数
不多的时候我们就可以用加装饰器的方法来判断,而不用一个一个的判断。当然,如果页面太多的话,
我们还可以考虑中间件的方式来进行判断。
'''
#装饰器模板
def wrapper(func):
    def inner(*args,**kwargs):
        '''函数执行之前的内容扩展'''
        res=func(*args,**kwargs)
        '''函数执行之前的内容扩展'''
        return res
    return inner

71、请实现一个装饰器,限制该函数被调用的频率,如10秒一次

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

import time
def timer(func):
    t = 0
    def inner(*args, **kwargs):
        nonlocal t
        t2 = time.time()
        if t2 - t >= 10:
            t = time.time()
            return func(*args, **kwargs)
        else:
            print('访问间隔太短')
    return inner

@timer
def test():
    print('Hello World!!')

test()
time.sleep(9)
test()

'''
Hello World!!
访问间隔太短
'''
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

import time
def time_pay(func):
    def inner(*args,**kwargs):
        for line in range(10):
            print(line+1)
            time.sleep(1)
        res=func(*args,**kwargs)
        return res
    return inner

@time_pay
def funcl():
    print('from func1...')

funcl()

'''
1
2
3
4
5
6
7
8
9
10
from func1...

'''

72、请实现一个装饰器,通过一次调用使函数一次执行5次。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19

def warpper(func):
    def inner(*args, **kwargs):
      for i in range(5):
          func(*args, **kwargs)

    return inner

@warpper
def test():
    print('a')

test()
-----------------------
a
a
a
a
a

73、介绍一下try except的用法和作用?

1
2
3
4
5
6
7

Python的except用来捕获所有异常,因为Python里面的每次错误都会抛出一个异常,所以每个程序的错误都被当作一个运行时错误。
try:
  pass 
except BaseException as e:
  print(e)
finally:pass

74、异常处理写法以及如何主动抛出、捕获、处理异常(应用场景)

1
2
3
4
5
6
7
8

try:
    raise Exception('触发异常')
except Exception as e:
    print(e) #处理异常
    
finally:
    print('无论是否错误都会执行此处代码!')

75、isinstance作用及应用场景?

1
2

作用:来判断一个对象是否是一个已知的类型

76、写代码并实现:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

'''
   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, and you may not use the same element twice.
  Example:
            Given nums = [2, 7, 11, 15], target = 9,
             Because nums[0] + nums[1] = 2 + 7 = 9,
             return [0, 1]
'''
class Solution:
    def twoSum(self,nums,target):
        d = {}
        n = len(nums)
        for x in range(n):
            if target - nums[x] in d:
                return d[target-nums[x]],x
            else:
                d[nums[x]] = x
# 输入:
#     nums:[2,7,11,15] 
#     target:9
# 输出:
#     [0,1]

!img 有待验证

77、使用生成器编写fib函数,函数声明为 fib(max),输入一个参数max值,使得该函数可以这样调用。并产生如下结果(斐波那契数列)1,1,2,3,5,8,13,.21…

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14

def fib():
    i,k = 1,0
    while 1 :
        j = i + k
        yield j
        i = k
        k = j
for fn in fib():
    if fn > 100:
        break
    else:
        print(fn)
# 1 1 2 3 5 8 13 21 34 55 89

78、一行代码,通过filter和lambda函数输出以下列表索引为基数对应的元素。

1
2
3
4

l1 = [12, 213, 22, 2, 2, 2, 22, 2, 2, 32]
l =filter(lambda x:x, [ l1[i] for i in range(1, len(l1), 2) ])
print(list(l))  #[213, 2, 2, 2, 32]

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

1
2
3

string、int、list、tuple、dict、bool、null
定制支持datetime类型
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13

import json
from json import JSONEncoder
from datetime import datetime
class ComplexEncoder(JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime):
            return obj.strftime('%Y-%m-%d %H:%M:%S')
        else:
            return super(ComplexEncoder,self).default(obj)
d = { 'name':'alex','data':datetime.now()}
print(json.dumps(d,cls=ComplexEncoder))
# {"name": "alex", "data": "2018-05-18 19:52:05"}

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10

import json

a=json.dumps({"ddf":"您好"})
print(a,type(a))
# {"ddf": "\u60a8\u597d"} <class 'str'>

b=json.dumps({"ddf":"您好"},ensure_ascii=False)
print(b,type(b))
# {"ddf": "您好"} <class 'str'>

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

1
2
3
4
5
6
7
8

断言是用来检查一个条件,如果它为真,就不做任何事。如果它为假,则会抛出AssertError并且包含错误信息。例如:

  防御型的编程
  运行时检查程序逻辑
  检查约定
  程序常量
  检查文档

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

1
2
3
4
5
6
7
8

# with语句的作用是通过某种方式简化异常处理,它是所谓的上下文管理器的一种,允许上下文管理器实现一些设置和清理操作# 例如:文件可以作为上下文管理器使用,它们可以关闭自身作为清理的一部分。# 用法举例如下:
with open('output.txt', 'w') as f:
    f.write('Hi there!')
'''
当你要成对执行两个相关的操作的时候,这样就很方便,以上便是经典例子,with语句会在嵌套的代码执行之后,自动关闭文件。这种做法的还有另一个优势就是,无论嵌套的代码是以何种方式结束的,它都关闭文件。如果在嵌套的代码中发生异常,
它能够在外部exception handler catch异常前关闭文件。如果嵌套代码有return/continue/break语句,它同样能够关闭文件。
'''

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

1
2
3
4
5

# os.listdir()方法可以列举某个文件夹内的所有文件和文件夹,os.path.isdir函数用于判断是否为文件夹。
import os 
s = [d for d in os.listdir('.')] # os.listdir可以列出文件和目录
print(s)   #['.idea', '668.py']

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

1
2
3
4
5

yield:     使用 yield 的函数被称为生成器(generator),跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作。
yield from:yield from 后面可以跟“ 生成器 元组 列表等可迭代对象和序列,返回也是一个生成器(generator)。

个人理解:yield把返回来的值组合成一个生成器,而yield from则把返回的(生成器,元组,列表等)组合成一个大的生成器。

85、python函数调用的时候参数的传递方式是值传递还是引用传递?

1
2
3
4
5
6
7

python的参数哦传递有:位置参数、默认参数、可变参数、关键字参数。
函数的传值到底是值传递还是引用传递,要分情况:
不可变参数用值传递:
  像整数和字符串这样不可变对象,是通过拷贝进行传递的,因为你无论如何都不可能在原处改变。
可变参数是引用传递的:
  比如像列表,字典这样的对象是通过引用传递、和C语言里面的用指针传递数组很相似,可变对象能在函数内部改变。

86、递归函数停止的条件?

1
2
3
4
5

递归的终止条件一般定义在递归函数内部,在递归调用前要做一个条件判断,根据判断的结果选择是继续调用自身,还是return;返回终止递归。
终止的条件:
  1.判断递归的次数是否达到某一限定值
  2.判断运算的结果是否达到某个范围等,根据设计的目的来选择

87、python递归的最大层数?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12

'''
最大层数为998,可以通过以下方式实验
'''

def func():
    func()
func()
'''
  [Previous line repeated 996 more times]  这里为什么是996?
RecursionError: maximum recursion depth exceeded   
'''

88、用Python匹配HTMLtag的时候,<.*>和<.?>有什么区别?

1
2
3

<.*>:贪婪匹配,会匹配到符合条件的所有标签
<.?>:非贪婪匹配,匹配到符合条件的第一个标签

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

1
2
3

functools.reduce:作用是将序列中的元素进行累计。
functools.wraps:装饰器中的原函数名是作为接受返回值的,但是装饰器中的返回值是包装器名,这样就破坏了原函数的属性,functools.wraps就是为了保留原函数的属性。

90、enumerate的作用是什么?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14

'''
enumerate函数是将一个可迭代对象中元素,按元素顺序每个增加一个索引值,将其组成一个索引序列,利用它可以同时获得索引和值,这样做的目的是为了将一个可选代对象中
元素组成一个“索引,值“对便于后续操作。
'''

goods_list = ['苹果', '梨','西瓜']
for index,goods in enumerate(goods_list):
    print(index,goods)
'''
0 苹果
1 梨
2 西瓜
'''

91、如何判断一个邮箱合法?(*****)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10

import re
if re. match(r'^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$',email):
    print(' right')
else:
    print('wrong')

#
if not re.match(r'^[a-z0-9][\w.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
   print('wrong')

面向对象

1、谈谈你对面向对象的理解?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14

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

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

封装,把方法封装到类中,把数据封装到对象中。
应用:上下文中
         - session/request封装到来RequestContext对象中
         - app/g封装到了AppContext中
继承:如果多个类中有相同的方法,为了避免重复编写,可以将其放在父类(基类)中,通过内置函数super()或者“基类名.方法名()”的方式实现这一目的。 
应用:rest framework中的视图类的继承

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

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

1
2
3
4
5
6

Python的类可以继承多个类,Python的类如果继承了多个类,那么其寻找方法的方式有两种
当类是经典类时,多继承情况下,会按照深度优先方式查找
当类是新式类时,多继承情况下,会按照广度优先方式查找
简单点说就是:经典类是纵向查找,新式类是横向查找
典类和新式类的区别就是,在声明类的时候,新式类需要加上object关键字。在python3中默认全是新式类 

3、什么是C3算法?

1
2
3

C3算法最早被提出是用于Lisp的,应用在Python中是为了解决原来基于深度优先搜索算法不满足本地优先级,和单调性的问题。本地优先级:指声明时父类的顺序,比如C(A,B),如果访问C类对象属性时,应该根据声明顺序,优先查找A类,然后再查找B类。
单调性:如果在C的解析顺序中,A排在B的前面,那么在C的所有子类里,也必须满足这个顺序。

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

1
2
3
4

1、在继承中基类的构造(__init__()方法)不会被自动调用,它需要在其派生类的构造中亲自专门调用。有别于C#
2、在调用基类的方法时,需要加上基类的类名前缀,且需要带上self参数变量。区别于在类中调用普通函数时并不需要带上self参数
3、Python总是首先查找对应类型的方法,如果它不能在派生类中找到对应的方法,它才开始到基类中逐个查找。  (先在本类中查找调用的方法,找不到才去基类中找)。 

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

1
2
3
4

super() 函数是用于调用父类(超类)的一个方法。用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。在super机制里可以保证公共父类仅被执行一次,至于执行的顺序,是按照mro进行的(E.__mro__)。
注意super继承只能用于新式类(pyhon3),用于经典类时就会报错。
新式类(python3只有新式类,默认继承object):必须有继承的类,如果没什么想继承的,那就继承object

6、什么是面向对象的mro ?

1
2
3

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

7、列举面向对象中带双下划线的特殊方法,如:newinit

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12

__call__ :对象后面加括号,触发执行。
__module__:表示当前操作的对象在哪个模块
__init__:构造方法,通过类创建对象时,自动触发执行。
__doc__:表示类的描述信息
__class__: 表示当前操作的对象的类是什么
__del__:析构方法,当对象在内存中被释放时,自动触发执行,注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,
        因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。
__dict__:类或对象中的所有成员
__str__:如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值。

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

9、双下划线和单下划线的区别?

1
2
3

“单下划线”开始的成员变量叫做保护变量,意思是只有类对象和子类对象自己能访问到这些变量。
“双下划线”开始的是私有成员,意思是只有类对象自己能访问,连子类对象也不能访问到这个数据。

10、请口述with的用法,如果自己的类需要支持with语句,应该如何书写?(*****)

1
2
3
4
5
6
7
8
9

基本格式 with context_expression [as target(s)]:with-body 
这里context_expression 要返回一个上下文管理器对象,该对象并不赋值给as子句中的target(s),如果指定了as子句的话,会将上下文管理器的__enter__()方法的
返回值赋值给 target(s)。target(s)可以是单个变量,或者由“()”括起来的元组(不能是仅仅由“,”分隔的变量列表,必须加“()”)。

自定义的上下文管理器要实现上下文管理协议所需要的__enter__()和__exit__()两个方法,
context_manager.enter():进入上下文管理器的运行时上下文,在语句体执行前调用。
with 语句将该方法的返回值赋值给as子句中的target,如果指定了as子句的话 
conte xt_manager.__exit__(exc_type,exc_value,exc_traceback):退出与上下文管理器相关的运行时上下文,返回一个布尔值表示是否对发生的异常进行处理。

11、实现一个Singleton单例类,要求遵循基本语言编程规范(用尽量多的方式)(*****)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12

# __new__
class Borg(object):
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls,'_instance'):
            ob = super(Borg,cls)
            cls._instance = ob.__new__(cls, *args, **kwargs)
            return cls._instance
        
class MyClass(Borg):
    def __init__(self):
        self.a = 1

12、单例模式的优点和应用?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12

单例模式的优点:
1、由于单例模式要求在全局内只有一个实例,因而可以节省比较多的内存空间;
2、全局只有一个接入点,可以更好地进行数据同步控制,避免多重占用;
3、单例可长驻内存,减少系统开销。
单例模式的应用举例:
1、生成全局惟一的序列号;
2、访问全局复用的惟一资源,如磁盘、总线等;
3、单个对象占用的资源过多,如数据库等;
4、系统全局统一管理,如Windows下的Task Manager;5、网站计数器
6、数据库配置,数据库连接池
7、应用程序的日志应用

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

1
2
3

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

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

1
2
3

1、静态方法不需要传入self参数,类成员方法需要传入代表本类的cls参数;
2、都可以通过实例或者类调用,不过实例方法通过类调用时需要传递实例的引用;

随机文章