python 面试题

python语法基础

python基础语法

1 、迭代器和生成器区别 ?

答:( 1)迭代器是一个更抽象的概念,任何对如果它类有 next 方法和 iter 方法返回自己本身 。对于 strings、 list、 dict、 tuple 等这类容器对象,使用 for 循环遍历是很方便的。在后台 for 语句 对容器象调用 iter()函数,iter()是 python 的内置函数。iter() 会返回一个定义 next()方法的迭代器对象,它在容器中逐个访问容 器内元素, next()也是 python 的内置函数。在没有后续元素时, next()会 抛出一个 StopIter 异常
( 2)生成器( Generator)是创建迭代器的简单而强大工具。 它们写起来就像是正规的函数,只在需要返回据时候使用 yield 语 句。每次 next()被调用,生成器会返回它脱离的位置,记忆语句最 后一次执行和所有数据。
区别:生成器能做到迭代的所有事 ,而且因为自动创建了 iter()和 next()方法 ,生成器显得特别简洁 ,而且生成器也是 高效的 ,使用生成器表 达式取代列解析可以同时节省 内存。除了 创建和保程序状态的自动方法,当发生器终结时 ,还会自动抛出 StopIteration 异常。

2 、线程、进程、协程

[1] 进程是具有一定独立功能的程序关于某个数据集合上的一次运 行活动,进程是系统进行资源分配和调度的一个独立单位。每个进程 都有自己的独立内存空间,不同进程通过进程间通信来通信。由于进 程比较重量,占据独立的内存,所以上下文进程间的切换开销(栈、 寄存器、虚拟内存、文件句柄等)比较大,但相对比较稳定安全。
[2] 线程是进程的一个实体,是 CPU 调度和分派的基本单位,它 是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存 器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的 全部资源。线程间通信主要通过共享内存,上下文切换很快,资源开 销较少,但相比进程不够稳定容易丢失数据。
[3]协程是一种用户态的轻量级线程,协程的调度完全由用户控制。 协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下 文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上 下文和栈,直接操作栈则基本没有内核切换的开销,可以不加锁的访 问全局变量,所以上下文的切换非常快。

3 . 装饰器

装饰器是一个很著名的设计模式,经常被用于有切面需求的场景, 较为经典的有插入日志、性能测试、事务处理等。装饰器是解决这类 问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数 功能本身无关的雷同代码并继续重用。概括的讲,装饰器的作用就是 为已经存在的对象添加额外的功能

装饰器(decorator)里引入通用功能处理:

引入日志
函数执行时间统计
执行函数前预备处理
执行函数后清理功能
权限校验等场景
缓存

from time import ctime, sleep
def timefun(func):
def wrappedfunc():
print("%s called at %s"%(func.name,
ctime()))
return func()
return wrappedfunc
@timefun
def foo():
print(“I am foo”)
foo()
sleep(2)
foo()

4 、 谈谈你对同步异步阻塞非阻塞理解

所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该 调用就不返回。按照这个定义,其实绝大多数函数都是同步调用。

异步的概念和同步相对。当一个异步过程调用发出后,调用者不能 立刻得到结果。实际处理这个调用的部件在完成后,通过状态、通知 和回调来通知调用者。

阻塞调用是指调用结果返回之前,当前线程会被挂起。函数只有在 得到结果之后才会返回

一个函数 recv 则是一个阻塞调用的例子。当 socket 工作在阻塞模式 的时候,如果没有数据的情况下调用该函数,则当前线程就会被挂起, 直到有数据为止。

非阻塞和阻塞的概念相对应,指在不能立刻得到结果之前,该函数 不会阻塞当前线程,而会立刻返回。

5 、GIL 对多线程的影响?

GIL 的全称是 Global Interpreter Lock(全局解释器锁),来源 是 python 设计之初的考虑,为了数据安全所做的决定。每个 CPU 在 同一时间只能执行一个线程(在单核 CPU 下的多线程其实都只是并发, 不是并行,并发和并行从宏观上来讲都是同时处理多路请求的概念。 但并发和并行又有区别,并行是指两个或者多个事件在同一时刻发生; 而并发是指两个或多个事件在同一时间间隔内发生。)

在 Python 多线程下,每个线程的执行方式:
1、获取 GIL
2、执行代码直到 sleep 或者是 python 虚拟机将其挂起。
3、释放 GIL
可见,某个线程想要执行,必须先拿到 GIL,我们可以把 GIL 看 作是“通行证”,并且在一个 python 进程中,GIL 只有一个。拿不 到通行证的线程,就不允许进入 CPU 执行。

