1. python是静态还是动态类型?是强类型还是弱类型?
    动态类型语言
    动态还是静态指的是编译期还是运行期确定类型 无类型声明
    强类型:js数字转字符串会自动转换是弱类型 不会自动转换
  2. python作为后端语言的优缺点?
    1.胶水语言,轮子多,应用广泛
    2.语言写起来快
    3.性能比较慢,python2 python3 不兼容
  3. 什么是鸭子类型?
    关注对象的行为【方法】,而不是类型
    比如file StringIO socket 对象都支持read/write方法(file like object)
    再比如定义了_iter_魔术方法的对象可以用for迭代
  4. 什么是monkey patch?那些地方用到了?自己如何实现?
    所谓的monkey patch就是运行时类型替换
    比如gevent库需要修改内置的socket
    from gevent import monkey;
    monkey.patch_socket()
    (把内置阻塞的库替换成非阻塞的socket)
  5. 什么是自省?
    运行是判断一个对象的类型的能力。
    python一切皆对象
  6. is 和 == 区别?
    is:比较的是两个对象的id值是否相等,也就是比较两个对象是否是同一个实例,是否指向同一个地址。
    ==:比较的是两个对象的内容是否相等,默认会调用对象的__equal__()方法

python所做的性能优化:
1.小整数对象[-5,256]是全局解释器范围内被重复使用,永远不会被GC回收。
2.同一个代码块中的不可变对象,只要是值相等的,就不会重复创建新的对象。
3.字符串中单个20以内他们的内存地址一样,单个21以上,内存地址不一样

  1. 什么是列表和字典推导?
    一种快速生成list/dict/set的方式
  2. 什么是生成器,迭代器?
    1.生成器定义
    在Python中,一边循环一边计算的机制,称为生 成器:generator。
    生成器仅仅保存了一套生成数值的算法,并且没有让这个算法现在就开始执行,而是我什么时候调它,它什么时候开始计算一个新的值,并给你返回。
1)生成器(generator)能够迭代的关键是它有一个next()方法,

  工作原理就是通过重复调用next()方法,直到捕获一个异常。

(2)带有 yield 的函数不再是一个普通函数,而是一个生成器generator。

  可用next()调用生成器对象来取值。next 两种方式 t.__next__()  |  next(t)。

  可用for 循环获取返回值(每执行一次,取生成器里面一个值)

  (基本上不会用next()来获取下一个返回值,而是直接使用for循环来迭代)。

(3)yield相当于 return 返回一个值,并且记住这个返回的位置,下次迭代时,代码从yield的下一条语句开始执行。

(4).send() 和next()一样,都能让生成器继续往下走一步(下次遇到yield停),但send()能传一个值,这个值作为yield表达式整体的结果

  ——换句话说,就是send可以强行修改上一个yield表达式值。比如函数中有一个yield赋值,a = yield 5,第一次迭代到这里会返回5,a还没有赋值。第二次迭代时,使用.send(10),那么,就是强行修改yield 5表达式的值为10,本来是5的,那么a=10

我又想要得到庞大的数据,又想让它占用空间少,那就用生成器。

迭代原理
面试题:for循环的原理是什么?
答:1. 获取迭代器
 2. 循环获取下一个元素
 3. 遇到异常停止迭代

可以被for的条件是什么?
答:能被for的对象必须具备__iter__方法
答:能被for的对象是可迭代对象

2.迭代器是一个可以记住遍历的位置的对象。
迭代器有两个基本的方法:iter() 和 next()。
  1. python2/3差异常考题
    1.python3中print为函数,python2中print为关键字。
    2.编码问题 python3不再有Unicode对象,默认str就是unicode
    3.除法返回浮点数
    4.string 字母 大小写字符串
    string.letters:包含所有字母(大写或小写)的字符串
    Python 3.0中,string.ascii_letters.
    5.python 2.7 cmp(x,y)函数用于比较2个对象,如果 x < y 返回 -1, 如果 x == y 返回 0, 如果 x > y 返回 1
    python3.7 cmp()已经不存在了,如果你需要实现比较功能,需要引入 operator 模块,适合任何对象
    6.python3可以加类型注解,帮助IDE实现类型检查
    7.优化的super()方便直接调用父类函数
    8.高级解包操作:
    9.参数传递:
  2. Python新增
    yield from 链接子生成器
    asyncio内置库
    新增库enum
  3. python3改进
    生成的pyc文件统一放到_pychche_
    一些内置库的修改 urllib selector
    dict性能优化
  4. python如何传递参数?
    对象引用的方式传递
    默认参数只计算一次
    不可变对象:bool,int,float,tuple,str
    可变对象:list set dict
  5. 函数传递中*args,**kwargs含义是什么?
    *args 被打包成tuple
    **kwargs 字典
  6. 什么时候需要捕获处理异常呢?看python内置异常的类型。
    1.网络请求(超时,连接错误)
    2.资源访问(权限问题)
    3.代码逻辑异常
    finally:无论异常有没有发送都会执行的代码,一般处理资源的关闭和释放
  7. 什么是Cpython GIL
    GIL:global interpreter lock
    Cpython使用简单的锁机制避免多个线程同时执行字节码。
    限制了程序的多核执行
    同一个时间只能有一个线程执行字节码
    CPU密集程序难以利用多核
    IO期间会释放GIL,对I/O密集程序影响不大
    CPU:cpu密集可以使用多进程+进程池
    IO:IO密集使用多协程、线程
  8. 如何剖析程序性能
    使用内置的profile/cprofile等工具
  9. 服务端性能优化措施
    1.数据结构与算法优化
    2.数据库层:添加索引批量操作减少IO
    3.缓存:使用内存数据库redis
    4.异步框架:asyncio
    5.并发:gevent/多线程
  10. 什么是生成器?
    可以生成值的函数
    当一个函数里有了yield关键字就成了生成器
    生成器可以挂起执行并且报存当前执行的状态

