Fork me on GitHub

python面试题收集

学习别人的,渐渐成为自己的

搜集一些别人的面试题,为自己的面试做些准备。以后逐渐添加面试题

nginx与uwsgi是如何通信的?

我们知道,nginx把浏览器等发过来的请求通过proxy_pass或者uwsgi_pass转发给上游的web application进行处理,然后把处理的结果发送给浏览器。uwsgi_pass命令的处理函数为ngx_http_uwsgi_handler,也就是说,当有请求到达配置uwsgi_pass的location时,会调用ngx_http_uwsgi_handler方法,而该方法是整个uwsgi事件处理的入口方法。下面来看该方法:

1
2
3
4
5
6
7
8
9
10
11
12
static ngx_int_t ngx_http_uwsgi_handler(ngx_http_request_t *r) { 
ngx_http_upstream_t *u;
ngx_http_uwsgi_loc_conf_t *uwcf;
uwcf = ngx_http_get_module_loc_conf(r, ngx_http_uwsgi_module);
u = r->upstream;
……
u->create_request = ngx_http_uwsgi_create_request;//根据wsgi协议创建请求包体
u->process_header = ngx_http_uwsgi_process_status_line;//根据wsgi协议解析uwsgi发送来的头部
……
rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);//从浏览器读取body数据
……
}

nginx与uwsgi是多线程还是多进程 ?

  • uwsgi是用c语言写的一个webserver,可以启动多个进程,进程里面可以启动多个线程来服务。进程分为主进程和worker进程,worker里面可以有多个线程。
  • Nginx会按需同时运行多个进程:一个主进程(master)和几个工作进程(worker),配置了缓存时还会有缓存加载器进程(cache loader)和缓存管理器进程(cache manager)等。Nginx主要通过“共享内存”的机制实现进程间通信。主进程以root用户身份运行,而worker、cache loader和cache manager均应以非特权用户身份运行。
  • 在工作方式上,Nginx分为单工作进程和多工作进程两种模式。在单工作进程模式下,除主进程外,还有一个工作进程,工作进程是单线程的;在多工作进程模式下,每个工作进程包含多个线程。Nginx默认为单工作进程模式。

连表查询

假设有如下两张表:

表A

ID Name
1 Tiim
2 Jimmy
3 John
4 Tom

表B

ID Hobby
1 Football
2 Basketball
2 Tennis
4 Soccer

内联结

1
Select A.Name B.Hobby from A, B where A.id = B.id

这是隐式的内联结,查询的结果是:

Name Hobby
Tiim Football
Jimmy Basketball
Jimmy Tennis
Tom Soccer

它的作用和:

1
select A.Name,B.Hobby from A INNER join B on A.id = B.id

外左联结

1
select A.Name,B.Hobby from A left join B on A.id = B.id

这样查询得到的结果将会是保留所有A表中联结字段的记录,若无与其相对应的B表中的字段记录则留空,结果如下:

Name Hobby
Tiim Football
Jimmy Basketball,Tennis
Jhon
Tom Soccer

所以从上面结果看出,因为A表中的John记录的ID没有在B表中有对应ID,因此为空,但Name栏仍有John记录。

右外联结

1
select A.Name.N.Hobby from A right join B on A/id = B.id

结果将会是:

Name Hobby
Tiim Football
Jimmy Basketball
Jimmy Tennis
Tom Soccer

ORM中的连表查询

Django中

1
Entry.objects.filter(blog__name='Beatles Blog')

Flask中

1
Entry.query.join(Blog,Blog.id == Entry.blog_id).filter(Blog.name = 'Beatles Blog')