6、python2 和 python3的区别
1.性能 Py3.0 运行 pystone benchmark 的速度比 Py2.5 慢 30%。Guido 认为 Py3.0 有极大的优化空间,在字符串和整形操作上可以取得很好的优化结果。 Py3.1 性能比 Py2.5 慢 15%,还有很大的提升空间。
2.编码 Py3.X 源码文件默认使用 utf-8 编码,这就使得以下代码是合法的: >>> 中国 = ‘china’ >>>print(中国) china
3. 语法
  • 1)去除了<>,全部改用!=
  • 2)去除``,全部改用 repr()
  • 3)关键词加入 as 和 with,还有 True,False,None
  • 4)整型除法返回浮点数,要得到整型结果,请使用//
  • 5)加入 nonlocal 语句。使用 noclocal x 可以直接指派外围(非全局)变量
  • 6)去除 print 语句,加入 print()函数实现相同的功能。同样的还有 exec 语句, 已经改为 exec()函数
  • 7)改变了顺序操作符的行为,例如 x<y,当 x 和 y 类型不匹配时抛出 TypeError 而不是返 回随即的 bool 值
  • 8)输入函数改变了,删除了 raw_input,用 input 代替: 2.X:guess = int(raw_input('Enter an integer : '))# 读取键盘输入的方法 3.X:guess = int(input('Enter an integer : '))
  • 9)去除元组参数解包。不能 def(a, (b, c)):pass 这样定义函数了
  • 10)新式的 8 进制字变量,相应地修改了 oct()函数。
  • 11)增加了 2 进制字面量和 bin()函数
  • 12)扩展的可迭代解包。在 Py3.X 里,a,b,*rest=seq 和 *rest,a=seq 都是合法的, 只要求两点:rest 是 list 对象和 seq 是可迭代的。
  • 13)新的 super(),可以不再给 super()传参数,
  • 14)新的 metaclass 语法: class Foo(*bases, **kwds): pass
  • 15)支持 class decorator。用法与函数 decorator 一样:
4. 字符串和字节串
  • 1)现在字符串只有 str 一种类型,但它跟 2.x 版本的 unicode 几乎一样。
  • 2)关于字节串,请参阅“数据类型”的第 2 条目
5.数据类型
  • 1)Py3.X 去除了 long 类型,现在只有一种整型——int,但它的行为就像 2.X 版本的 long
  • 2)新增了 bytes 类型,对应于 2.X 版本的八位串,定义一个 bytes 字面量的方法如下: str 对象和 bytes 对象可以使用.encode() (str-> bytes)or .decode()(bytes-> str)方法相互转化。
  • 3)dict 的.keys()、.items 和.values()方法返回迭代器,而之前的 iterkeys()等函数都被废弃。同时去掉的还有 dict.has_key(),用 in 替代它吧
6.面向对象
  • 1)引入抽象基类(Abstraact Base Classes,ABCs)。
  • 2)容器类和迭代器类被 ABCs 化,所以 cellections 模块里的类型比 Py2.5 多了很多。

import collections
print(’\n’.join(dir(collections)))
Callable
Container
Hashable
ItemsView
Iterable
Iterator
KeysView
Mapping
MappingView
MutableMapping
MutableSequence
MutableSet
Na
medTuple
Sequence
Set
Sized
ValuesView
all builtins do c file name _abcoll _itemgetter _sys defaultdict deque 另 外,数值类型也被 ABCs 化。关于这两点,请参阅 PEP 3119 和 PEP 3141。

  • 3)迭代器的 next()方法改名为__next__(),并增加内置函数 next(),用以调用迭代器的__next__()方法
  • 4)增加了@abstractmethod 和 @abstractproperty 两个 decorator,编写抽象方法(属性)更加方便。
7.异常
  • 1)所有异常都从 BaseException 继承,并删除了 StardardError
  • 2)去除了异常类的序列行为和.message 属性
  • 3)用 raise Exception(args)代替 raise Exception, args 语法
  • 4)捕获异常的语法改变,引入了 as 关键字来标识异常实例
  • 5)异常链,因为__context__在 3.0a1 版本中没有实现
