如果C语言功底较深 可以发出更多 拷问灵魂深处的问题;
不是所有问题 这里都提供答案;这里提供的答案 也有可能有错或很片面;对于非超级熟手,这些问题可以只是线索,答案自己去搜 去试 去扩充
这里的问题 也不全是python的 也有些计算机基础的。
大部分都是网上摘的或书上的,按个人想法汇总了一下,不是纯原创。
part1:
- python中的变量是什么? 变量有类型吗? a = 9999 这个语句 做了几件事?
- ==和is的区别? 谁更快?
- #!开头的意义是什么 ? 所有文件都需要以#! 开头吗?
- python垃圾回收机制? _____为主,_____为辅。
- 如何实现引用计数?计数增长和减少的场景有哪些?引用计数的缺点?
- 分代回收 更优先处理_____对象;
- 标记-清除 发生在_____时;是为了解决_____问题
- 弱引用 主要是为了解决_____问题, 常用于_____场景
- python回收对象条件?
- del 删除的是对象吗?
- python内存机制?
- 小整数缓存机制?
- python有GIL 全局解释器锁, 为什么还会使用多线程?
- 强类型语言 和弱类型语言区别是? python是哪种?
- 动态语言 和静态语言 区别是?python是哪种?
- 解释型语言 和编译型语言区别?
- 是内存中一个对象的标签或引用; 变量没有类型,对象才有类型; 创建object9999, 创建name a, 将name a关联到object9999, 后续就可使用a来调用9999这个object
- ==比较值,调用魔术方法__eq__; is比较对象的id; is更快,不过我觉得这个意义不大,因为比较的东西/二者功能不一样;
- #!用于帮助内核找到python解释器, 只有直接执行的文件 才需要以#!开头
- 引用计数为主 标记-清除 分代收集为辅。
- 略.. 循环引用问题。
- 新对象 而不是老对象
- 没有空闲内存时 把所有可访问到的对象做标记,清扫一遍内存,把没标记的对象释放;循环引用问题
- 循环引用不能被垃圾回收;缓存
- 对象引用计数为0 或只存在对象的弱引用时
- del删除name 而不是object。可能引起垃圾回收。
- 金字塔型内存管理;-1 -2层是操作系统操作的;0层是C使用的malloc,free函数操作的;1层是python的接口函数PyMem_Malloc函数操作的;第3层是我们对python对象的操作
- [-5, 257]区间的整数 是全局已经创建好的init对象;不会每次调用都创建新的。
- python多线程机制 对CPU密集型代码 并不友好,这门语言就不是为这样的场景用的, 这样的场景就用C吧。对IO密集型代码友好。(python: 程序员的时间 比机器的时间重要)
- 略
- 略
- 略
part2:
- dict与 list的比较(空间方面)? set与列表元组的不同? set与dict的相通之处?
- 元组里放一列表, 这个列表的变化 会影响元组吗? 元组一定可哈希吗?
- aaa = (1, 2, 3) bbb = aaa[:] id(aaa) == id(bbb) 吗;如果aaa是list呢? # 写在一行是排版问题
- all, any, filter, map, reduce, zip用法?
- sort sorted , reverse revesed 区别?
- 容器序列和扁平序列的区别?
- 插入新元素时,想保持原有 有序序列的顺序, 用什么?
- 列表推导式, 字典推导式这些? 列表推导式的[],换成(),会有啥变化?
- 浅拷贝 深拷贝区别?
- 定义默认参数时,注意点?
- *args **kwargs的使用? python序列解包? 我当初是在 * ** 是如何打散时花了好一些功夫
- python参数传递模式?
7. bisect.insort
10. 默认参数需指向不变对象。
12. 共享传参,函数形参 获得实参中 引用的副本; 实参为不可变对象时, 就不能修改原始对象值;相当于传值;实参为可变对象时,可修改值,相当于传引用
part3:
- 单下划线 双下划线的区别? 我们应该尽量少用哪种? 哪种会有名字改编? 双下划线的意义是?
- 魔术方法,我们会调用吗? _______会调用。 实现魔术方法 有什么好处?
- 常见的==, > ,<, len(), str(), bool(),直接调用一个对象(), with xxx, for _ in xxx; xx in xx 背后的魔术方法是什么?
- __init__ __new__的区别 及调用时机
- 想要自定义 不可变容器类型,只需实现 哪两种魔术方法? 可变容器类型呢? 支持可迭代呢?
- __getattribute__, __getattr__, __getitem__, __get__ 区别是?
- 略 双下划 双下划 避免与子类定义的名称冲突
- no, 一般是python解释器来调用。 自定义类型 表现得像内置的类型一样, 让代码更优雅
- 略
- 略
- __len__, __getitem__; 增加__setitem__ __delitem__; 增加__iter__
- 访问任何属性,访问一个不存在的属性 按索引访问元素, 描述器使用(描述器展开又是一段了)
part4
- 闭包是什么? 自由变量是什么? nonlocal有什么用? 闭包存在__closure__属性中 ?
- 函数装饰器 和被装饰的函数 分别在什么时候执行?
- 装饰器的工作原理? 带参数的装饰器 返回的函数拥有闭包变量(the 参数)
- 这个网上能搜到很多相关的,但我觉得 流畅的pathon里面的定义 我最喜欢:闭包 是指延伸了作用域的函数,其中包含 函数定义体中引用,但不在函数定义体中定义的 非全局变量。 当然,理解的过程 还有很多方式,可以再多搜搜。 自由变量是指 未在本地作用域中绑定的变量 nonlocal声明的作用是 把变量标记为自由变量
- 导入模块时;调用时
- 略
part5
- 方法和函数的区别?
- 类代码中self的作用?
- 什么是动态绑定?
- 类中的默认方法, 用类名.方法时, 方法是_______的; 用_______时, 方法是绑定的;
- 类中的方法 默认是绑定给_______用的,绑定方法会自动传值(传_______)
- @classmethod 会改变: 绑定到_______身上 自动传值(传_______)
- @staticmethod 会_______绑定关系,将方法变成普通函数
- @classmethod 常在什么场景使用?
- @porperty 将_______ 转成 _______
- 普通字段attribute和属性property的区别?
- 略
- 略
- 略
- 未绑定; 实例.方法
- 实例 对象
- 类, 类
- 解除
- 定义其他的构造方法, 如参数不同等
- 函数调用 转成 属性访问
- (先去搜其他答案吧, 这里比喻上来说) attribute 有默认的getter/setter/deleter 触发内置的get/set/delete方法;property是特殊的attribute, 可以自定义 getter/setter/deleter,自己控制get/set/delete时触发的方法;或通过不定义 来禁止这些操作。
- super和父类的关联是? super(cls, inst)得到的是_____? (网上有很多,继承后的对象的实例化过程,其调用顺序 超出首次预期)
- 使用类名访问还是super访问好?
- 经典类和新式类的区别是?
- 虚拟子类是怎么创建的? 和直接继承的子类的区别
- 要创建一个class, 可以使用type()函数,其三个参数分别是什么? (了解如何去创建一个类)
- 创建一个 class Foo(Bar): pass时, python会如何处理__metaclass__属性?
- metaclass作用。 元类做的三件事是?
- 略
- 要么一直用super,要么一直用类名访问
- 略
- 略
- 略
- Foo中有__metaclass__吗? 如果没有 Bar中有吗? 如果有,通过__metaclass__里的__new__方法创建一个Foo 的类对象;再往上还会在模块中找,找不到则用type()来创建。
- 拦截类的创建 修改类 返回修改后的类
part6:
- yield用法
- yield作用
- yield from用法
- 生成器 可以用多次吗?
- 可迭代对象iterrable 迭代器iterator 生成器generator之间的关系是怎样?
- 我略你不能略
- 我觉得 就是可以保存它自己的工作和状态,但不需要写成类
- 略
- no,只能用一次
- 略
- 略一部分。 生成器是特殊的迭代器,不需要常规迭代器的__iter__()和__next__()方法,只需要yield关键字。
part7: 杂七杂八
- collection模块 / 几种时间类型及其转换 /
- 字典和json的区别?
- 能否对字典 同时进行迭代和修改? 往字典里插入数据时, 可能会改变顺序吗? 集合呢?
- eval()函数作用? 想要更安全的执行,有没有更好的方法?
- 访问对象属性三种方法
- 反射机制? python的反射机制
- 有一种减少内存的方法? 使用场景?
- 什么是序列化? pickle模块的dump load 可能用得多。
- python2 python3里str的区别 字节数组的作用?
- 尾调用是指? 尾递归优化 就在眼前了。 python不支持尾递归优化,递归是很好的理论方法,不是推荐的日常方法(机器学习中用到递归的场景 比传统软件多)
- 顺便可以了解下 函数式编程是指? python可以支持函数式编程。
- 猴子补丁 鸭子类型 白鹅类型 是指?
- 略
- 略
- 略
- 把字符串当python代码执行。 import ast; ast.literal_eval()
- ins.name ins.__dict__['name'] (启用了__slot__除外) getattr(ins, 'name')
- 略。python的反射机制在跟其他语言比轻便很多,不易察觉。getattr hasattr这些用起来很自然。流畅的python里面也有一些其他关于内省的模块使用介绍。promotions
- __slots__告诉解释器 不要使用字典 而是使用元组存储实例属性,这样可以节省空间。 在实例数以千计或更大时才推荐使用。 禁止用户新增实例属性 是这个功能的附作用,并不是为了这个原因而设计的。__slots__还有其他负作用,可以了解下
part8: 聊聊哈希
刚开始接触时,觉得一会与map相关,一会又与加密相关;看得有点晕
现在来说,一知道他是什么(特性是什么),二知道他的应用场景;其他的就可推导可理解了
一:hash是一个function,有以下特点:
1,输入相同时,输出肯定相同
2,不能求逆。即拿到输出,求不出输入
3,不同的输入, 输出可能一样
二:应用场景有两种:
1,一种物理存储结构, 哈希表的键的存储地址
2,密码学中的摘要和完整性较验。 (非加密)
对于场景一,
比如python中的字典的键,以及集合set,都使用了哈希算法 来获取元素的存储地址。
前面有个基本问题 list和dict的区别:dict耗空间,但查找很快。因为查询时能通过hash算法计算得到存储地址,直接去这个地址拿东西 当然快了。
散列表, 其实是一个稀疏数组(总有空白元素)。散列表里的单元叫表元。
python会设法保证 大概还有1/3的表元是空的。 前面有个问题:当往字典里插入数据时, 是否会改变顺序? 当空白的表元要小于约1/3时, python会把它复制到一个更大的空间去。所以可能会改变顺序的。
如果要把一个对象放入散列表中, 需要先计算这个元素的散列值。python使用hash()方法,其背后的魔术方法是__hash__()。 放入或查询这个元素时 计算出来的这个元素的散列值,直接用于得到这个元素的存储地址(直接作为地址 或有个映射关系)。
在查询元素时,如果计算出来的search_key, 与对应存储位置的实际found_key不匹配,这种情况叫哈希冲突/散列冲突。解决的办法有 开放定址法 再散列函数法等。
对于场景一来说,衡量一个hash函数好坏的标准 就是 计算简单快捷,结果分布均匀。注意计算快在分布均前面;如果有哈希冲突(这种机率相对不大), 再重新处理一下哈希冲突即可,可以接受的。但如果计算慢,就很要命了。
对于场景二,
先大体了解下密码学常要解决的三类问题
1,数据完整性问题: 防止恶意篡改数据。
2,数据的机密性问题: 防止数据被截获窃听等
3,身份验证问题: 防止数据交互双方身份被冒充问题。
后两类问题,分别 用对称加密 和非对称加密来解决, 第一类问题 用单向加密解决(只能加密不能解密) 哈希算法、散列算法,还叫摘要算法,就是这种场景下的摘要啦。
在用于网站银行密码较验时,抗碰撞抗篡改的要求性很高,计算速度的要求是在其次的。
此场景下与散列表,空间那些都没关系,只看这一次hash算法的结果。
完了可以再了解一下一致性哈希。
part9:
关于编码:内存中用什么编码 磁盘和网络中呢...
part10:
B树、B+树、AVL树、红黑树 区别是什么,适用场景分别是什么...
说到B树 B+树的应用索引, 除了关系型数据库中的索引的建立与使用,倒排索引 也需要了解下。
高手看完这篇文章,大概5分钟吧, 可怜鄙人用五笔还花了大几个钟头将近一天码这些字(当然也有边写边思考), 还有更多更多离散的天数和时间在这一天后面; xx好比针挑土,毁掉这一切似乎有点容易;但仍然只能继续挑土吧,换个勺容易点,哈哈