写一个单例模式

  • 使用继承方式:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class Singleton:
    _instance = None
    def __new__(cls, *args, **kwargs):
    if cls._instance is None:
    cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
    return cls._instance
    class SingleSpam(Singleton):
    TEST = 'testing'
    s1 = SingleSpam()
    print(s1.TEST, ' ', id(s1))
    s2 = SingleSpam()
    print(s2.TEST, ' ', id(s2))
  • 使用装饰器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    from functools import wraps
    def singleton(cls):
    instances = {}
    @wraps(cls)
    def _instance(*args, **kwargs):
    if cls not in instances:
    instances[cls] = cls(*args, **kwargs)
    return instances[cls]
    return _instance
    @singleton
    class SingleSpam(object):
    TEST = 'testing'
    s1 = SingleSpam()
    print(s1.TEST, ' ', id(s1))
    s2 = SingleSpam()
    print(s2.TEST, ' ', id(s2))
  • 使用元类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class Singleton(type):
    _instance = None
    def __call__(cls, *args, **kwargs):
    if cls._instance is None:
    cls._instance = super(Singleton, cls).__call__(*args, **kwargs)
    return cls._instance
    class SingleSpam(metaclass=Singleton):
    TEST = 'testing'
    s1 = SingleSpam()
    print(s1.TEST, ' ', id(s1))
    s2 = SingleSpam()
    print(s2.TEST, ' ', id(s2))

请你说出几种常见的反爬策略?

  • 检查user-agent
  • 加防盗链
  • 使用验证码
  • 监控ip
  • 监控session
  • 将请求的参数加密

请说一下线程与进程的区别

进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。

1) 简而言之,一个程序至少有一个进程,一个进程至少有一个线程.

线程的划分尺度小于进程,使得多线程程序的并发性高。

另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。

线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。

从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。

下面的程序 会是什么情况?答案会报参数错误。

1
2
3
4
5
6
7
8
9
class A(object):
def run(self,a):
return a

class B(A):
def run(self,a,b):
return b

B().run(1)

因为B重写了run方法,所以run应该有两个参数

ORM常用筛选条件

Django

大于、大于等于
1
2
3
4
5
__gt  大于
__gte 大于等于

User.objects.filter(age__gt=10) // 查询年龄大于10岁的用户
User.objects.filter(age__gte=10) // 查询年龄大于等于10岁的用户
小于、小于等于
1
2
3
4
5
__lt  小于
__lte 小于等于

User.objects.filter(age__lt=10) // 查询年龄小于10岁的用户
User.objects.filter(age__lte=10) // 查询年龄小于等于10岁的用户
in
1
2
3
__in
查询年龄在某一范围的用户
User.objects.filter(age__in=[10, 20, 30])
like
1
2
3
4
__exact        精确等于 like 'aaa'
__iexact 精确等于 忽略大小写 ilike 'aaa'
__contains 包含 like '%aaa%'
__icontains 包含 忽略大小写 ilike '%aaa%',但是对于sqlite来说,contains的作用效果等同于icontains。
is null / is not null
1
2
3
4
__isnull  判空

User.objects.filter(username__isnull=True) // 查询用户名为空的用户
User.objects.filter(username__isnull=False) // 查询用户名不为空的用户
不等于/不包含于
1
2
User.objects.filter().excute(age=10)    // 查询年龄不为10的用户
User.objects.filter().excute(age__in=[10, 20]) // 查询年龄不为在 [10, 20] 的用户

Flask

大于、大于等于
1
2
3

User.query.filter(User.age > 10) // 查询年龄大于10岁的用户
User.query.filter(User.age >= 10) // 查询年龄大于等于10岁的用户
小于、小于等于
1
2
3

User.query.filter(User.age < 10) // 查询年龄小于10岁的用户
User.query.filter(User.age <= 10) // 查询年龄小于等于10岁的用户
in
1
2
查询年龄在某一范围的用户
User.query.filter(User.age.in_([10, 20, 30]))
like
1
User.query.filter(User.name.like('%wu%'))
is null / is not null
1
2
3

User.query.filter(User.username = None ) // 查询用户名为空的用户
User.query.filter(User.username != None ) // 查询用户名不为空的用户
不等于/不包含于
1
2
User.query.filter(~(User.age=10))    // 查询年龄不为10的用户
User.objects.filter(~(User.age.in_([10,20]))) // 查询年龄不为在 [10, 20] 的用户