8.模块变动
  • 1)移除了 cPickle 模块,可以使用 pickle 模块代替。最终我们将会有一个透明高效的模块。
  • 2)移除了 imageop 模块
  • 3)移除了 audiodev, Bastion, bsddb185, exceptions, linuxaudiodev, md5, MimeWriter, mimify, popen2, rexec, sets, sha, stringold, strop, sunaudiodev, timing 和 xmllib 模块
  • 4)移除了 bsddb 模块(单独发布,可以从http://www.jcea.es/programacion/pybsddb.htm 获 取)
  • 5)移除了 new 模块
  • 6)os.tmpnam()和 os.tmpfile()函数被移动到 tmpfile 模块下
  • 7)tokenize 模块现在使用 bytes 工作。主要的入口点不再是 generate_tokens,而是 tokenize.tokenize()
9.其它
  • 1)xrange() 改名为 range(),要想使用 range()获得一个 list,必须显式调用: >>> list(range(10)) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
  • 2)bytes 对象不能 hash,也不支持 b.lower()、b.strip()和 b.split()方法,但对于后两者 可以使用 b.strip(b’ \n\t\r \f’)和 b.split(b’ ‘)来达到相同目的
  • 3) zip()、 map()和 filter()都返回迭代器。而 apply()、callable()、 coerce()、execfile()、 reduce() 和 reload ()函数都被去除了现在可以使用 hasattr()来替换 callable(). hasattr()的语法如: hasattr(string, ‘name’)
  • 4)string.letters 和相关的.lowercase 和.uppercase 被去除,请改用 string.ascii_letters等
  • 5)如果 x < y 的不能比较,抛出 TypeError 异常。2.x 版本是返回伪随机布尔值的
  • 6)__getslice__系列成员被废弃。a[i:j]根据上下文转换为 a.getitem(slice(I, j))或__setitem__和 __delitem__调用
  • 7)file 类被废弃
7、 什么是线程安全?

线程安全是在多线程的环境下,能够保证多个线程同时执行时程序依旧运行正 确, 而且要保证对于共享的数据可以由多个线程存取,但是同一时刻只能有一个线
程进行存取。多线程环境下解决资源竞争问题的办法是加锁来保证存取操作的唯一
性。

linux

1 、 十个常用的 linux 命令?

Ls,help,cd ,more,clear,mkdir,pwd,rm,grep,find,mv,su,date…

2、find 和 grep?

grep 命令是一种强大的文本搜索工具,grep 搜索内容串可以是正则表达式, 允许对文本文件进行模式查找。如果找到匹配模式, grep 打印包含模式的所有行。

find 通常用来在特定的目录下搜索符合条件的文件,也可以用来搜索特定用户 属主的文件。

3、什么是面向对象编程?

面向对象编程是一种解决软件复用的设计和编程方法。 这种方法把软件系统中 相近相似的操作逻辑和操作 应用数据、状态,以类的型式描述出来,以对象实例的形式 在软件系统中复用,以达到提高软件开发效率的作用。

4、线上服务可能因为种种原因导致挂掉怎么办?

Linux 下的后台进程管理利器 supervisor
每次文件修改后在linux执行:service supervisord restart

5、 python 的多进程与多线程的运行机制是什么?有什么区别? 分别在什么情况下用?

运行机制:进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位线程是进程的一个实体,是 CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如果制造数据的速度时快时慢,缓冲区的好处就体现出来了。当数据制造快的时候,消
费者来不及处理,未处理的数据可以暂时存在缓冲区中。程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.

区别:

多进程稳定性好,一个子进程崩溃了,不会影响主进程以及其余进程。但是缺点是创建进程的代价非常大,因为操作系统要给每个进程分配固定的资源,并且,操作系统对进程的总数会有一定的限制,若进程过多,操作系统调度都会存在问题,会造成假死状态。

多线程效率较高一些,但是致命的缺点是任何一个线程崩溃都可能造成整个进程的崩溃,因为它们共享了进程的内存资源池。

使用情况:
如果代码是IO密集型的,多线程。
如果代码是CPU 密集型的,多进程是更好的选择——特别是所使用的机器是多核或多CPU的。

6 、 如何提高 Python 的运行效率,请说出不少于 2 种提高运行效 率的方法。

使用生成器

关键代码使用外部功能包:Cython、Pylnlne、PyPy、Pyrex

针对循环的优化——尽量避免在循环中访问变量的属性;

