http://t.csdnimg.cn/Luguc
http://t.csdnimg.cn/Luguc有完整资源的面经,不收费用自取,点个赞吧。
1.xrange 和 range 的区别?
xrange用法与range完全相同,所不同的是生成的不是一个数组,而是一个生成器。
要生成很大的数字序列的时候,用xrange会比range性能优很多,因为不需要一上来就开辟一块很大的内存空间,这两个基本上都是在循环的时候用。
2.什么是 PEP8?
PEP是 Python Enhancement Proposal 的缩写,翻译过来就是 Python增强建议书
简单说就是一种编码规范,是为了让代码“更好看”,更容易被阅读
具体可参考:
https://www.python.org/dev/peps/pep-0008/
3.了解 Python 之禅吗?
import this
4.了解 docstring 吗?
Python有一个很奇妙的特性,称为 文档字符串 ,它通常被简称为 docstrings 。DocStrings是一个重要的工具,由于它帮助你的程序文档更加简单易懂,你应该尽量使用它。你甚至可以在程序运行的时候,从函数恢复文档字符串。
使用魔法方法'__doc__'可以打印docstring的内容
5.如何给变量加注释?
参数注释:以冒号(:)标记
返回值注释:以 -> 标记
示例:
def add(x:int, y:int) -> int:
return x + y
6.列举 Python 中的基本数据类型。
Python3 中有六个标准的数据类型:
Number(数字)
String(字符串)
List(列表)
Tuple(元组)
Set(集合)
Dictionary(字典)
Python3 的六个标准数据类型中:
不可变数据(3 个):Number(数字)、String(字符串)、Tuple(元组);
可变数据(3 个):List(列表)、Dictionary(字典)、Set(集合)。
7.将 "hello world" 转换为首字母大写 "Hello World"。
z = 'hello world'
z.title()
8.如何检测字符串中只含有数字?
# 分为两种情况
# 1.不包含正负号 +-
a = '32323'
a.isdigit()
9.将字符串 "ilovechina" 进行反转。
s = 'ilovechina'
s = s[::-1]
10.Python 中的字符串格式化方式你知道哪些?
# Python3.6之后的版本提供了三种字符串格式化的方式
# 1. %s占位符
def foo(name):
return 'hello %s' % name
# 2. format()
def foo(name):
return 'hello {}'.format(name)
# f-string
def foo(name):
return f'hello {name}'
11.有一个字符串开头和末尾都有空格,比如 " adabdw "。要求写一个函数把这个字符串的前后空格都去掉。
s = " adabdw "
s.strip()
12.一个编码为 GBK 的字符串 S,要将其转成 UTF-8 编码的字符串,应如何操作?
s.encode('utf-8')
13.怎样将字符串转换为小写?
b = 'HHH'
b.lower()
14.已知 AList = [1,2,3,1,2],对 AList 列表元素去重,写出具体过程。
a_list = [1,2,3,1,2]
ss = set(a_list)
15.给定两个 list,A 和 B,找出相同元素和不同元素。
list_a = [1,2,3,4,5,6]
list_b = [2,3,6]
set1 = set(list_a)
set2 = set(list_b)
# 相同元素
print(set1&set2)
# 不同元素
print(set1^set2)
16.用一行代码展开该列表 [[1,2],[3,4],[5,6]],得出[1,2,3,4,5,6]。
mm = [[1,2],[3,4],[5,6]]
[j for a in mm for j in a]
17.合并列表 [1,5,7,9] 和 [2,2,6,8]。
a = [1,5,7,9]
b = [2,2,6,8]
# 方法1
a.extend(b)
# 方法2
a[0:0] = b
# 方法3
a += b
18.如何打乱一个列表的元素?
import random
a = [1,5,7,9]
random.shuffle(a)
19.字典操作中 del 和 pop 有什么区别?
del 操作删除键值对,不返回值;
pop 操作删除键值对的同时,返回键所对应的值。
20.将如下字典按照年龄排序。
d1 = [
{'name':'alice', 'age':38},
{'name':'bob', 'age':18},
{'name':'Carl', 'age':28},
]
sorted(d1,key=lambda x:x['age'])
21.请合并下面两个字典 a = {"A":1,"B":2},b = {"C":3,"D":4}。
# python3合并字典有三种方式
# 1.
a = {'a':1,'b':2}
b = {'c':3,'d':4}
c = {}
c.update(a)
c.update(b)
# 2.
c = dict(a,**b)
# 3.
c = {**a,**b} # 官方推荐这种方式
22.如何把 元组 ("a","b") 和 元组(1,2),变为字典{"a":1,"b":2}?
a = ('a','b')
b = (1,2)
z=zip(a,b)
c = dict(z)
23.我们知道对于列表可以使用切片操作进行部分元素的选择,那么如何对生成器类型的对象实现相同的功能呢?
使用自带的itertools库进行实现,具体实现方式 itertools.islice(生成器对象,起始位置,结束位置),即可实现切片功能。
24.在读文件操作的时候会使用 read、readline 或者 readlines,简述它们各自的作用。
read将整个文本都读取为一个字符串,占用内存大,readline读取为一个生成器,支持遍历和迭代,占用空间小。readlines将文本读取为列表,占用空间大
25.json 序列化时,默认遇到中文会转换成 unicode,如果想要保留中文怎么办?
使用json.dumps函数时,添加参数ensure_ascii=False,如果想显示的更美观,可以添加indent=2参数,会在每个key值前添加两个空格。
26.Python 字典和 json 字符串相互转化方法。
json.dumps() 将Python中的对象转换为JSON中的字符串对象
json.loads() 将JSON中的字符串对象转换为Python中的对象
27.函数装饰器有什么作用?请列举说明。
函数装饰器可以在不修改原函数的条件下,为原函数添加额外的功能,例如记录日志,运行性能,缓存等
以记录函数运行时间为例,实现一个装饰器
import time
def time_it(func):
def wrapper(func):
start_time = time.time()
res = func()
end_time = time.time()
return start_time - end_time
return wrapper
28.简述 Python 垃圾回收机制。
引用计数机制:
python里每一个东西都是对象,它们的核心就是一个结构体:PyObject
typedef struct_object {
int ob_refcnt;
struct_typeobject *ob_type;
} PyObject;
PyObject是每个对象必有的内容,其中ob_refcnt就是做为引用计数。当一个对象有新的引用时,它的ob_refcnt就会增加,当引用它的对象被删除,它的ob_refcnt就会减少
#define Py_INCREF(op) ((op)->ob_refcnt++) //增加计数
#define Py_DECREF(op) \ //减少计数
if (--(op)->ob_refcnt != 0) \
; \
else \
__Py_Dealloc((PyObject *)(op))
当引用计数为0时,该对象生命就结束了。
引用计数机制的优点:
简单
实时性:一旦没有引用,内存就直接释放了。不用像其他机制等到特定时机。实时性还带来一个好处:处理回收内存的时间分摊到了平时
29.魔法函数 __call__怎么使用?
class Bar:
def __call__(self, *args, **kwargs):
print('i am instance method')
b = Bar() # 实例化
b() # 实例对象b 可以作为函数调用 等同于b.__call__ 使用
# OUT: i am instance method
# 带参数的类装饰器
class Bar:
def __init__(self, p1):
self.p1 = p1
def __call__(self, func):
def wrapper():
print("Starting", func.__name__)
print("p1=", self.p1)
func()
print("Ending", func.__name__)
return wrapper
@Bar("foo bar")
def hello():
print("Hello")
30.如何判断一个对象是函数还是方法?
判断对象是函数或方法应该使用type(obj)
31.简述 @classmethod 和 @staticmethod 用法和区别。
一般来说,要使用某个类的方法,需要先实例化一个对象再调用方法。
而使用@staticmethod或@classmethod,就可以不需要实例化,直接类名.方法名()来调用。
这有利于组织代码,把某些应该属于某个类的函数给放到那个类里去,同时有利于命名空间的整洁。
既然@staticmethod和@classmethod都可以直接类名.方法名()来调用,那他们有什么区别呢
从它们的使用上来看,
@staticmethod不需要表示自身对象的self和自身类的cls参数,就跟使用函数一样。
@classmethod也不需要self参数,但第一个参数需要是表示自身类的cls参数。
如果在@staticmethod中要调用到这个类的一些属性方法,只能直接类名.属性名或类名.方法名。
而@classmethod因为持有cls参数,可以来调用类的属性,类的方法,实例化对象等,避免硬编码
class A(object):
bar = 1
def foo(self):
print 'foo'
@staticmethod
def static_foo():
print 'static_foo'
print A.bar
@classmethod
def class_foo(cls):
print 'class_foo'
print cls.bar
cls().foo()
A.static_foo()
A.class_foo()
32.Python 中的接口如何实现?
#抽象类加抽象方法就等于面向对象编程中的接口
from abc import ABCMeta,abstractmethod
class interface(object):
__metaclass__ = ABCMeta #指定这是一个抽象类
@abstractmethod #抽象方法
def Lee(self):
pass
def Marlon(self):
pass
class RelalizeInterfaceLee(interface):#必须实现interface中的所有函数,否则会编译错误
def __init__(self):
print '这是接口interface的实现'
def Lee(self):
print '实现Lee功能'
def Marlon(self):
pass
33.请列举你知道的 Python 的魔法方法及用途。
1. __call__:允许一个类的实例像函数一样被调用。实质上说,这意味着 x() 与 x._call_() 是相同的
2.__init__:显示初始化属性
3.__str__,__repr__,定义类的时候,重写这两个方法可以让类更清晰
再就是__setattr__,__getattr__,__delattr__等等
34.简述 any() 和 all() 方法。
#any(x)判断x对象是否为空对象,如果都为空、0、false,则返回false,如果不都为空、0、false,则返回true
#all(x)如果all(x)参数x对象的所有元素不为0、''、False或者x为空对象,则返回True,否则返回False
35.什么是猴子补丁?
猴子补丁是一个概念,不是python中发明的,其他动态语言也有这么个概念。 《松本行弘的程序世界》这本书,里面专门有一章讲了猴子补丁的设计,所谓的猴子补丁的含义是指在动态语言中,不去改变源码而对功能进行追加和变更
36.当退出 Python 时是否释放所有内存分配?
答案是否定的。那些具有对象循环引用或者全局命名空间引用的变量,在 Python 退出是往往不会被释放
另外不会释放 C 库保留的部分内容。
37.Python 中的 is 和 == 有什么区别?
is比较的是两个对象的id值是否相等,也就是比较两个对象是否为同一个实例对象,是否指向同一个内存地址。
==比较的是两个对象的内容是否相等,默认会调用对象的__eq__()方法。
38.Python 中的作用域有哪些?
L (Local) 局部作用域
E (Enclosing) 闭包函数外的函数中
G (Global) 全局作用域
B (Built-in) 内建作用域
39.了解 enumerate 吗?
# 遍历列表时候,携带索引index
a = ['a','b','c']
for index,item in enumerate(a):
print(index,item)
40.请对 Python 中的异常处理写一个简单的应用场景。
class NameTooShortError(ValueError):
pass
def validate(name):
if len(name) < 10:
raise NameTooShortError(name)
# 使用自定义异常类,使得发生异常时的错误更容易排查
41.Python 中递归的最大次数是多少?如何突破?
python解释器限制最大的递归深度是999,可以通过
import sys
sys.setrecursionlimit(10000) # set the maximum depth as 10000
重新设置最大递归深度
42.简述 isinstance 的作用以及应用场景。
来判断一个对象是否是一个已知的类型
举个栗子:
p= 'sfa'
isinstance(p,str)
True
43.lambda 表达式格式以及应用场景。
d = {'a':2,'b':1,'c':3,'d':'4'}
sorted(d,key=lambda x :x[1])
# 将字典d按照值排序
44.dir() 是用来干什么的?
dir() 函数不带参数时,返回当前范围内的变量、方法和定义的类型列表;带参数时,返回参数的属性、方法列表。如果参数包含方法__dir__(),该方法将被调用。如果参数不包含__dir__(),该方法将最大限度地收集参数信息。
45.列举 5 个 Python 中的异常类型以及其含义。
1. ArithmeticError 此基类用于派生针对各种算术类错误而引发的内置异常: OverflowError, ZeroDivisionError, FloatingPointError
2. BufferError 当与 缓冲区 相关的操作无法执行时将被引发。
3. LookupError 此基类用于派生当映射或序列所使用的键或索引无效时引发的异常: IndexError, KeyError。 这可以通过 codecs.lookup() 来直接引发
4. ImportError 当 import 语句尝试加载模块遇到麻烦时将被引发。 并且当 from ... import 中的 "from list" 存在无法找到的名称时也会被引发
5. IndexError 当序列抽取超出范围时将被引发。 (切片索引会被静默截短到允许的范围;如果指定索引不是整数则 TypeError 会被引发
46.浅拷贝(copy) 和深拷贝(deepcopy) 的区别是什么?
copy 即所谓的浅拷贝,赋值的时候非递归地复制子对象的引用;
deepcopy 即所谓的深拷贝,赋值的时候递归复制子对象。
47.请阐述代码中经常遇到的 *args, **kwargs 的含义及用法。
这两个是python中的可变参数。*args表示任何多个位置参数,它是一个tuple;**kwargs表示关键字参数,它是一个dict。并且同时使用*args和**kwargs时,必须*args参数列要在**kwargs前
48.Python 中会有函数或成员变量包含单下划线前缀和结尾,或双下划线前缀结尾,它们的区别是什么?
前置单下划线_var:命名约定,用来表示该名称仅在内部使用。一般对 Python 解释器没 有特殊含义(通配符导入除外),只能作为对程序员的提示。
后置单下划线 var_:命名约定,用于避免与 Python 关键字发生命名冲突。
前置双下划线__var:在类环境中使用时会触发名称改写,对 Python 解释器有特殊含义。
前后双下划线__var__:表示由 Python 语言定义的特殊方法。在自定义的属性中要避免
使用这种命名方式。
49.举例 sort 和 sorted 的区别。
sort()与sorted()的不同在于,sort是在原位重新排列列表,而sorted()是产生一个新的列表
50.pprint 模块是干什么的?
print()和pprint()都是python的打印模块,功能基本一样,唯一的区别就是pprint()模块打印出来的数据结构更加完整,每行为一个数据结构,更加方便阅读打印输出结果。特别是对于特别长的数据打印,print()输出结果都在一行,不方便查看,而pprint()采用分行打印输出,所以对于数据结构比较复杂、数据长度较长的数据,适合采用pprint()打印方式