Python篇:(coding之外基础篇)
详细可参考https://github.com/kenwoodjw/python_interview_question
数据结构:
1 Tuple和list区别:
- 共同点:都是序列,都可以存储任何数据类型,可以通过索引访问
- 不同点:tuple不可变不可复制(immutable),list可变(mutable)。list不能当作字典的key, 而tuple可以(The most important limitation for a
dict
is that the keys must be hashable/immutable)。
元组通常由不同的数据,而列表是相同类型的数据队列。元组表示的是结构,而列表表示的是顺序。
2 mutable有list,dict,set,int,double....immutable有string,number,tuple. mutable的对象被更改时传递地址,不新增内存;immutable的对象被更改时开辟新内存将原地址的值复制并修改。
3 字典:哈希表结构,key是unique的,访问时间复杂度为O(1); The most important limitation for adictis that the keys must be hashable/immutable。 字典推导式:d = {key:value for (key,value) in iterable};按key/value排序sorted(d.items(),key=lambda x:x[0]);
4 list comprehension(列表推导式/列表解析):[a for a in range(0, 100) if a%2](找100以内偶数)。
反转list: list[::-1]。
超出index有时不会产生IndexError错误,返回[].
找相同元素/删除重复元素:set(list)
删除元素:1 倒序遍历(因为元素总是前移)2 filter b = filter(lambda x: x>5,a) 3 列表解析
备注:
hashable:value始终不变且可以与其他object比较,所有python内置不可变对象都是hashable的,可变对象都不是hashable的。(reference:An object is hashable if it has a hash value which never changes during its lifetime (it needs a __hash__() method) and can be compared to other objects (it needs an __eq__() or __cmp__() method). Hashable objects which compare equal must have the same hash value.Hashability makes an object usable as a dictionary key and a set member, because these data structures use the hash value internally.All of Python’s immutable built-in objects are hashable, while no mutable containers (such as lists or dictionaries) are. Objects which are instances of user-defined classes are hashable by default; they all compare unequal, and their hash value is their id().)
对象:
1 mutable/immutable
不可变对象,该对象所指向的内存中的值不能被改变。当改变某个变量时候,由于其所指的值不能被改变,相当于把原来的值复制一份后再改变,这会开辟一个新的地址,变量再指向这个新的地址。
可变对象,该对象所指向的内存中的值可以被改变。变量(准确的说是引用)改变后,实际上其所指的值直接发生改变,并没有发生复制行为,也没有开辟出新的地址,通俗点说就是原地改变。
2 class 的重载
__init__
构造器,当一个实例被创建的时候初始化的方法,但是它并不是实例化调用的第一个方法。__new__
才是实例化对象调用的第一个方法,它只取下cls参数,并把其他参数传给__init___
.___new__
很少使用,但是也有它适合的场景,尤其是当类继承自一个像元祖或者字符串这样不经常改变的类型的时候。__call__
让一个类的实例像函数一样被调用__getitem__
定义获取容器中指定元素的行为,相当于self[key]__getattr__
定义当用户试图访问一个不存在属性的时候的行为。__setattr__
定义当一个属性被设置的时候的行为__getattribute___
定义当一个属性被访问的时候的行为__str__
, __repr__
- object representation (casting to string, printing)__len__
, __next__
... - generators__enter__
, __exit__
- context managers__eq__
, __lt__
, __gt__
- operator overloading
3 class中的只读属性
参考:https://blog.csdn.net/weixin_35653315/article/details/78077253
- 用私有属性+@property
定义只读属性, 需要预先定义好属性名, 然后实现对应的getter方法.
函数:
1 参数传递方式:
Python的参数传递有:位置参数、默认参数、可变参数、关键字参数。
不可变参数用值传递:像整数和字符串这样的不可变对象,是通过拷贝进行传递的,因为你无论如何都不可能在原处改变不可变对象。
可变参数是引用传递:比如像列表,字典这样的对象是通过引用传递、和C语言里面的用指针传递数组很相似,可变对象能在函数内部改变。
2 global全局变量:global 变量;python3 新增nonlocal(函数嵌套)
example:https://blog.csdn.net/zmq570235977/article/details/48209851
3 缺省函数
*args是不定长参数,它可以表示输入参数是不确定的,可以是任意多个。
**kwargs是关键字参数,赋值的时候是以键值对的方式,参数可以是任意多对在定义函数的时候
不确定会有多少参数会传入时,就可以使用两个参数
def my_func(*args, **kwargs):args
is atuple
with all positional arguments passed to the function andkwargs
is adict
with all keyword arguments. They can be named anything as long as the unpack operators*
and**
are used.*
unpacks atuple
and**
unpacks adict
.
4 装饰器(decorators)
Python中的装饰器用于修改或注入函数或类中的代码。使用装饰器,可以包装类或函数方法调用,以便可以在执行原始代码之前或之后执行一段代码。 装饰器可用于检查权限,修改或跟踪传递给方法的参数,将调用记录到特定方法等。
装饰器本质上是一个callable object ,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。
example:https://www.runoob.com/w3cnote/python-func-decorators.html
5 yield Generator and iterator
yield就是保存当前程序执行状态。你用for循环的时候,每次取一个元素的时候就会计算一次。用yield的函数叫generator,和iterator一样,它的好处是不用一次计算所有元素,而是用一次算一次,可以节省很多空间,generator每次计算需要上一次计算结果,所以用yield,否则一return,上次计算结果就没了
生成器(Generator),只是在需要返回数据的时候使用yield语句。每次next()被调用时,生成器会返回它脱离的位置(它记忆语句最后一次执行的位置和所有的数据值)
example: X= (i for i in range(10)), X是genertaor
迭代器是遵循迭代协议的对象。用户可以使用 iter() 以从任何序列得到迭代器(如 list, tuple, dictionary, set 等)。另一个方法则是创建一个另一种形式的迭代器 —— generator 。要获取下一个元素,则使用成员函数 next()(Python 2)或函数 next() function (Python 3) 。当没有元素时,则引发 StopIteration 此例外。若要实现自己的迭代器,则只要实现 next()(Python 2)或__next__
()( Python 3)
内存管理与回收:
1 内存管理机制: 引用计数、垃圾回收、内存池
参考:https://foofish.net/python-gc.html
- 引用计数是一种非常高效的内存管理手段,当一个Python对象被引用时其引用计数增加1,当其不再被一个变量引用时则计数减1,当引用计数等于0时对象被删除。弱引用不会增加引用
- 垃圾回收:引用计数,标记清除,分代回收
- 内存池:金字塔型进行分配,第3层:最上层,用户对Python对象的直接操作;第1层和第2层:内存池,有Python的接口函数PyMem_Malloc实现-----若请求分配的内存在1~256字节之间就使用内存池管理系统进行分配,调用malloc函数分配内存,但是每次只会分配一块大小为256K的大块内存,不会调用free函数释放内存,将该内存块留在内存池中以便下次使用。;第0层:大内存-----若请求分配的内存大于256K,malloc函数分配内存,free函数释放内存。第-1,-2层:操作系统进行操作
如何优化:
- 手动垃圾回收
- 调高垃圾回收阈值
- 避免循环引用
参考:http://kkpattern.github.io/2015/06/20/python-memory-optimization-zh.html
2 内存泄漏
内存泄漏指由于疏忽或错误造成程序未能释放已经不再使用的内存。内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,导致在释放该段内存之前就失去了对该段内存的控制,从而造成了内存的浪费。
有__del__()
函数的对象间的循环引用是导致内存泄露的主凶。不使用一个对象时使用: del object 来删除一个对象的引用计数就可以有效防止内存泄露问题。
通过Python扩展模块gc 来查看不能回收的对象的详细信息。
可以通过 sys.getrefcount(obj) 来获取对象的引用计数,并根据返回值是否为0来判断是否内存泄露
C++ 篇(To be continued)