7、请至少列举5个PEP8规范(越多越好)
  • 1、缩进,4个空格的缩进(编译器都可以完成此功能),不适用Tab,更不能混合使用Tab和空格
  • 2、每行最大长度为79,换行可以使用反斜杠。最好使用圆括号,换行点再操作符的后边敲回车。
  • 3、不要再一句import中多个库。比如import os,sys(不推荐)
  • 4、模块命名尽量短小,使用全部小写的方式,可以使用下划线。
  • 5、包命名尽量短小,使用全部小写的方式。不可以使用下划线
  • 6、类的命名使用CapWords的方式,模块内部使用的类采用–CapWords的方式。
  • 7、函数命名使用全部小写的方式,可以使用下划线。
  • 8、异常命名使用CapWords+Error后缀的方式。
  • 9、常量命名使用全部大写的方式,可以使用下划线。
  • 10、类的属性(方法和变量)命名使用全部小写的方式,可以使用下划线。
  • 11、类方法第一个参数必须是self,而静态方法第一个参数必须是cls。

数据库

web

前端

后端

django

flask

爬虫

1、 常见的反爬虫和应对方法?
  • 1).通过 Headers 反爬虫
    从用户请求的 Headers 反爬虫是最常见的反爬虫策略。很多网站都 会对 Headers 的 User-Agent 进行检测, 还有一部分网站会对 Referer 进行检测(一些资源网站的防盗链就是检测 Referer)。如果遇到了 这类反爬虫机制,可以直接在爬虫中添加 Headers,将浏览器的 User-Agent 复制到爬虫的 Headers 中;或者将 Referer 值修改为目标网站域名。对于检测 Headers 的反爬虫,在爬虫中修改或者添加 Headers 就能很好的绕过。
  • 2).基于用户行为反爬虫
    还有一部分网站是通过检测用户行为,例如同一 IP 短时间内多次 访问同一页面,或者同一账户短时间内多次进行相同操作。
    大多数网站都是前一种情况,对于这种情况,使用 IP 代理就可以 解决。可以专门写一个爬虫,爬取网上公开的代理 ip,检测后全部 保存起来。这样的代理 ip 爬虫经常会用到,最好自己准备一个。有 了大量代理 ip 后可以每请求几次更换一个 ip,这在 requests 或者 urllib2 中很容易做到,这样就能很容易的绕过第一种反爬虫。
    对于第二种情况,可以在每次请求后随机间隔几秒再进行下一次请 求。有些有逻辑漏洞的网站,可以通过请求几次,退出登录,重新登 录,继续请求来绕过同一账号短时间内不能多次进行相同请求的限制。
  • 3).动态页面的反爬虫
    上述的几种情况大多都是出现在静态页面,还有一部分网站,我们 需要爬取的数据是通过ajax请求得到,或者通过JavaScript生成的。 首先用 Fiddler 对网络请求进行分析。如果能够找到 ajax 请求,也 能分析出具体的参数和响应的具体含义,我们就能采用上面的方法, 直接利用 requests 或者 urllib2 模拟 ajax 请求,对响应的 json 进 行分析得到需要的数据。
    能够直接模拟 ajax 请求获取数据固然是极好的,但是有些网站把 ajax 请求的所有参数全部加密了。我们根本没办法构造自己所需要 的数据的请求。这种情况下就用 selenium+phantomJS,调用浏览器 内核,并利用 phantomJS 执行 js 来模拟人为操作以及触发页面中的 js 脚本。从填写表单到点击按钮再到滚动页面,全部都可以模拟, 不考虑具体的请求和响应过程,只是完完整整的把人浏览页面获取数 据的过程模拟一遍。
    用这套框架几乎能绕过大多数的反爬虫,因为它不是在伪装成浏览 器来获取数据(上述的通过添加 Headers 一定程度上就是为了伪装 成浏览器),它本身就是浏览器,phantomJS 就是一个没有界面的浏 览器,只是操控这个浏览器的不是人。利 selenium+phantomJS 能干 很多事情,例如识别点触式(12306)或者滑动式的验证码,对页面 表单进行暴力破解等。
2、 分布式爬虫主要解决什么问题?
  • 1)ip
  • 2)带宽
  • 3)cpu
  • 4)io
3、 简单说一下你对 scrapy 的了解?

scrapy是一个快速(fast)、高层次(high-level)的基于 python 的 web 爬虫构架。 用来下载、并解析 web 页面, 其 parse->yield item->pipeline 流程是所有爬虫的固有 模式。构造形式主要分

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值