python近期遇到的一些面试问题(三)
整理一下最近被问到的一些高频率的面试问题。总结一下方便日后复习巩固用,同时希望可以帮助一些朋友们。
前两期点这↓
python近期遇到的一些面试问题(一)
python近期遇到的一些面试问题(二)
1.请写一个邮箱的正则表达式
电子邮件地址有统一的标准格式:用户名@服务器域名。用户名表示邮件信箱、注册名或信件接收者的用户标识,@符号后是你使用的邮件服务器的域名。@可以读成“at”,也就是“在”的意思。整个电子邮件地址可理解为网络中某台服务器上的某个用户的地址。
答案
1.用户名,可以自己选择。由字母a~z(不区分大小写)、数字0~9、点、减号或下划线组成;只能以数字或字母开头和结尾
2.与你使用的网站有关,代表邮箱服务商。例如网易的有@163.com新浪有@vip.sina.com等
网上看到了各种各样的版本,都不确定用哪个,于是自己简单的总结了一个。大家有更好的欢迎留言。
r"^[a-zA-Z0-9]+[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$"
下面解释上面的表达式
1.首先强调一点关于\\w的含义,\\w匹配英文字母和俄语字母或数字或下划线或汉字
2.注意[]和[]的区别,[]表示字符集合,[]表示已[]内的任意字符集开始,[]表示
3.[a-zA-Z0-9]+:这里注意[]和[]的,第一个表示已什么开头,第二个[]的^表示不等于[]内。
所以这段表示以英文字母和数字开头,后面紧跟的+,限定其个数>=1个。
4.[a-zA-Z0-9_.+-]+:表示匹配英文字母和数字开头以及_.+-,的任意一个字符,并限定其个数>=1个。
为了考虑@前面可能出现.+-(但是不在开头出现)。
5.@就是邮箱必备符号了
6.@[a-zA-Z0-9-]+.:前面的不用说了,后面的.表示.转义了,也是必备符号。
7.
[a-zA-Z0-9-.]+$
:dollar符表示以什么结束,这里表示以英文字和数字或-. 1个或多个结尾。
来个例子验证一波:
import re
plt=re.compile(r"^[a-zA-Z0-9]+[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$")
b=plt.findall(\'adas+fefe.we@qq.com.cn\')
print(b)
网上找了个验证邮件地址的通用正则表达式(符合 RFC 5322 标准)
(?:[a-z0-9!#$%&\'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&\'*+/=?^_`{|}~-]+)*|"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])
2.以下两段代码运行之后结果是否相同?为什么?
第一段
l=[]
for i in range(10):
l.append({\'num\':i})
print(l)
第二段
l=[]
a={\'num\':0}
for i in range(10):
a[\'num\']=i
l.append(a)
print(l)
答案
首先分析第一段,{\'num\':i}的循环里面,每一次循环都产生一个新的字典类型,所以这个比较简单结果是
[{\'num\': 0}, {\'num\': 1}, {\'num\': 2}, {\'num\': 3}, {\'num\': 4}, {\'num\': 5}, {\'num\': 6}, {\'num\': 7}, {\'num\': 8}, {\'num\': 9}]
第二段情况就有些特殊了,a={\'num\':0}表示把映射类型字典的引用给了a,循环a[\'num\']=i的时候,a的引用地址不变,所以取了最后一次循环的值。
[{\'num\': 9}, {\'num\': 9}, {\'num\': 9}, {\'num\': 9}, {\'num\': 9}, {\'num\': 9}, {\'num\': 9}, {\'num\': 9}, {\'num\': 9}, {\'num\': 9}]
3.请写出下列代码的输出的内容:
def test1():
for i in range(2):
print(\'+\'+str(i))
yield str(i)
for a in test1():
print(\'-\'+a)
for a in list(test1()):
print(\'-\'+a)
答案
首先我们分析test1()打印的是什么, ```答案
zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * 号操作符,可以将元组解压为列表。
zip 方法在 Python 2 和 Python 3 中的不同:在 Python 3.x 中为了减少内存,zip() 返回的是一个对象。
所以这里按照最短的元素组成的字典输出是。
{\'a\':1,\'b\':2,\'c\':3}
5.请实现下面对象的序列号和反序列化。
class User():
name=\'user1\'
age=30
答案
我们把变量从内存中变成可存储或传输的过程称之为序列化 反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化 另外我们使用的模块是pickle #####1、只能在python中使用,只支持python的基本数据类型。 #####2、可以处理复杂的序列化语法。(例如自定义的类的方法,游戏的存档等) #####3、序列化的时候,只是序列化了整个序列对象,而不是内存地址。 pickle.dumps()方法把任意对象序列化成一个bytes.所以我们首先需要创建一个对象即u=User() 然后我们再把这个对象序列化。即 ``` bytes=pickle.dumps(u) ``` 然后是反序列化: 用pickle.loads()方法反序列化出对象.即 ``` object=pickle.loads(bytes) ``` ###6.写出下面代码的输出内容: ``` for n in filter(lambda n:n%5,[n for n in range(100) if n%5==0]): print(n) else: print(\'12345\') ```答案
首先我们知道filter的用法 filter(function, iterable) 其中还 function -- 判断函数。 iterable -- 可迭代对象。 返回 True 或 False 但是这个题比较坑 n%5和n%5==0的区别 ,n%5是n除以5求其余数。n%5==0是n的5整除。 lambda n:n%5这个返回的是个数字而不是一个布尔类型不符合filter的要求,所以输出12345。 要达到筛选效果我们可以这样改. ``` for n in filter(lambda n:n%5==0,[n for n in range(100) if n%5==0]): print(n) ``` 但是如果我们这样改呢, ``` for i in filter(lambda n:n%5==0,[n for n in range(100) if n%5==0]): print(n) ``` 结果就比较有意思了,大家可以考虑下为什么。