25. 数据库联接操作,左连接,右链接,全链接的操作以及区别(手写 SQL 语句)
left join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录 (通俗点讲就是,左边的表是老大,要显示全部内容,右边的表是小弟,只有跟老大相同的东西才显示出来,不相同的就是null);
right join(右联接) 返回包括右表中的所有记录和左表中联结字段相等的记录(通俗点讲就是,右边的表是老大,要显示全部内容,左边的表是小弟,只有跟老大相同的东西才显示出来,不相同的就是null;
inner join(等值连接|全连接也叫内连接) 只返回两个表中联结字段相等的行(左右两边势均力敌,不相上下。两边都不想妥协,所以只有共同的东西才显示出来);
26. 数据库的三大范式的理解。
三大范式只是一般设计数据库的基本理念,可以建立冗余较小、结构合理的数据库。如果有特殊情况,当然要特殊对待,数据库设计最重要的是看需求跟性能,需求>性能>表结构。所以不能一味的去追求范式建立数据库。
27.什么是SQL注入?
SQL是操作数据库数据的结构化查询语言,网页的应用数据和后台数据库中的数据进行交互时会采用SQL。而SQL注入是将Web页面的原URL、表单域或数据包输入的参数,修改拼接成SQL语句,传递给Web服务器,进而传给数据库服务器以执行数据库命令。如Web应用程序的开发人员对用户所输入的数据或cookie等内容不进行过滤或验证(即存在注入点)就直接传输给数据库,就可能导致拼接的SQL被执行,获取对数据库的信息以及提权,发生SQL注入攻击。
其特点如下:
1)、广泛性
任何一个基于SQL语言的数据库都可能被攻击,很多开发人员在编写Web应用程序时未对从输入参数、Web表单、cookie等接受到的值进行规范性验证和检测,通常会出现SQL注入漏洞。
2)、隐蔽性
SQL注入语句一般都嵌入在普通的HTTP请求中,很难与正常语句区分开,所以当前许多防火墙都无法识别予以警告,而且SQL注入变种极多,攻击者可以调整攻击的参数,所以使用传统的方法防御SQL注入效果非常不理想。
3)、危害大
攻击者通过SQL注入获取到服务器的库名、表名、字段名,从而获取到整个服务器中的数据,对网站用户的数据安全有极大的威胁。攻击者也可以通过获取到的数据,得到后台管理员的密码,然后对网页页面进行恶意篡改。这样不仅对数据库信息安全造成严重威胁,对整个数据库系统安全也影响重大。
4)、操作方便
互联网上有很多SQL注入工具,简单易学,攻击过程简单,不需要专业知识也能自如运用。
28. Python的底层实现,用到的排序函数(手写冒泡算法)
答:共有八种
- 选择排序-简单选择排序
- 选择排序-堆排序
- 插入排序-直接插入排序
- 插入排序-希尔排序
- 交换排序-快速排序
- 交换排序-冒泡排序
- 归并排序
- 桶排序/基数排序
冒泡排序:
冒泡排序是最常见到的排序算法,也是大学学习时遇到的第一种排序算法,它的实现思想是:相邻的两个元素进行比较,然后把较大的元素放到后面(正向排序),在一轮比较完后最大的元素就放在了最后一个位置,因为这一点像鱼儿在水中吐的气泡在上升的过程中不断变大,所以得名冒泡排序。在该排序算法中,要遍历n-1轮,每一轮都要比较数组中的元素,所以时间复杂度是
O(n2)。冒泡排序具体实现的代码如下:
def bubble_sort(alist):
length = len(alist)
for i in range(length - 1):
# i表示比较多少轮
for j in range(length - i - 1):
# j表示每轮比较的元素的范围,因为每比较一轮就会排序好一个元素的位置,
# 所以在下一轮比较的时候就少比较了一个元素,所以要减去i
if alist[j] > alist[j + 1]:
alist[j], alist[j + 1] = alist[j + 1], alist[j]
原文链接:https://blog.csdn.net/sensev/article/details/80908776
9. 解释一下 python 中的 GIL 是什么
1. gil是什么:全局解析器锁
2. gil的作用:单核的情况下可以实现多任务(并发)
3. gil的解决方案:
多进程vs多线程:最流行的方法是应用多进程方法,在这个方法中你使用多个进程而不是多个线程。每一个Python进程都有自己的Python解释器和内存空间,因此GIL不会成为问题。
30. GIL是单线程的,那么python中多线程的实现有什么用。
- 进程之间不能共享内存,但线程之间共享内存非常容易。
- 操作系统在创建进程时,需要为该进程重新分配系统资源,但创建线程的代价则小得多。因此,使用多线程来实现多任务并发执行比使用多进程的效率高。
- Python 语言内置了多线程功能支持,而不是单纯地作为底层操作系统的调度方式,从而简化了 Python 的多线程编程。
31. 对于多线程,我是怎么去使用的,如果要我去设计一个线程池,我该怎么去设计。
方法一:使用threadpool模块,这是个python的第三方模块,支持python2和python3.
方法二:使用concurrent.futures模块,这个模块是python3中自带的模块,但是,python2.7以上版本也可以安装使用
方法3:重写threadpool或者future的函数;
方法4:自己构建一个线程池
32. python协程实现一个生产者消费者模型。(手写代码)
def consumer(name):
print('%s开始准备吃包子了' % name)
while True:
baozi = yield
print('[%s]包子来了,被[%s]吃了' % (baozi, name))
def product(name):
print('%s开始做包子了' % name)
c = consumer('张三') # 生成器
c1 = consumer('李四')
c.__next__()
c1.__next__()
代码转自:https://www.cnblogs.com/xuehuahongmei/p/5958373.html
运行结果:
老板开始做包子了
张三开始准备吃包子了
李四开始准备吃包子了
做好了2个包子
[0]包子来了,被[张三]吃了
[0]包子来了,被[李四]吃了
做好了2个包子
[1]包子来了,被[张三]吃了
[1]包子来了,被[李四]吃了
做好了2个包子
[2]包子来了,被[张三]吃了
[2]包子来了,被[李四]吃了
做好了2个包子
[3]包子来了,被[张三]吃了
[3]包子来了,被[李四]吃了
做好了2个包子
[4]包子来了,被[张三]吃了
[4]包子来了,被[李四]吃了
做好了2个包子
[5]包子来了,被[张三]吃了
[5]包子来了,被[李四]吃了
做好了2个包子
[6]包子来了,被[张三]吃了
[6]包子来了,被[李四]吃了
做好了2个包子
[7]包子来了,被[张三]吃了
[7]包子来了,被[李四]吃了
做好了2个包子
[8]包子来了,被[张三]吃了
[8]包子来了,被[李四]吃了
做好了2个包子
[9]包子来了,被[张三]吃了
[9]包子来了,被[李四]吃了
Process finished with exit code 0