19.什么是单元测试?
单元测试相关库:nose/pytest
如何设计测试用例:
1.正常值功能测试
2.边界值(比如最大,最小,最左最右)
3.异常值 (比如None,空值,非法值)

  1. Python深拷贝和浅拷贝?
    深拷贝:又开辟了一块空间,复制过来
    浅拷贝:指向的是同一个对象
  2. 如何捕获异常,常用的异常机制有哪些?

如果我们没有对异常进行任何预防,那么在程序执行的过程中发生异常,就会中断程序,调用python默认的异常处理器,并在终端输出异常信息。

try…except…finally语句:当try语句执行时发生异常,回到try语句层,寻找后面是否有except语句。找到except语句后,会调用这个自定义的异常处理器。except将异常处理完毕后,程序继续往下执行。finally语句表示,无论异常发生与否,finally中的语句都要执行。

assert语句:判断assert后面紧跟的语句是True还是False,如果是True则继续执行print,如果是False则中断程序,调用默认的异常处理器,同时输出assert语句逗号后面的提示信息。

with语句:如果with语句或语句块中发生异常,会调用默认的异常处理器处理,但文件还是会正常关闭。

  1. 函数装饰器有什么作用(常考)
    装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。有了装饰器,就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。
    闭包的实现

Python中的装饰器是通过闭包实现的,简单地讲,闭包就是引用了外部变量的内部函数,而闭包的实现正是利用了以上函数特性,下面我们来看看闭包是如何实现的:

def outer(x):

def inner(): # 函数嵌套
     return x # 跨域访问,引用了外部变量x

return inner # 函数作为返回值

2.简述Python的作用域以及Python搜索变量的顺序

Python作用域简单说就是一个变量的命名空间。代码中变量被赋值的位置,就决定了哪些范围的对象可以访问这个变量,这个范围就是变量的作用域。在Python中,只有模块(module),类(class)以及函数(def、lambda)才会引入新的作用域。Python的变量名解析机制也称为 LEGB 法则:本地作用域(Local)→当前作用域被嵌入的本地作用域(Enclosing locals)→全局/模块作用域(Global)→内置作用域(Built-in)

  1. 新式类和旧式类的区别,如何确保使用的类是新式类

为了统一类(class)和类型(type),python在2.2版本引进来新式类。在2.1版本中,类和类型是不同的。

为了确保使用的是新式类,有以下方法:

放在类模块代码的最前面 metaclass = type
从内建类object直接或者间接地继承
在python3版本中,默认所有的类都是新式类。

  1. 简述__new__和__init__的区别

创建一个新实例时调用__new__,初始化一个实例时用__init__,这是它们最本质的区别。

new方法会返回所构造的对象,init则不会.

new函数必须以cls作为第一个参数,而init则以self作为其第一个参数.

基本思路是先按需分配,等到没有空闲内存的时候从寄存器和程序栈上的引用出发,遍历以对象为节点、以引用为边构成的图,把所有可以访问到的对象打上标记,然后清扫一遍内存空间,把所有没标记的对象释放。

以下情况是导致引用计数加一的情况:

对象被创建,例如a=2
对象被引用,b=a
对象被作为参数,传入到一个函数中
对象作为一个元素,存储在容器中
下面的情况则会导致引用计数减一:

对象别名被显示销毁 del
对象别名被赋予新的对象
一个对象离开他的作用域
对象所在的容器被销毁或者是从容器中删除对象

限制python可见显卡 python 限制内存_生成器


分代回收

分代回收是一种以空间换时间的操作方式,Python将内存根据对象的存活时间划分为不同的集合,每个集合称为一个代,Python将内存分为了3“代”,分别为年轻代(第0代)、中年代(第1代)、老年代(第2代),他们对应的是3个链表,它们的垃圾收集频率与对象的存活时间的增大而减小。新创建的对象都会分配在年轻代,年轻代链表的总数达到上限时,Python垃圾收集机制就会被触发,把那些可以被回收的对象回收掉,而那些不会回收的对象就会被移到中年代去,依此类推,老年代中的对象是存活时间最久的对象,甚至是存活于整个系统的生命周期内。同时,分代回收是建立在标记清除技术基础之上。分代回收同样作为Python的辅助垃圾收集技术处理那些容器对象

  • Python中的@property有什么作用?如何实现成员变量的只读属性?

@property装饰器就是负责把一个方法变成属性调用,通常用在属性的get方法和set方法,通过设置@property可以实现实例成员变量的直接访问,又保留了参数的检查。另外通过设置get方法而不定义set方法可以实现成员变量的只读属性。

  • *args and **kwargs

*args代表位置参数,它会接收任意多个参数并把这些参数作为元组传递给函数。**kwargs代表的关键字参数,允许你使用没有事先定义的参数名,另外,位置参数一定要放在关键字参数的前面。

  • 有用过with statement吗?它的好处是什么?具体如何实现?

with语句适用于对资源进行访问的场合,确保不管使用过程中是否发生异常都会执行必要的“清理”操作,释放资源,比如文件使用后自动关闭、线程中锁的自动获取和释放等。

  • List item