put与post的区别?

POST
用于提交请求,可以更新或者创建资源,是非幂等的
举个例子,在我们的支付系统中,一个api的功能是创建收款金额二维码,它和金额相关,每个用户可以有多个二维码,如果连续调用则会创建新的二维码,这个时候就用POST


PUT
用于向指定的URI传送更新资源,是幂等的
还是那个例子,用户的账户二维码只和用户关联,而且是一一对应的关系,此时这个api就可以用PUT,因为每次调用它,都将刷新用户账户二维码

http有几种方式?

OPTIONS:返回服务器针对特定资源所支持的HTTP请求方法。也可以利用向Web服务器发送的请求来测试服务器的功能性。

HEAD:向服务器索要与GET请求相一致的响应,只不过响应体将不会被返回。这一方法可以在不必传输整个响应内容的情况下,就可以获取包含在响应消息头中的元信息。

GET:向特定的资源发出请求。

POST:向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的创建和/或已有资源的修改。

PUT:向指定资源位置上传其最新内容。

DELETE:请求服务器删除Request-URI所标识的资源。

TRACE:回显服务器收到的请求,主要用于测试或诊断。

CONNECT:HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。

解释下面linux命令的含义

cat: 常用来显示文件内容,或者将几个文件连接起来显示,或者从标准输入读取内容并显示,它常与重定向符号配合使用。
rsync: 更快更好地远程拷贝文件
rm: 删除文件或目录
grep: 在一个或多个文件中搜索字符串模板
tcpdump: 是一个运行在命令行下的抓包工具
strace: 常用来跟踪进程执行时的系统调用和所接收的信号
chmod: 修改文件权限
less: 对文件或其它输出进行分页显示的工具,可向前向后翻页,而more只能向后翻页
netstat: 用于列出系统上所有的网络套接字连接情况,包括 tcp, udp 以及 unix 套接字,另外它还能列出处于监听状态(即等待接入请求)的套接字
top: 实时显示系统中各个进程的资源占用状况
telnet: 远程登录
scp: linux系统下基于ssh登陆进行安全的远程文件拷贝命令

用最简洁的代码,将元素类型为int的list中大于100的元素输出到另一个list,并将后一个list中的元素从大到小排序

1
2
3
4
5
6
import random

lstA = random.sample(range(1000), 100)
lstB = list(filter(lambda x: x > 100, lstA))
lstB.sort(reverse=True)
print(lstB)

给两个排好序的数组,找出重复的元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import random

lstA = [1,5,8,14,16,25,28,39]# random.sample(range(1 << 15), 1011)
lstB = [2,3,6,8,12,13,16,21,25,28]# random.sample(range(1 << 15), 2030)
# lstA.sort()
# lstB.sort()

lenA = len(lstA)
lenB = len(lstB)
common = []
i, j = 0, 0

while i < lenA and j < lenB:
if lstA[i] < lstB[j]:
i += 1
elif lstA[i] > lstB[j]:
j += 1
else:
common.append(lstA[i])
i += 1
j += 1

print(common)

给一个字符串,输出它的所有排列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def arrangement(lst, length, index=0):
if index == length - 1:
print(''.join(lst))
return
for pos in range(index, length):
lst[pos], lst[index] = lst[index], lst[pos]
arrangement(lst, length, index + 1)
lst[pos], lst[index] = lst[index], lst[pos]


def start_arrangement(iterable):
lst = list(iterable)
arrangement(lst, len(lst))


start_arrangement('abcd')

Python基础题

写了一些题目。但是deploy时hexo报错,网上说是hexo模板的问题,有些特殊符号没正确处理。但是尝试了没解决
…后面找到原因再补充…

Python进阶题

-------------本文结束感谢您的阅读-------------

本文标题:python面试题收集

文章作者:Longofo

发布时间:2018年05月01日 - 12:05

最后更新:2018年07月10日 - 09:07

原始链接:http://longofo.cc/python面试题收集.html

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

请我吃包辣条也好啊!!!
分享到: