2020 年最全 Python 面试题汇总 (二)
@Author:Runsen
求职季在即,技巧千万条,硬实力才是关键,听说今年疫情大环境不好,更要好好准备才行。于是Runsen在牛客网,Leetcode,九章算法,不断地寻找面试真题,共计100题,包括Python基础,算法,数据库,SQL,Linux。
大四刷题拼offer系列,不拼不行啊。我先刷下牛客网的Python的题目和知识点,适当的记录下自己做
错的题目。
文章目录
- 21、__new__和__init__的区别
- 22、==和is的区别
- 23、*args and **kwargs
- 24、 闭包
- 25、PEP8规范
- 26、ascii、Unicode、utf-8、gbk的区别
- 27、进制转换
- 28、可迭代对象迭代器
- 29、迭代器
- 30、获取命令行参数
- 31、filter、map、reduce
- 32、yield和return的区别
- 33、生成器
- 34、enumerate
- 35、面向对象的三大特性
- 36、super
- 37、魔术方法
- 38、@staticmethod和@classmethod区别
- 39、@property
- 40、内置类属性
21、__new__和__init__的区别
填空题:在Python中__new__
和 __init__
的区别主要表现在
__new__
:创建对象时调用,会返回当前对象的一个实例__init__:
创建完对象后调用,对当前对象的一些实例初始化,无返回值
class ClsTest(object):def __init__(self):print("init")def __new__(cls,*args, **kwargs):print("new")ClsTest()
# 输出
new
简单总结如下:
1,__new__
方法是对象的生成方法,__init__
方法是对象的初始化方法。
2,对象生成后,才能初始化。故__new__
方法在__init__
方法之前调用。
3,__new__
方法的第一个参数是cls,指的是类本身,__init__
的第一个参数是self,指的是__new__
方法生成的对象。
4,__new__
方法的其余参数会和生成的对象一起继续传给__init__
方法。
5,__new__
方法的返回值通常调用其父类的__new__
方法生成。
6,__init__
方法不能有返回值。
7,__new__
较少使用,可以用它实现单例模式,即一个类只能创建一个实例,有时候通过使用单例模式可以极大减少内存的占用。
22、==和is的区别
题目举例:说明Python中==和is的区别。
参考解析:is是判读对象标识符是否一致,而==是判读两个对象的内容是否相等!
x is y
相当于 id(x)==id(y)
==是检查两个对象的内容是否相等,会调用对象的内部__eq__()
。
例如下面这段代码,只有数值型和字符串型的情况下,a is b才为True,当a和b是tuple,list,dict或set型时,a is b为False。(下面代码只举了字符串和list)
>>> a = "Runsen"
>>> b = "Runsen"
>>> a is b
True
>>> id(a) == id(b)
True
>>> a == b
True
>>> c = [1,2,3]
>>> d = [1,2,3]
>>> c is d
False
>>> id(c) == id(d)
False
>>> c == d
True
23、*args and **kwargs
请问:在Python函数中*args and **kwargs
有上面区别?
*args
代表一个元组(数组参数),**kwargs
代表一个字典(字典参数)
# 单星号(*): 将所有参数以元祖(tuple)的形式导入
def signal_start(param1,*param2):print ("param1={}".format(param1))print ("*param2={}".format(param2))
signal_start(1,2,3,4,5)
# param1=1
# *param2=(2, 3, 4, 5)# 双星号(**)将参数以字典的形式导入
def double_start(param1,**param2):print ("param1={}".format(param1))print ("**param2={}".format(param2))double_start(1,a=2,b=3)
# param1=1
# **param2={'a': 2, 'b': 3}
24、 闭包
问:说说Python中闭包是什么?
答:可以将闭包理解为一种特殊的函数,这种函数由两个函数的嵌套组成,外函数和内函数。
def 外层函数(参数):def 内层函数():print("内层函数执行", 参数)return 内层函数内层函数的引用 = 外层函数("传入参数")
内层函数的引用()
在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了一个闭包。
下面举一个具体的闭包函数的实例,代码如下。
# outer是外部函数
def outer(a):# inner是内函数def inner( b ):#在内函数中 用到了外函数的临时变量print(a+b)# 外函数的返回值是内函数的引用return inner
ret = outer(5) #ret = inner
ret(10) #15 ret 存了外函数的返回值,也就是inner函数的引用,这里相当于执行inner函数
25、PEP8规范
请列出至少5个PEP8规范
每一级缩进使用4个空续缩进对齐。
每行代码的最大长度限制为79个字符
在表达式中避免无关的空格
代码更改时,相应的注释也要随之更改。
命名要规范,通俗易懂
26、ascii、Unicode、utf-8、gbk的区别
- ascii 是最早美国用的标准信息交换码,把所有的字母的大小写,各种符号用 二进制来表示,共有256中,加入些拉丁文等字符,1bytes代表一个字符
- Unicode是为了统一世界各国语言的不用,统一用2个bytes代表一个字符,可以表达2^16=65556个,称为万国语言,特点:速度快,但浪费空间
- utf-8 为了改变Unicode的这种缺点,规定1个英文字符用1个字节表示,1个中文字符用3个字节表示,特点;节省空间,速度慢,用在硬盘数据传输,网络数据传输,相比硬盘和网络速度,体现不出来的
- gbk 是中文的字符编码,用2个字节代表一个字符
27、进制转换
进制转换以十进制为媒介:十六进制前面加上0x,八进制加上0o,二进制前面加上0b。
二进制 | 八进制 | 十进制 | 十六进制 | |
---|---|---|---|---|
二进制 | bin(int(x, 8)) | bin(int(x, 10)) | bin(int(x, 16)) | |
八进制 | oct(int(x, 2)) | oct(int(x, 10)) | oct(int(x, 16)) | |
十进制 | int(x, 2) | int(x, 8) | int(x, 16) | |
十六进制 | hex(int(x, 2)) | hex(int(x, 8)) | hex(int(x, 10)) |
28、可迭代对象迭代器
什么是可迭代对象?
可迭代的对象:常见的可以被for循环迭代的一些数据类型都是可迭代的对象,如列表,元组,字典,集合,字符串,生成器,range函数生成的数列等。凡是可作用于for循环的对象都是Iterable可迭代对象类型;
>>> iter(1111)
Traceback (most recent call last):File "<stdin>", line 1, in <module>
TypeError: 'int' object is not iterable
>>> iter("1111")
<str_iterator object at 0x000002430E9C2320>
这些对象都有一个内置的iter方法,且该方法可以返回一个迭代器对象,当用iter(可迭代对象)
调用这个对象时,会返回一个迭代器对象(属于Iterator类)
29、迭代器
什么是迭代器?
凡是可作用于next( )函数的对象都是迭代器(Iterator类型),它们表示一个惰性计算的序列。
集合数据类型如list、tuple、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。
>>> list=['Runsen','为','offer', '而战']
>>> it = iter(list) # 创建迭代器对象
>>> print ('输出迭代器的下一个元素: ',next(it))
输出迭代器的下一个元素: Runsen
>>> print ('再输出迭代器的下一个元素: ',next(it))
再输出迭代器的下一个元素: 为
30、获取命令行参数
Python代码如何获取命令行参数?
python中获取命令行参数的方法有很多,早先的sys模块的argv就是其中之一,现在使用比较多的是argparse模块。
sys.argv[0]是Python脚本文件名,sys.argv[1:]之后的才是传入到python脚本中的参数。所有通过命令行传入到脚本中的参数,都是字符串类型!
下面是testargv.py文件中的代码。
import sysif __name__ == "__main__":print(sys.argv)print(sys.argv[0])sum = 0if len(sys.argv) > 1:for i in sys.argv[1:]:sum += int(i) # 强制类型转换成int类型print("sum = ", sum)else:print("No Parameter is passed in!")
argparse更易于编写用户友好的命令行界面。程序定义所需要的参数,argparse将找出如何从sys.argv中解析这些参数。
使用步骤:
- import argparse 首先导入模块
- parser = argparse.ArgumentParser() 创建一个解析对象
- parser.add_argument() 向该对象中添加你要关注的命令行参数和选项
- parser.parse_args() 进行解析
下面是testargparse.py的代码。
import argparse# ArgumentParser对象保存了将命令行传入的参数解析成Python数据类型的所以信息
parser = argparse.ArgumentParser(description='Process some integers.')
# 调用add_argument,即可将程序的参数填充进ArgumentParser,规定
# ArgumentParser如何将命令行的字符转换成objects
parser.add_argument('integers', metavar='N', type=int, nargs='+',help='an integer for the accumulator')
parser.add_argument('--sum', dest='accumulate', action='store_const',const=sum, default=max,help='sum the integers (default: find the max)')
# 调用parse_args() 可以将上述所有的信息保存并开始使用
args = parser.parse_args()
print(args.accumulate(args.integers))
31、filter、map、reduce
filter() 相当于过滤器的作用
s=[1,2,3,5,6,8,9,10,25,12,30]
# 筛选出3的倍数
# 第一个参数为一个返回True或者False的函数,第二个参数为可迭代对象
# 该函数把可迭代对象依次传入第一个函数,如果为True,则筛选
d=filter(lambda x:True if x % 3 == 0 else False,s)
print(list(d))
# [3, 6, 9, 12, 30]
map与lambda连用
# 第一个参数为函数,依次将后面的参数传给第一个函数,并执行函数
# 如果有多个参数则,依次将后面的对应传给参数
s=map(lambda x,y:x+y,range(10),range(10))
print(list(s))
# [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
ss=map(lambda x:x*x,range(10))
print(list(ss))
# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
reduce与lambda连用,与区别是:map返回的是Map对象,需要用List转化。
from functools import reduce
# 开始的时候将可迭代对象的第一个数和第二个数当成x和y
# 然后将第一次函数的执行结果当成x,然后再传入一个数当成y
# 再执行函数
s=reduce(lambda x,y:x+y,range(101))
print(s) # 相当于0+1+2+……+99+100
# 5050
32、yield和return的区别
你知道yield和return的区别
相同点:都是返回函数执行的结果
不同点:return 在返回结果后结束函数的运行,而yield 则是让函数变成一个生成器,生成器每次产生一个值(yield语句),函数被冻结,被唤醒后再产生一个值。
例子:求一组数的平方值
# return 实现:def squre(n):ls = [i*i for i in range(n)]return ls
for i in squre(5):print(i, end=' ')
结果为:0 1 4 9 16
# yield 实现:def squre(n):for i in range(n):yield i*ifor i in squre(5):print(i, end=' ')
结果为:0 1 4 9 16
yield和return也很好区别,return就返回值,结束函数,yield只是保存,不会结束函数。想下,在scrapy中,如果将yield改为retrun,那么爬一个就return,也就是爬取一个数据就停止了。
33、生成器
什么是生成器?
在Python中,一边循环一边计算的机制,称为生成器:generator。
因为列表所有数据都在内存中,如果有海量数据的话将会非常耗内存。
创建生成器,只要把一个列表生成式的[]改成(),就创建了一个generator:
>>> L = [x * x for x in range(10)]
>>> L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> g = (x * x for x in range(10))
>>> g
<generator object <genexpr> at 0x1022ef630>
还有一种方法就是在函数中使用yield关键字,那么这个函数就不再是一个普通函数,而是一个generator。调用函数就是创建了一个生成器(generator)对象。
def gen():yield 1# 返回一个对象,这个对象的值是1
def ret():return 1# 返回一个数字1
g = gen()
r = ret()
print(g,r)
print(next(g))#输出如下
<generator object gen at 0x0000020452E83840> 1
1
也是就函数中只要有yield,这个函数就会变成生成器。每次运行到yield的时候,函数会暂停,并且保存当前的运行状态,返回返回当前的数值,并在下一次执行next方法的时候,又从当前位置继续往下走。
34、enumerate
enumerate的意思是什么?如何使用。
在Python中,如果要在迭代列表的同时对迭代次数进行计数,可以使用 enumerate关键字。下面是没有使用enumerate实现的遍历。
Mylist = ['Runsen','为','offer', '而战']
for i in range(len(Mylist )):print(i, Mylist [i])# 输出如下
0 Runsen
1 为
2 offer
3 而战
enumerate()提供了强大的功能,例如,当您需要获取索引列表时,它会派上用场:
for i, j in enumerate(Mylist):print(i, j)# 输出如下
0 Runsen
1 为
2 offer
3 而战
35、面向对象的三大特性
简述面向对象的三大特性?
继承:继承就是继承的类直接拥有被继承类的属性而不需要在自己的类体中重新再写一遍,其中被继承的类叫做父类、基类,继承的类叫做派生类、子类。
封装: 封装就是把类中的属性和方法定义为私有的,方法就是在属性名或方法名前加双下划线,而一旦这样定义了属性或方法名后,python会自动将其转换为
_类名__属性名
(方法名)的格式,在类的内部调用还是用双下划线加属性名或方法名,在类的外部调用就要用_类名__属性名
(方法名)。父类的私有属性和方法,子类无法对其进行修改。多态:多态就是不同的对象可以调用相同的方法然后得到不同的结果,有点类似接口类的感觉,在python中处处体现着多态,比如不管你是列表还是字符串还是数字都可以使用+和*。
36、super
简述super关键字?
调用父类(超类)的一个方法,可以使用 super() 函数,super() 函数的一个常见用法是在 init() 方法中确保父类被正确的初始化了,具体的看我写的示例。
'''
@Author: Runsen
@微信公众号: Python之王
@博客: https://blog.csdn.net/weixin_44510615
@Date: 2020/8/29
'''# 创建一个A类
class A(object):def __init__(self):self.x = 0def A(self):print("This A func")class B(A):# 创建 B 继承 Adef __init__(self):super().__init__()self.y = 1def B(self):print("This B class ")print(self.x, self.y)super().A()if __name__ == '__main__':b = B()# 实例化 Bb.B()# 调用B# 输出如下
This B class
0 1
This A func
但是这里需要注意如果出现了"双下划线"的函数中的变量,只有类对象自己能访问,连子类对象也不能访问到这个数据。具体看我很早之前写的博客的示例。
class Father():__money = 1000 #私有变量是继承不了def __action(self): # 父类的私有方法money = 1000print('调用父类的方法')class Son(Father):def action(self):super()._Father__action()print(money) son=Son()
son.action() 调用父类的方法
name 'money' is not defined
这里的__action
由于是"双下划线“,因此money 私有变量是不能用supper继承不了,也就是不可以访问父类中的私有属性方法的变量money。
37、魔术方法
什么是魔术方法?
在Python中的面向对象中有很多魔术方法如:
__init__: 构造函数,在生成对象时调用
__del__: 析构函数,释放对象时使用
__str__: 使用print(对象)或者str(对象)的时候触发
__repr__: 在使用repr(对象)的时候触发,前提是没有__str__。如果有__str__,则没有用。
__setitem__ : 按照索引赋值:每当属性被赋值的时候都会调用该方法:self.__dict__[name] = value
__getitem__: 按照索引获取值:当访问不存在的属性时会调用该方法
_delitem__(self,name): 当删除属性时调用该方法
__len__: 获得长度
__cmp__: 比较运算
__call__: 函数调用
__add__: 加运算
__sub__: 减运算
__mul__: 乘运算
__div__: 除运算
__mod__: 求余运算
__pow__: 乘方
下面,我只介绍几个常见的。__init__
和__init__
在上面有谈到,这里不再述说。
1、__str__
:用于处理打印实例本身的时候的输出内容。如果没有覆写该函数,则默认输出一个对象名称和内存地址。
2、 __del__
: 析构方法,恰好在对象要被删除之前调用,目的是做一些释放销毁工作。
3、__call__
:其实就是调用这个对象的 对象名__call__()
方法,可以用来改变实例的内部成员的值。
下面看一个具体示例,区别上面的三种魔术方法。
'''
@Author: Runsen
@微信公众号: Python之王
@博客: https://blog.csdn.net/weixin_44510615
@Date: 2020/8/29
'''class Student(object):def __init__(self, name, age): # 重写了__init__方法self.name = nameself.age = agedef __str__(self):return "姓名:%s; 年龄:%d" % (self.name, self.age)def __del__(self):# 当对象被销毁时,会自动调用这个方法print('__del__ 方法被调用了')def __call__(self, a, b):self.name = aself.age = bprint('__call__ with ({}, {})'.format(self.name, self.age))def say(self):return "Runsen为Offer而战"s = Student('Runsen', 20)
print(s)
s("runsen",20)
print(s)
print(s.say())
del s# 输出如下
姓名:Runsen; 年龄:20
__call__ with (runsen, 20)
姓名:runsen; 年龄:20
Runsen为Offer而战
__del__ 方法被调用了
38、@staticmethod和@classmethod区别
说下@staticmethod和@classmethod的区别
其实@staticmethod和@classmethod都是用来声明静态方法的。只不过一个声明静态方法,一个声明类方法。
类方法:使用装饰器@classmethod。第一个参数为当前类的对象,通常为cls。实例对象和类对象都可以调用类方法。(不用声明对象就可以调用)
静态方法:使用装饰器@staticmethod。没有self和cls参数。方法体中不能使用类或者实例的任何属性和方法。实例对象和类对象都可以调用。
为了方便大家了解两者的差别,以下的示例代码将有助于发现其中的差别:
'''
@Author: Runsen
@微信公众号: 润森笔记
@博客: https://blog.csdn.net/weixin_44510615
@Date: 2020/8/30
'''
class A():@classmethoddef get_name(cls, name):print(cls) # <class '__main__.A'>print('my name is %s' % name)@staticmethoddef get_age(age):print(f'i am %s years old' % age)if __name__ == '__main__':A.get_name('Runsen') # my name is RunsenA.get_age(20) # i am 20 years old
@staticmethod 与 @classmethod在Python中称为 装饰器,用来修饰函数,相当于添加一个额外的功能,比如不再像普通函数那样进行实例化。通过使用装饰器可以让代码更加整洁,易读。用了修饰器之后,也可以进行实例化之后再调用,但是就显得多此一举了。
普通方法 | 类方法(@classmethod) | 实例方法(@staticmethod) | |
---|---|---|---|
a = A() | a.get_name() | a.get_name() | a.get_name() |
A | 不可用 | A.get_name() | A.get_name() |
39、@property
说下你对@property的理解
@property可以将一个方法的调用变成属性调用。举例说明:平时我们调用数据属性和方法,是这样的
class School():name = "家里蹲大学"def test(self):print("实例方法")@propertydef test_pro(self):print("静态属性")if __name__ == "__main__":s = School()print(s.name)s.test()#输出 # 家里蹲大学# 实例方法
如果我们想直接类似于数据属性一样的去调用方法
class School():name = "家里蹲大学"def test(self):print("实例方法")@propertydef test_pro(self):print("静态属性")if __name__ == "__main__":s = School()print(s.name)# 注意返回的函数 千万别加()s.test_pro#输出 # 家里蹲大学# 静态属性
40、内置类属性
说下你了解几个内置类属性?
__dict__
: 类的属性(包含一个字典,由类的数据属性组成)
__doc__
:类的文档字符串
__name__:
类名
__module__
: 类定义所在的模块
__bases__
: 类的所有父类构成元素(包含了一个由所有父类组成的元组)
如果你想跟博主建立亲密关系,可以关注博主,或者关注博主公众号“Python之王”,了解一个非本科程序员是如何成长的。
博主ID:润森,希望大家点赞、评论、收藏
2020 年最全 Python 面试题汇总 (二)相关推荐
- 2020 年最全 Python 面试题汇总 (四)
@Author:Runsen 文章目录 前言 61.01背包 62.完全背包 63.多重背包 64.多重背包的二进制 65.混合背包 66.Vivio面试真题 67.二维费用的背包问题 68.买卖股票 ...
- 2020 年最全 Python 面试题汇总 (五)
@Author:Runsen 文章目录 81.逆序对 82.手写一个栈 83.有效的扩号 84.扩号的生成 85.最长有效括号 86.比特位计数问题 87.判断给定的数是否为丑数 88.找出第 n 个 ...
- 2020 年最全 Python 面试题汇总 (一)
@Author:Runsen 大四刷题拼offer系列,不拼不行啊.我先刷下牛客网的Python的题目和知识点,适当的记录下自己做错的题目. 文章目录 1.Pythno逻辑运算符 2.求100亿有多少 ...
- python 面试题 2020_2020年最全python面试题
1.Python里面如何实现tuple和list的转换? 答:直接使用tuple和list函数就行了,type()可以判断对象的类型 2.什么是lambda函数?它有什么好处? 答:lambda 表达 ...
- python面试题及答案2020_2020年python面试题汇总(最新)
随着近些年机器学习.云计算等技术的发展,Python的职位需求越来越高.那么提前掌握最新的python面试题技巧,将有助于在求职中取得成功:同时gxlcms作为知名的编程学习网站,有着最新最热门的py ...
- 面试题汇总二 Java 多线程篇
前言 题目汇总来源 史上最全各类面试题汇总,没有之一,不接受反驳 面试题汇总一 Java 语言基础篇 面试题汇总二 Java 多线程篇 面试题汇总三 Java 集合篇 面试题汇总四 JVM 篇 面试题 ...
- 【专升本计算机】2021年甘肃省专升本计算机全真模拟试题(二)
[专升本计算机]2021年甘肃省专升本计算机全真模拟试题(一) [专升本计算机]2021年甘肃省专升本计算机全真模拟试题(二) [专升本计算机]2021年甘肃省专升本计算机全真模拟试题(三) [专升本 ...
- python面试题汇总(史上最全)
python面试题 ✅作者简介:大家好我是编程ID
- 赢在微点答案专区英语_免费领取 | 2020广东省中考全真模拟试题语文、数学、英语、化学、物理、历史、道德与法治、生物、地理共67套,可下载打印,...
2020年广东省中考命题科目.命题依据.考试方式和考试时长.各科卷面分值.预设难度和试卷结构. 点击图片可以放大 2020年中考渐渐临近,广大学子的备考复习也愈发紧张.这个时候,一套优秀的模拟试卷会给 ...
最新文章
- 网络工程师的“钱途”如何?
- python下载后如何使用-如何使用python下载文件?
- 字典树andXOR*
- 吴裕雄 Bootstrap 前端框架开发——Bootstrap 排版:移除默认的列表样式
- 什么是mysql的游标_MySQL游标概念是什么 MySQL游标概念与用法介绍
- leetcode 141. Linked List Cycle
- 大数据导论章节答案_智慧树大数据导论章节答案
- boost学习之BOOST_PP_SEQ_FOR_EACH_R
- gabor变换人脸识别的python实现,att_faces数据集平均识别率99%
- 均匀分布(uniform distribution)期望的最大似然估计(maximum likelihood estimation)
- 一维树桩数组区间更新、区间查询
- java怎么复制别人的数据库_数据库实现主从复制
- springboot2.x整合Email并利用AOP做一个项目异常通知功能
- [C#]写自己的类库
- OpenCV相机帧率低以及花屏问题
- 牛客SQL题解 - 查找employees表
- 从mysql中导出数据乱码_MySQL导入导出数据出现乱码的解决办法
- 40篇英语短文搞定高考3500个单词
- 爬虫---涨跌停股票池信息----(东方财富)
- 魔兽世界8.0哪个服务器稳定,魔兽世界活得最安逸的BOSS!8.0版本才拿到7.0服务器首杀!...
热门文章
- C/Cpp / extern 关键字
- opencv 眼睛识别 linux,用opencv测试人脸识别眨眼练习及问题
- Android APP层 ShellUtils
- java 革命_JAVA数据库连接池的革命 -- 从BoneCP到HikariCP(转)
- 3 左右_3万左右电动迷你小汽车,3万左右电动迷你小汽车车型推荐
- mysql授权用户主机_MySQL用户授权(GRANT)
- 个人永久性免费-Excel催化剂功能第28波-工作薄瘦身,安全地减少非必要冗余
- NumPy 矩阵库(Matrix)
- Android界面编程--使用活动条(ActionBar)--通过ActionBar菜单改变TextView的字体和颜色...
- [Baltic2009]Radio Transmission