python企业面试题集锦
Posted romeo614
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python企业面试题集锦相关的知识,希望对你有一定的参考价值。
1
|
谈谈对Python和其他语言的区别 |
Python属于解释型语言,当程序运行时,是一行一行的解释,并运行,所以调式代码很方便,开发效率高, 还有龟叔给Python定位是任其自由发展、优雅、明确、简单,所以在每个领域都有建树,所有它有着非常强大的第三方库, 特点: 语法简洁优美,功能强大,标准库与第三方库都非常强大,而且应用领域也非常广 可移植性,可扩展性,可嵌入性 缺点: 运行速度慢, - 解释型 - python/php - 编译型 - c/java/c# - Python弱类型
(1)与java相比:在很多方面,Python比Java要简单,比如java中所有变量必须声明才能使用,而Python不需要声明,用少量的代码构建出很多功能;(高效的高级数据结构)
(2)与php相比:python标准包直接提供了工具,并且相对于PHP代码更易于维护;
(3)Python与c相比:
Python 和 C Python这门语言是由C开发而来
对于使用:Python的类库齐全并且使用简洁,如果要实现同样的功能,Python 10行代码可以解决,C可能就需要100行甚至更多.
对于速度:Python的运行速度相较与C,绝逼是慢了
Python的优势:
1、Python 易于学习;
2、用少量的代码构建出很多功能;(高效的高级数据结构)
3、Python 拥有最成熟的程序包资源库之一;
4、Python完全支持面向对象;
5、Python 是跨平台且开源的。
6、动态类型:
位和字节的关系
1字节 = 8 位 位(bit),数据存储是以“字节”(Byte)为单位,数据传输是以大多是以“位”(bit,又名“比特”)为单位, 一个位就代表一个0或1(即一个二进制),二进制是构成存储器的最小单位,每8个位(bit,简写为b)组成一个字节(Byte,简写为B), 字节是最小一级的信息单位
b、B、KB、MB、GB的关系
b --->位(bit) B --->字节 一个字节等于8位 1B = 8 bit 1kb = 1024 B 1 MB = 1024 KB 1 GB = 1024 MB
PEP8规范
1、使用4个空格而不是tab键进行缩进。 2、每行长度不能超过79 3、使用空行来间隔函数和类,以及函数内部的大块代码 4、必要时候,在每一行下写注释 5、使用文档注释,写出函数注释 6、在操作符和逗号之后使用空格,但是不要在括号内部使用 7、命名类和函数的时候使用一致的方式,比如使用CamelCase来命名类, 使用lower_case_with_underscores来命名函数和方法 8、在类中总是使用self来作为默认 9、尽量不要使用魔法方法 10、默认使用UTF-8,甚至ASCII作为编码方式 11、换行可以使用反斜杠,最好使用圆括号。 12、不要在一句import中多个库, 空格的使用 各种右括号前不要加空格。 逗号、冒号、分号前不要加空格。 函数的左括号前不要加空格。如Func(1) 序列的左括号前不要加空格。如list[2] 操作符左右各加一个空格,不要为了对齐增加空格 函数默认参数使用的赋值符左右省略空格 不要将多句语句写在同一行,尽管使用‘;’允许 if/for/while语句中,即使执行语句只有一句,也必须另起一行 函数命名使用全部小写的方式,常量命名使用大写,类属性(方法和变量)使用小写 类的命名首字母大写
一行代码实现删除列表里重复的元素
1
|
sorted( set (list),key=list.index)排列顺序不变 oldList = [ ‘a‘ , ‘b‘ , ‘c‘ , ‘d‘ , ‘a‘ , ‘a‘ ] |
newList
=
[]
for
letter
in
oldList:
if
letter
not
in
newList:
newList.append(letter)
print
newList
运行结果:
[
‘a‘
,
‘b‘
,
‘c‘
,
‘d‘
]
1
|
|
一行代码实现九九乘法表
1
|
print( ‘
‘ . join ([ ‘ ‘ . join ([ "%2s*%2s=%2s" %(j,i,i*j) for j in range(1,i+1)]) for i in range(1,10)])) |
1
2
3
4
|
s= "1,2,3" print(s.split( "," )) 结果 [ ‘1‘ , ‘2‘ , ‘3‘ ]<br data-filtered= "filtered" ><br data-filtered= "filtered" ><br data-filtered= "filtered" > |
s=[‘1‘, ‘2‘, ‘3‘]
print([int(i) for i in s])
结果
[1, 2, 3]
一行代码生成
[i**2 for i in range(1,11)]
结果
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
a=(5)与b=(5,)的区别
1
|
元组中只包含一个元素时,需要在元素后面添加逗号,否则括号会被当作运算符使用: |
a=(5)
b=(5,)
print(type(a),a)
print(type(b),b)
结果
<class ‘int‘> 5
<class ‘tuple‘> (5,)
三元运算写法和应用场景?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
应用场景:简化 if 语句 # 关于三元运算 # 结果+ if + 条件 + else + 结果 result= ‘gt‘ if 1>3 else ‘lt‘ print(result) # lt # 理解:如果条件为真,把if前面的值赋值给变量,否则把else后面的值赋值给变量。 lambda 表达式 temp = lambda x,y:x+y print(temp(4,10)) # 14 可替代: def foo(x,y): return x+y print(foo(4,10)) # 14 |
Python3和Python2的区别?
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
|
1:打印时,py2需要可以不需要加括号,py3 需要 python 2 :print ( ‘lili‘ ) , print ‘lili‘ python 3 : print ( ‘lili‘ ) python3 必须加括号 exec语句被python3废弃,统一使用exec函数 2:内涵 Python2:1,臃肿,源码的重复量很多。 2,语法不清晰,掺杂着C,php,Java,的一些陋习。 Python3:几乎是重构后的源码,规范,清晰,优美。 3、输出中文的区别 python2:要输出中文 需加 # -*- encoding:utf-8 -*- Python3 : 直接搞 4:input不同 python2 :raw_input python3 :input 统一使用input函数 5:指定字节 python2在编译安装时,可以通过参数-----enable-unicode=ucs2 或-----enable-unicode=ucs4分别用于指定使用2个字节、4个字节表示一个unicode; python3无法进行选择,默认使用 ucs4 查看当前python中表示unicode字符串时占用的空间: impor sys print(sys.maxunicode) #如果值是65535,则表示使用usc2标准,即:2个字节表示 #如果值是1114111,则表示使用usc4标准,即:4个字节表示 6: py2:xrange range py3:range 统一使用range,Python3中range的机制也进行修改并提高了大数据集生成效率 7:在包的知识点里 包:一群模块文件的集合 + __init__ 区别:py2 : 必须有__init__ py3:不是必须的了 8:不相等操作符 "<>" 被Python3废弃,统一使用 "!=" 9: long 整数类型被Python3废弃,统一使用 int 10:迭代器iterator的next()函数被Python3废弃,统一使用next(iterator) 11:异常StandardError 被Python3废弃,统一使用Exception 12:字典变量的has_key函数被Python废弃,统一使用 in 关键词 13:file函数被Python3废弃,统一使用open来处理文件,可以通过io.IOBase检查文件类型 |
xrange和range的区别
1
2
3
4
5
|
python2中 都在循环时使用,xrange内存性能更好,xrange用法与range完全相同,range一个生成list对象,xrange是生成器 要生成很大的数字序列的时候,用xrange会比range性能优很多,因为不需要一上来就开辟一块很大的内存空间。 在 Python 3 中,range() 是像 xrange() 那样实现,xrange()被抛弃。 |
文件操作时:xreadlines和readlines的区别?
1
2
3
|
python2中 readlines 返回一个列表 xreadlines 返回一个生成器 |
1
2
3
4
|
#format的三种玩法 格式化输出 res= ‘{} {} {}‘ .format( ‘egon‘ ,18, ‘male‘ ) ==> egon 18 male res= ‘{1} {0} {1}‘ .format( ‘egon‘ ,18, ‘male‘ ) ==> 18 egon 18 res= ‘{name} {age} {sex}‘ .format(sex= ‘male‘ ,name= ‘egon‘ ,age=18) |
谈谈Python的深浅拷贝?
1
2
3
4
|
浅拷贝只是增加了一个指针指向一个存在的地址, 而深拷贝是增加一个指针并且开辟了新的内存,这个增加的指针指向这个新的内存, 采用浅拷贝的情况,释放内存,会释放同一内存,深拷贝就不会出现释放同一内存的错误 |
Python垃圾回收机制?
1
2
3
4
5
|
引用计数 标记清除 分代回收 |
按每个字符串的第一个值,合并a和b到c
1
2
|
a = [ "a,1" , "b,3,22" , "c,3,4" ] b = [ "a,2" , "b,1" , "d,2" ] |
d=a+b
dic={}
for i in d:
dic.setdefault(i[0],"")
dic[i[0]]+=i[1:]
c=[]
for i in dic:
msg=i+dic[i]
c.append(msg)
1
|
print(c) |
一个list中多层嵌套list或者tuple(元组)或字典(dict)等的遍历
1
2
3
4
5
6
7
8
9
10
11
|
#coding=utf-8 def printList(list1): for elements in list1: if isinstance(elements,list) or isinstance(elements, tuple): printList(elements) #递归调用函数本身进行深层次的遍历 elif isinstance(elements, dict): for i in elements.items(): print(i) else : print(elements) 该题的基本思路就是先判断list中每一个元素具体是什么类型,如果是list或者是tuple,就采用递归算法往深进行一层一层的遍历,<br data-filtered= "filtered" >直到list中的元素为常规类型时,就打印输出,由于dict类型中的键值key必须唯一,所以只能是不可变类型数据,所以这里不存在深层遍历dict键值的问题。 |
列表排序
正数在前负数在后 2.整数从小到大 3.负数从大到小
1
2
3
4
5
|
例: 排序前[7, -8, 5, 4, 0, -2, -5] 排序后[0, 4, 5, 7, -2, -5, -8] print(list(sorted(lst, key = lambda x: (x < 0, abs(x))))) |
详解 https://www.cnblogs.com/ellisonzhang/p/10359057.html
什么是反射?以及应?用场景?
1
2
3
|
反射的核心本质就是以字符串的形式去导入个模块,利用字符串的形式去执行函数。 Django中的 CBV就是基于反射实现的。 |
用尽量多的方法实现单例模式
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
|
1:使用模块 Python的模块就是天然的单例模式。 因为模块在第一次导入时,会生成 .pyc 文件,当第二次导入时,就会直接加载 .pyc 文件,而不会再次执行模块代码。 因此,我们只需把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了。 例如: class V1( object ): def foo(self) pass V1 = V1() 将上面代码保存在文件test.py,要使用时,直接在其他文件中导入此文件中的对象,这个对象既是单例模式的对象 如: from a import V1 2:使用装饰器 def Singleton(cls): _instance = {} def _singleton(*args, **kargs): if cls not in _instance: _instance[cls] = cls(*args, **kargs) return _instance[cls] return _singleton @Singleton class A( object ): a = 1 def __init__(self, x=0): self.x = x a1 = A(2) a2 = A(3) 3:使用类 4:基于__new__方法实现 当我们实例化一个对象时,是先执行了类的__new__方法 当:(我们没写时,默认调用 object .__new__),实例化对象;然后再执行类的__init__方法,对这个对象进行初始化,所有我们可以基于这个,实现单例模式 |
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(a=2) func(2) func(2) ‘‘ ‘ [1] [1, 1] [1, 1, 1] 函数的默认参数是一个list 当第一次执行的时候实例化了一个list 第二次执行还是用第一次执行的时候实例化的地址存储 所以三次执行的结果就是 [1, 1, 1] 想每次执行只输出[1] ,默认参数应该设置为None ‘‘ ‘ |
字符串驻留机制
1
2
3
4
5
|
字符串驻留机制 对于短字符串,将其赋值给多个不同的对象时,内存中只有一个副本,多个对象共享该副 本。长字符串不遵守驻留机制。 驻留适用范围 由数字,字符和下划线(_)组成的python标识符以及整数[-5,256]。 |
Python里面如何拷贝一个对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
1.浅拷贝 : 使用copy.copy,它可以进行对象的浅拷贝(shallow copy),它复制了对象,但对于对象中的元素,依然使用引用(换句话说修改拷贝对象元素,则被拷贝对象元素也被修改) 2.深拷贝 : 使用copy.deepcopy,它可以进行深拷贝,不仅拷贝了对象,同时也拷贝了对象中的元素,获得了全新的对象,与被拷贝对象完全独立,但这需要牺牲一定的时间和空间。 3.特殊拷贝:相当于浅拷贝 如要复制列表L,使用list(L),要复制一个字典d,使用dict(d),要复制一个集合s,使用 set (s)。 总结一下的话:如果你要复制某个对象 object , 它属于python内建的类型type,那么你可以使用type( object )来 获得一个拷贝。 |
如何打乱一个排好序的list
1
2
|
1. import random 2. random.shuffle(alist) |
.find()和.index()的区别
1
2
3
|
s.index(x):返回字符串中出现x的最左端的索引值,如果不在则抛出valueError异常 s.find(x) :返回字符串中出现x的最左端字符的索引值,如果不在则返回-1 |
输入一个字符串,输出该字符串中字符的所有组合
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
|
def func(s) s=s.split( "," ) lst=[] lst1=[] lst2=[] for i in range(len(s)): for j in range(len(s)): for k in range(len(s)): if i>=j: msg= "" . join (s[j:i]) msg=msg+s[len(s)-k-1] count=0 for i in range(1,len(msg)): if len(msg) ==1 : lst.append(msg) elif msg[i]>msg[i-1]: count+=1 if count==len(msg)-1: lst.append(msg) a=list( set (lst)) for i in a: lst1.append( int (i)) lst1=sorted(lst1) for i in lst1: lst2.append(str(i)) print(lst2,len(lst2)) |
一个数如果恰好等于它的因子之和,这个数就称为“完数”。例如6=1+2+3.编程
找出1000以内的所有完数。
def func(n):
a=n/2
lst=[]
count=1
while count<a+1:
if n%count==0:
lst.append(count)
count+=1
if sum(lst)==n:
return n
lst=[]
for i in range(1001):
if func(i):
lst.append(i)
print(lst)
将一个正整数分解质因数。例如:输入90,打印出90=2*3*3*5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
n = int (input( ">>>" )) b = n a = n / 2 lst = [] count = 2 while count < a + 1: if n % count == 0: n = n / count lst.append(count) else : count += 1 print(f "{b}=" , end= "" ) for i in range(len(lst)): if i == len(lst) - 1: print(lst[i]) else : print(f "{lst[i]}*" , end= "" ) |
判断101-200之间有多少个素数,并输出所有素数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
def func(n): b=n a=n/2 lst=[] count=2 while count<a+1: if n%count==0: n=n/count lst.append(count) else : count += 1 return lst count=0 for i in range(101,201): a=func(i) if a == []: count += 1 print(count) |
对于一个非空字符串,判断其是否可以有一个子字符串重复多次组成
# def func(s): # lst=list(s) # count=0 # for j in range(1,len(s)//2+1): # lst1=[] # for i in range(0,len(s),j): # msg="".join(lst[i:i+j]) # lst1.append(msg) # if len(set(lst1))==1: # count=1 # print("Ture") # return lst1[0] # if count==0: # print("False")
把aaabbcccd这种形式的字符串压缩成a3b2c3d1这种形式
1
2
3
4
5
6
7
8
|
s= "aaabbcccd" lst=[] for i in s: if i not in lst: lst.append(i) lst.append(str(s.count(i))) msg= "" . join (lst) print(msg) |
通过代码实现如下进制转换:
1 hex() 2 转换一个整数对象为十六进制的字符串 3 4 >>> hex(16) 5 ‘0x10‘ 6 >>> hex(18) 7 ‘0x12‘ 8 >>> hex(32) 9 ‘0x20‘
1 oct() 2 转换一个整数对象为八进制的字符串 3 4 >>> oct(8) 5 ‘0o10‘ 6 >>> oct(166) 7 ‘0o246‘
1 bin() 2 转换一个整数对象为二进制字符串 3 4 >>> bin(10) 5 ‘0b1010‘ 6 >>> bin(255) 7 ‘0b11111111‘
1 chr() 2 转换一个[0, 255]之间的整数为对应的ASCII字符 3 4 >>> chr(65) 5 ‘A‘ 6 >>> chr(67) 7 ‘C‘ 8 >>> chr(90) 9 ‘Z‘ 10 >>> chr(97) 11 ‘a‘
1 ord() 2 将一个ASCII字符转换为对应整数 3 4 >>> ord(‘A‘) 5 65 6 >>> ord(‘z‘) 7 122
1 16进制转10进制 2 >>> int(‘10‘, 16) 3 16 4 >>> int(‘0x10‘, 16) 5 16 6 7 8进制转10进制 8 >>> int(‘0o10‘, 8) 9 8 10 >>> int(‘10‘, 8) 11 8 12 13 2进制转10进制 14 >>> int(‘0b1010‘, 2) 15 10 16 >>> int(‘1010‘, 2) 17 10
lambda表达式格式以及应用场景
2、map,filter,reduce函数
例子: a = [(‘a‘,1),(‘b‘,2),(‘c‘,3),(‘d‘,4)] a_1 = list(map(lambda x:x[0],a)) 如上例子,map函数第一个参数是一个lambda表达式,输入一个对象,返回该对象的第一个元素。
第二个就是需要作用的对象,此处是一个列表。Python3中map返回一个map对象,我们需要人工
转为list,得到的结果就是[‘a’,’b’,’c’,’d’] 例子: a = [1,2,3,4] b = [2,3,4,5] a_1 = list(map(lambda x,y:x+y,a,b)) 上边这个例子是为了说明,lambda表达式参数可以是多个。返回结果是[3,5,7,9]
例子: a = [1,2,3,4,5,6,7] a_1 = filter(lambda x:x<4,a) 如上例子,定义lambda表达式,筛选a列表中小于4的元素,结果为[1,2,3]。filter函数直接返回一个列表,
无需再进行转换,第三个是初始值,我们没给初始值,那么开始操作的两个元素就是序列的前两个。否则将使用我们
给出的初始值和序列第一个元素操作,然后结果再与第三个元素操作,以此类推。上个例子结果是28
例子: from functools import reduce #python3需要导入此模块 a = [1,2,3,4,5,6,7] a_1 = reduce(lambda x,y:x+y,a) reduce中使用的lambda表达式需要两个参数,reduce函数共三个参数, 第一个是就是lambda表达式,第二个是要累计的序列,第三个是初始值, 我们没给初始值,那么开始操作的两个元素就是序列的前两个。否则将使 用我们给出的初始值和序列第一个元素操作,然后结果再与第三个元素操 作,以此类推。上个例子结果是28
3、字典多条件排序
例子: dict = {‘a‘:1,‘b‘:2,‘c‘:3,‘d‘:4,‘e‘:3,‘f‘:1,‘g‘:7} sorted_dict_asc = sorted(dict.items(),key=lambda item:item[0]) sorted_dict_dsc = sorted(dict.items(),key=lambda item:item[0],reverse=True) 输出(第一个升序,第二个降序): [(‘a‘, 1), (‘b‘, 2), (‘c‘, 3), (‘d‘, 4), (‘e‘, 3), (‘f‘, 1), (‘g‘, 7)] [(‘g‘, 7), (‘f‘, 1), (‘e‘, 3), (‘d‘, 4), (‘c‘, 3), (‘b‘, 2), (‘a‘, 1)]]
pass的作用
pass是空语句占位符,是为了保持程序结构的完整性。
*arg和**kwarg作用
定义函数时,使用*arg和**kwarg *arg和**kwarg 可以帮助我们处理上面这种情况,允许我们在调用函数的时候传入多个实参 def exmaple2(required_arg, *arg, **kwarg): if arg: print "arg: ", arg if kwarg: print "kwarg: ", kwarg exmaple2("Hi", 1, 2, 3, keyword1 = "bar", keyword2 = "foo") >> arg: (1, 2, 3) >> kwarg: {‘keyword2‘: ‘foo‘, ‘keyword1‘: ‘bar‘} 从上面的例子可以看到,当我传入了更多实参的时候 *arg会把多出来的位置参数转化为tuple **kwarg会把关键字参数转化为dict
简述 生成器、迭代器、可迭代对象 以及应用场景?
1
2
3
4
5
6
7
8
9
10
11
|
简述 生成器、迭代器、可迭代对象 以及应用场景? Python可迭代对象(Iterable) Python中经常使用 for 来对某个对象进行遍历,此时被遍历的这个对象就是可迭代对象,像常见的list,tuple都是。<br>如果给一个准确的定义的话,就是只要它定义了可以返回一个迭代器的__iter__方法,或者定义了可以支持下标索引的__getitem__方法<br>(这些双下划线方法会在其他章节中全面解释),那么它就是一个可迭代对象。 Python迭代器(iterator) 迭代器是通过next()来实现的,每调用一次他就会返回下一个元素,当没有下一个元素的时候返回一个StopIteration异常,<br>所以实际上定义了这个方法的都算是迭代器。可以用通过下面例子来体验一下迭代器: 生成器(Generators) 生成器是构造迭代器的最简单有力的工具,与普通函数不同的只有在返回一个值的时候使用yield来替代 return ,然后yield会自动构建好next()和iter() 因为迭代器如此普遍,python专门为 for 关键字做了迭代器的语法糖。在 for 循环中,Python将自动调用工厂函数iter()获得迭代器,<br>自动调用next()获取元素,还完成了检查StopIteration异常的工作。 |
谈谈你对闭包的理解。
1 #闭包函数的实例 2 # outer是外部函数 a和b都是外函数的临时变量 3 def outer( a ): 4 b = 10 5 # inner是内函数 6 def inner(): 7 #在内函数中 用到了外函数的临时变量 8 print(a+b) 9 # 外函数的返回值是内函数的引用 10 return inner 11 12 if __name__ == ‘__main__‘: 13 # 在这里我们调用外函数传入参数5 14 #此时外函数两个临时变量 a是5 b是10 ,并创建了内函数,然后把内函数的引用返回存给了demo 15 # 外函数结束的时候发现内部函数将会用到自己的临时变量,这两个临时变量就不会释放,会绑定给这个内部函数 16 demo = outer(5) 17 # 我们调用内部函数,看一看内部函数是不是能使用外部函数的临时变量 18 # demo存了外函数的返回值,也就是inner函数的引用,这里相当于执行inner函数 19 demo() # 15 20 21 demo2 = outer(7) 22 demo2()#17
1
2
|
# 一行代码 通过filter 和 lambda 函数输出以下列表索引为奇数的对应的元素 list_b = [12, 232, 22, 2, 2, 3, 22, 22, 32] |
new_list=[x[1] for x in filter(lambda x:x[0]%2==1,enumerate(list_b))]
Python中 dict.items() dict.iteritems()区别
dict.items()返回的是一个完整的列表,而dict.iteritems()返回的是一个生成器(迭代器)。 dict.items()返回列表list的所有列表项,形如这样的二元组list:[(key,value),(key,value),...],
dict.iteritems()是generator, yield 2-tuple。相对来说,前者需要花费更多内存空间和时间,但访问某一项的时间较快(KEY)。
后者花费很少的空间,通过next()不断取下一个值,但是将花费稍微多的时间来生成下一item。
对于yield与yield from 的理解
yield是什么?
yield单词的含义:屈服,投降,提供
对于一个函数而言,程序的执行,从上到下执行完一遍,这个函数也就完成了它的使命。
def hello():
print(‘exe 1‘)
print(‘exe 2‘)
hello()这个函数从上到下依次执行,然后hello()结束。
若一个函数中加入了yield语句,那么这个函数就被增强了,变成了一个生成器:generator。
对于一个函数,其程序执行到了yield语句,那么它选择了`投降`,返回一个结果,这个函数被中断,然后随着生成器的next的执行,该函数从中断的地方执行。
>```
def helloYield():
print(‘exe 1‘)
yield ‘1 be exed‘
print(‘exe 2‘)
yield ‘2 be exed‘
执行:
gen=helloYield()
print(gen.__next__())
print(gen.__next__())
结果:
exe 1
1 be exed
exe 2
2 be exed
yield from是什么?
yield 可以返回结果
yield from 可以返回一个新的迭代器
看一个例子:
有一个list,如下:
lists = [
1, 2, 3,
[4, 5, [6, 7], 8],
[[[9, 10], 11]],
[[]],
12,
]
需要将list中的所有数据一个个显示出来,如下:
1
2
3
4
5
6
7
8
9
10
11
12
采用yield from的方式,代码如下:
def flatten(items):
for item in items:
if isinstance(item, (list, tuple)):
yield from flatten(item)
else:
yield item
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
常用模块都有那些? re模块,os模块,json模块,time模块, 爬虫里面的requests/beautifulsoup4(bs4) re的match和search区别? re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。 re.search 扫描整个字符串并返回第一个成功的匹配。 什么是正则的贪婪匹配? 匹配一个字符串没有节制,能匹配多少就去匹配多少,知道没有匹配的为止 |
logging模块的作用?以及应用场景?
模块定义的函数和类为应用程序和库的开发实现了一个灵活的事件日志系统 作用:可以了解程序运行情况,是否正常
在程序的出现故障快速定位出错地方及故障分析
谈谈你对面向对象的理解
三大特性以及解释?
面对对象是一种编程思想,以类的眼光来来看待事物的一种方式。将有共同的属性和方法的事物封装到同一个类下面。
继承:将多个类的共同属性和方法封装到一个父类下面,然后在用这些类来继承这个类的属性和方法
封装:将有共同的属性和方法封装到同一个类下面
- 第一层面:创建类和对象会分别创建二者的名称空间,我们只能用类名.或者obj.的方式去访问里面的名字,这本身就是一种封装
- 第二层面:类中把某些属性和方法隐藏起来(或者说定义成私有的),只在类的内部使用、外部无法访问,或者留下少量接口(函数)供外部访问。
多态:Python天生是支持多态的。指的是基类的同一个方法在不同的派生类中有着不同的功能
Python面向对象中的继承有什么特点
继承概念的实现方式主要有2类:实现继承、接口继承。 实现继承是指使用基类的属性和方法而无需额外编码的能力; 接口继承是指仅使用属性和方法的名称、但是子类必须提供实现的能力(子类重构爹类方法); python 两种类:经典类 新式类 python3 新式类 —— 都默认继承object class Animal(object): == class Animal: python2 经典类和新式类 并存 class Animal: 经典类 —— 继承顺序 个别使用方法 class Animal(object): 新式类 继承分为单继承和多继承 Python是支持多继承的 如果没有指定基类,python的类会默认继承object类,object是所有python类的基类,它提供了一些常见方法(如__str__)的实现。
补充继承的应用(面试题)
1、对象可以调用自己本类和父类的所有方法和属性, 先调用自己的 自己没有才调父类的。谁(对象)调用方法,方法中的self就指向谁 class Foo: def __init__(self): self.func() def func(self): print(‘Foo.func‘) class Son(Foo): def func(self): print(‘Son.func‘) s = Son() # Son.func ======================================================== class A: def get(self): self.say() def say(self): print(‘AAAAA‘) class B(A): def say(self): print(‘BBBBB‘) b = B() b.get() #输出结果为:BBBBB
面向对象深度优先和广度优先是什么?
Python的类可以继承多个类,Python的类如果继承了多个类,那么其寻找方法的方式有两种 当类是经典类时,多继承情况下,会按照深度优先方式查找 py3 当类是新式类时,多继承情况下,会按照广度优先方式查找 py2 简单点说就是:经典类是纵向查找,新式类是横向查找 经典类和新式类的区别就是,在声明类的时候,新式类需要加上object关键字。在python3中默认全是新式类
面向对象中super的作用?
用于子类继承基类的方法
class FooParent(object): def __init__(self): self.parent = ‘I‘m the parent.‘ print(‘Parent‘) print(‘1111‘) def bar(self, message): print("%s from Parent" % message) class FooChild(FooParent): def __init__(self): # super(FooChild,self) 首先找到 FooChild 的父类(就是类 FooParent),然后把类B的对象 FooChild 转换为类 FooParent 的对象 super(FooChild, self).__init__() print(‘Child‘) # def bar(self, message): # # super(FooChild, self).bar(message) # print(‘Child bar fuction‘) # print(self.parent) if __name__ == ‘__main__‘: fooChild = FooChild() fooChild.bar(‘HelloWorld‘)
是否使用过functools中的函数?其作用是什么?
用于修复装饰器
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
列举面向对象中带双下划线的特殊方法,如:__new__、__init__
- __new__:生成实例
- __init__:生成实例的属性
-
__call__:实例对象加( )会执行def __call__:... 方法里边的内容。
__del__:析构方法,当对象在内存中被释放时,自动触发执行。如当 del obj 或者应用程序运行完毕时,执行该方法里边的内容。
__enter__和__exit__:出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量;with中代码块执行完毕时执行__exit__里边的内容。
__module__:表示当前操作的对象在那个模块 obj.__module__
__class__ :表示当前操作的对象的类是什么 obj.__class____doc__:类的描述信息,该描述信息无法被继承
__str__:改变对象的字符串显示 print函数 --->obj.__str__()
__repr__:改变对象的字符串显示 交互式解释器 --->obj.__repr__()
__format__:自定制格式化字符串__slots__:一个类变量 用来限制实例可以添加的属性的数量和类型
__setitem__,__getitem,__delitem__:
class Foo: def __init__(self,name): self.name=name def __getitem__(self, item): print(self.__dict__[item]) def __setitem__(self, key, value): self.__dict__[key]=value def __delitem__(self, key): print(‘del obj[key]时,我执行‘) self.__dict__.pop(key) def __delattr__(self, item): print(‘del obj.key时,我执行‘) self.__dict__.pop(item) f1=Foo(‘sb‘) f1[‘age‘]=18 f1[‘age1‘]=19 del f1.age1 del f1[‘age‘] f1[‘name‘]=‘alex‘ print(f1.__dict__)
__get__():调用一个属性时,触发
__set__():为一个属性赋值时,触发
__delete__():采用del删除属性时,触发
__setattr__,__delattr__,__getattr__ :
如何判断是函数还是方法?
看他的调用者是谁,如果是类,就需要传入一个参数self的值,这时他就是一个函数,
如果调用者是对象,就不需要给self传入参数值,这时他就是一个方法
print(isinstance(obj.func, FunctionType)) # False
print(isinstance(obj.func, MethodType)) # True
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参数 """
静态方法和类方法区别?
尽管 classmethod 和 staticmethod 非常相似,但在用法上依然有一些明显的区别。classmethod 必须有一个指
向类对象的引用作为第一个参数,而 staticmethod 可以没有任何参数。
举个栗子:
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
什么是面向对象的mro
1
|
mro就是方法解析顺序 |
isinstance作用以及应用场景?
isinstance(对象,类) 判断这个对象是不是这个类或者这个类的子类的实例化
# # 判断a 属不属于A这个类(可以判断到祖宗类) class A: pass class B(A): pass a = A() b = B() print(isinstance(b,A)) # ===> True 判断到祖宗类 # 任何与object都是True,内部都继承object class A:pass a = A() # 实例化 print(isinstance(a,object)) # True
75. json序列化时,可以处理的数据类型有哪些?如何定制支持datetime类型?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
class CJsonEncoder(json.JSONEncoder): def default (self, obj): if isinstance(obj, datetime.date): return obj.strftime( ‘%Y-%m-%d %H:%M:%S‘ ) else : return json.JSONEncoder. default (self, obj) import json import datetime a = datetime.datetime.now() print(a) b = json.dumps(a,cls=CJsonEncoder) print(b) |
json序列化时,默认遇到中文会转换成unicode,如果想要保留中文怎么办?
在序列化时,中文汉字总是被转换为unicode码,在dumps函数中添加参数ensure_ascii=False即可解决。
什么是断言?应用场景?
assert 是的作用?断言 条件成立(布尔值为True)则继续往下,否则跑出异常,一般用于:满足某个条件之后,才能执行,否则应该跑出异常。
logging模块的作用?以及应用场景?
1
2
3
4
5
6
7
|
1.日志的作用 通过log的分析,可以方便用户了解系统或软件、应用的运行情况;如果你的应用log足够丰富,也可以分析以往用户的操作行为、<br>类型喜好、地域分布或其他更多信息;如果一个应用的log同时也分了多个级别,那么可以很轻易地分析得到该应用的健康状况,<br>及时发现问题并快速定位、解决问题,补救损失。简单来讲就是,我们通过记录和分析日志可以了解一个系统或软件程序运行情况<br>是否正常,也可以在应用程序出现故障时快速定位问题。比如,做运维的同学,在接收到报警或各种问题反馈后,进行问题排查时<br>通常都会先去看各种日志,大部分问题都可以在日志中找到答案。再比如,做开发的同学,可以通过IDE控制台上输出的各种日志进<br>行程序调试。对于运维老司机或者有经验的开发人员,可以快速的通过日志定位到问题的根源。可见,日志的重要性不可小觑。<br>日志的作用可以简单总结为以下3点: 程序调试 了解软件程序运行情况,是否正常 软件程序运行故障分析与问题定位 即:DEBUG < INFO < WARNING < ERROR < CRITICAL,而日志的信息量是依次减少的; |
有用过with statement吗?它的好处是什么?
1
2
3
4
5
6
7
8
|
文件操作的时候用过 with语句的作用是通过某种方式简化异常处理,它是所谓的上下文管理器的一种 with open( ‘output.txt‘ , ‘w‘ ) as f: f.write( ‘Hi there!‘ ) 当你要成对执行两个相关的操作的时候,这样就很方便,以上便是经典例子,with语句会在嵌套的代码执行之后,<br>自动关闭文件。这种做法的还有另一个优势就是,无论嵌套的代码是以何种方式结束的,它都关闭文件。<br>如果在嵌套的代码中发生异常,它能够在外部exception handler catch 异常前关闭文件。如果嵌套代码有 return / continue / break 语句,它同样能够关闭文件。 |
请描述with的用法
python中with可以明显改进代码友好度,比如: 复制代码 代码如下: with open(‘a.txt‘) as f: print f.readlines() 为了我们自己的类也可以使用with, 只要给这个类增加两个函数__enter__, __exit__即可: 复制代码 代码如下: >>> class A: def __enter__(self): print ‘in enter‘ def __exit__(self, e_t, e_v, t_b): print ‘in exit‘ >>> with A() as a: print ‘in with‘ in enter in with in exit 另外python库中还有一个模块contextlib,使你不用构造含有__enter__, __exit__的类就可以使用with: 复制代码 代码如下: >>> from contextlib import contextmanager >>> from __future__ import with_statement >>> @contextmanager ... def context(): ... print ‘entering the zone‘ ... try: ... yield ... except Exception, e: ... print ‘with an error %s‘%e ... raise e ... else: ... print ‘with no error‘ ... >>> with context(): ... print ‘----in context call------‘ ... entering the zone ----in context call------ with no error 使用的最多的就是这个contextmanager, 另外还有一个closing 用处不大 复制代码 代码如下: from contextlib import closing import urllib with closing(urllib.urlopen(‘http://www.python.org‘)) as page: for line in page: print line
以上是关于python企业面试题集锦的主要内容,如果未能解决你的问题,请参考以下文章