python我们的答案_python面试答案

38、threading.local

作用:为每个线程创建一个独立的空间,使得线程对自己的空间中的数据进行操作(数据隔离)。

应用:DBUtils 中为每个线程创建一个数据库连接,注意:Flask中并没有使用 threading.local ,而是

使用了 LocalStack ,细化到了协程。

import threadingfromthreading import local

import time

obj=local()

def task(i):

obj.num=i

obj.sleep(2)

print(obj.num, i)for i in range(10):

t= threading.Thread(target = task, args =(i,))

t.start()

问题:如何获取一个线程的唯一标记?threading.get_ident()

根据字典自定义一个类似于 threading.local功能?

import time

import threading

DIC={}

def task(i):

ident=threading.get_ident()if ident inDIC :

DIC[ident]['num'] =ielse:

DIC[ident]= {'num': i }

time.sleep(2)

print(DIC[ident]['num'], i)for i in range(10):

t= threading.Thread(target = task, arg =(i,))

t.start()

根据字典自定义一个为每个协程开辟空间进行存取数据

import time

import threading

import greenlet

DIC={}

def task(i):

# ident=threading.get_ident()

ident=greenlet.getcurrent()if ident inDIC:

DIC[ident]['xxxxx'] =ielse:

DIC[ident]= {'xxxxx':i }

time.sleep(2)

print(DIC[ident]['xxxxx'],i)for i in range(10):

t= threading.Thread(target=task,args=(i,))

t.start()

通过 getattr/setattr 构造出来 threading.local 的加强版(协程)

imort time

import treading

import greenlettry:

get_ident=greenlet.getcurrent

except Exceptionase:

get_ident=threading.get_identclass Local(object):

DIC={}

def __getattr__(self, item):

ident=get_ident()if ident inself.DIC:

self.DIC[ident][key]=valueelse:

self.DIC[ident]={key:value}

obj=Local()

def task(i):

obj.xxxxx=i

time.sleep(2)

print(obj.xxxxx,i)for i in range(10):

t= threading.Thread(target=task,args=(i,)

t.start()39、Flask的上下文管理

请求到来的时候:

# ctx=RequestContext(self, environ) # self是app对象,environ请求相关的原始数据

# ctx.request=Request(environ)

# ctx.session=None

# 将包含了request/session的ctx对象放到“空调”

{1232:{ctx:ctx对象}1231:{ctx:ctx对象}1211:{ctx:ctx对象}1111:{ctx:ctx对象}1261:{ctx:ctx对象}

}

视图函数:fromflask import reuqest,session

request.method

请求结束:

根据当前线程的唯一标记,将“空调”上的数据移除。40、Flask之偏函数

偏函数是从Python2.5引入的一个概念,通过functools模块被用户调用。偏函数是将所要承载的函数作为partial()函数的第一个参数,原函数的各个参数依次作为partial()函数后续的参数,除非使用关键字参数。

偏函数可以帮助开发者自动传递参数。

例如:from functools import partialdef func(x, y, z):return x + y +z

new_func= partial(func, 10)

print(func(10, 10, 10))  # 30print(new_func(10, 10))  # 30应用场景:在Flask的源码里遇过:

请求进来触发 def __call__() 方法-- > def wsgi_app() --> ctx.push() --> def push() --

> _request_ctx_stack.push(self) -->globals.py文件里 有关于偏函数的使用

request= LocalProxy(partial(_lookup_req_object, 'request'))

session= LocalProxy(partial(_lookup_req_object, 'session'))

g= LocalProxy(partial(_lookup_app_object, 'g'))

PS:

其实可以看到不管request还是session最后都是通过getattr(top, name)获取的,也就是说肯定有一个上下

文对象同时保持request和session。我们只要一处导入request,在任何视图函数中都可以使用request,关键

是每次的都是不同的request对象,说明获取request对象肯定是一个动态的操作,不然肯定都是相同的

request。这里的魔法就是_lookup_req_object函数和LocalProxy组合完成的。 LocalProxy是werkzeug.local.py中

定义的一个代理对象,它的作用就是将所有的请求都发给内部的_local对象。

当我们调用request.method时会调用_lookup_req_object,对request的任何调用都是对

_lookup_req_object返回对象的调用。既然每次request都不同,要么调用top=_request_ctx_stack.top返回的

top不同,要么top.request属性不同,在flask中每次返回的top是不一样的,所以request的各个属性都是变化

的。

现在需要看看_request_ctx_stack=LocalStack(),LocalStack其实就是简单的模拟了堆栈的基本操作,

push,top,pop,内部保存的线程本地变量是在多线程中request不混乱的关键。41、面向对象中的 super 方法的用途

一、根据 mro 的顺序执行方法

二、主动执行Base类的方法42、基于列表实现栈class Stack(object):

def __init__(self):

self.data=[]

def push(self,val):

self.data.append(val)

def pop(self):returnself.data.pop()

def top(self):return self.data[-1]

_stack=Stack()

_stack.push('哈哈')

_stack.push('呵呵')

print(_stack.pop())

print(_stack.pop())43、在类中什么是函数,什么是方法?class Foo(object):

def func(self):

pass

# 执行方式一

obj=Foo()

obj.func() # 方法

# 执行方式二

Foo.func(123) # 函数44、面向对象中双下划线方法

__str__

__init__

__repr__

__new__              单例模型用到     rest framework 序列化的时候用到了

__getattr__

__setattr__

__delattr__

在 flask Local对象用到

__call__               在 Flask 的源码请求入口和 Django 的请求入口(WSGIHandler.__call__)都用到了

setitem

getitem

delitem,class Foo(object):

def __getitem__(self, item):return 1def __setitem__(self, key, value):

pass

def __delitem__(self, key):

pass

obj=Foo()

obj['k1']

obj['k1'] = 123del obj['k1']

dict,api封装返回数据时:BaseResponse

mro, 显示继承顺序

slots,Local对象,显示类中能调用的方法45、请求上下文管理(ctx):request,session-请求到来之后wsgi会触发__call__方法,由__call__方法再次调用wsgi_app方法-在wsgi_app方法中:- 首先将 请求相关+空session 封装到一个RequestContext对象中,即:ctx。-将ctx交给LocalStack对象,再由LocalStack将ctx添加到Local中,Local结构:

__storage__={1231:{stack:[ctx,] }

}- 根据请求中的cookie中提取名称为sessionid对应的值,对cookie进行加密+反序列化,再次赋值给ctx

中的session->视图函数-把session中的数据再次写入到cookie中。-将ctx删除-结果返回给用户浏览器-断开socket连接46、关于Flask中的g

g对象是application context,可以存储任何你想存储的内容,如数据库连接或登录的用户。应用

上下文flask._app_ctx_stack 和 flask.g 差不多, 可以保存一些特定的数据到这两个对象内部, 当然这些数

据只在"一个请求"的生命周期中有效. 不过flask._app_ctx_stack 推荐给extension的开发者使用, flask.g

留给web 开发使用. 如果要"跨请求"来共享数据, 需要使用 session 对象.可以使用get()方法来获取g的属

性,如:

user=getattr(flask.g,'user',None)

user=flask.g.get('user',None)

g 的生命周期:

g 是面向单个 request 的,一个 request 处理完,g 里的东西就没啦。(注意,这里说的 request

不是指 request context,从0.10版本开始,g 已经是面向 app context 了。这里写面向单个 request

是为了帮助提问者理解问题中提到的区别,仅考虑在 web 下的场景。)

g 和 session 的比较:

session 是可以跨 request 使用的,session 的数据是经过加密后存储在 cookie 里的,用户每次

request 都会把这些 cookie 信息发回来,从而实现跨 request 使用。

g是面向单个 request 的,一个 request 处理完,g 里的东西就没啦。(注意,这里说的 request

不是指 request context,从0.10版本开始,g 已经是面向 app context 了。这里写面向单个 request是为

了帮助提问者理解问题中提到的区别,仅考虑在 web 下的场景。)

g 和全局变量的比较:

全局变量在项目启动后就会引进,而且全局变量不会改变,不会消失;g 是在有请求的时候才

被设置,一次请求结束后会自动消失。47、什么是响应式布局?

简而言之,就是一个网站能够兼容多个终端--而不是为每个终端做一个特定的版本。这个概念是为

解决移动互联网浏览而诞生的。

响应式布局可以为不同终端的用户提供更加舒适的界面和更好的用户体验,而且随着目前大屏幕移

动设备的普及,用"大势所趋"来形容也不为过。随着越来越多的设计师采用这个技术,我们不仅看

到很多的创新,还看到了一些成形的模式。

优点:

面对不同分辨率设备灵活性强

能够快捷解决多设备显示适应问题

缺点:

兼容各种设备工作量大,效率低下

代码累赘,会出现隐藏无用的元素,加载时间加长

其实这是一种折中性质的设计解决方案,多方面因素影响而达不到最佳效果

一定程度上改变了网站原有的布局结构,会出现用户混淆的情况

原理:使用了媒介查询:@media属性48、MySQL 数据库的引擎1.Innodb引擎

支持事务

支持锁

行锁和表锁:但是当SQL语句没有指定要锁定的具体行范围的话,Innodb 也会锁全表。

支持外键约束2.MyIASM引擎

MyIASM是MySQL默认的引擎,不支持事务,也不支持行级锁和外键,只支持表级锁。

两种引擎的比较:

大尺寸的数据集趋向于选择InnoDB引擎,因为它支持事务处理和故障恢复。数据库的大小决

定了故障恢复的时间长短,InnoDB可以利用事务日志进行数据恢复,这会比较快。主键查询

在InnoDB引擎下也会相当快,不过需要注意的是如果主键太长也会导致性能问题。大批的

INSERT语句(在每个INSERT语句中写入多行,批量插入)在MyISAM下会快一些,但是

UPDATE语句在InnoDB下则会更快一些,尤其是在并发量大的时候。49、Flask 上下文管理

LocalProxy:它是werkzeug.local.py中定义的一个代理对象,它的作用就是将所有的请求都发给内部

的_local对象。

主要包含两种:

请求上下文(ctx=RequestContext())里面含有两种信息 request  \ session

app 上下文(app_ctx=AppContext())里面含有两种信息 app \ g

详细流程:1、程序启动后:

启动项目的全局变量,实例化了两个对象,并创建了两个Stack

两个Local:

local1={

}

local2={

}

两个LocalStack:

_request_ctx_stack

_app_ctx_stack2、请求到来后

对数据进行封装:

ctx=RequestContext(request,session)

app_ctx=AppContext(app,g)

保存数据:

将包含了(app,g)数据的app_ctx对象,利用 _app_ctx_stack(贝贝,LocalStack())将

app_ctx添加到Local中

storage={1231:{stack:[app_ctx(app,g),]}

}

将包含了request,session数据的ctx对象,利用_request_ctx_stack(刘淞,

LocalStack()),将ctx添加到Local中

storage={1231:{stack:[ctx(request,session),]}

}

问题:

Local是什么?作用?

答:存储数据,在Flask中给每一个协程开辟一个内存空间,保证数据之间的隔离

LocalStack是什么?作用?

答:将Local的数据,字典storage对应的值维护成一个栈(栈里面有 push 和 pop 这两

个方法),然后把数据存储到Local 中3、视图函数处理:fromflask import Flask,request,session,current_app,g

app=Flask(__name__)

@app.route('/index')

def index():

# 去请求上下文中获取值 _request_ctx_stack

request.method # 找小东北获取值

session['xxx'] # 找龙泰获取值

# 去app上下文中获取值:_app_ctx_stack

print(current_app)

print(g)return "Index"if __name__ == '__main__':

app.run()

app.wsgi_app

通过LocalProxy对象+偏函数,调用LocalStack去Local中获取响应ctx、app_ctx中封装的

值。

问题:

为什么要把 ctx=requestssion    app_ctx = app/g    ?答:因为离线脚本需要使用app_ctx。4、请求结束

_app_ctx_stack.pop()

_request_ctx_stack.pop()50、MySQL 数据库的索引

索引作用:加速查找+约束。

索引种类:-主键索引:加速查找、不重复、非空-唯一索引:加速查找、不重复-普通索引:加速查找-联合索引:加速查找-联合唯一索引:加速查找、不重复

PS:联合索引遵循最左前缀原则。

id   name   pwd   email

数据表中有上面4个字段,如果把 name pwd email 设成联合索引,只有下面的情况能命中

索引select * from tb where name='x'select * from tb where name='x' and pwd='123'select * from tb where name='x' and email='123@qq.com'select * from tb where name='x' and pwd='123' and email='xs'当下面两种情况的时候不会命中索引select * from tb where pwd='123'select * from tb where pwd='123' and email='123@qq.com'名词:-覆盖索引:在索引文件中就可以把想要的数据得到。

MySQL可以利用索引返回select列表中的字段,而不必根据索引再次读取数据

文件,包函所有满足查询需要的数据的索引称为覆盖索引。

注意:如果使用覆盖索引,一定要注意select列表中只取出需要的列,不可select *,因为如果将所有字段一起做索引会导致索引文件过大,查询性能下

降。select name fromtb1;-索引合并:使用多个单列索引去查找数据。1、索引合并是把几个索引的范围扫描合并成一个索引。2、索引合并的时候,会对索引进行并集,交集或者先交集再并集操作,以便合并

成一个索引。3、这些需要合并的索引只能是一个表的。不能对多表进行索引合并。

创建索引,但无法命中索引:

https://www.cnblogs.com/wupeiqi/articles/5716963.html

51、MySQL 数据库授权

MySQL 赋予用户权限命令的简单格式可概括为:

grant 权限 on 数据库对象 to 用户

详解:https://www.cnblogs.com/bethal/p/5512755.html

52、MySQL 数据库视图

视图(View)是一种虚拟存在的表。其内容与真实的表相似,包含一系列带有名称的列和行数据。

但是视图并不在数据库中以存储的数据的形式存在。行和列的数据来自定义视图时查询所引用的基

本表,并且在具体引用视图时动态生成。

视图是存储在数据库中的查询的SQL 语句,它主要出于两种原因:安全原因, 视图可以隐藏一些

数据,如:社会保险基金表,可以用视图只显示姓名,地址,而不显示社会保险号和工资数等,另

一原因是可使复杂的查询易于理解和使用。

创建视图create view :

CREATE VIEW 视图名(列1,列2...) AS SELECT (列1,列2...) FROM ...;53、MySQL 数据库触发器

MySQL包含对触发器的支持。触发器是一种与表操作有关的数据库对象,当触发器所在表上出现指

定事件时,将调用该对象,即表的操作事件触发表上的触发器的执行。

在对某张表进行:增、删、改的前后自定义操作。

在MySQL中,创建触发器语法如下:

CREATE TRIGGER trigger_name

trigger_time

trigger_event ON tbl_name

FOR EACH ROW

trigger_stmt

查看触发器,和查看数据库(show databases;)查看表格(show tables;)一样,查看触发器的语法如

下:

SHOW TRIGGERS [FROM schema_name];

删除触发器,和删除数据库、删除表格一样,删除触发器的语法如下:

DROP TRIGGER [IF EXISTS] [schema_name.]trigger_name

触发器的执行顺序

我们建立的数据库一般都是 InnoDB 数据库,其上建立的表是事务性表,也就是事务安全的。这

时,若SQL语句或触发器执行失败,MySQL 会回滚事务,有:

①如果 BEFORE 触发器执行失败,SQL 无法正确执行。

②SQL 执行失败时,AFTER 型触发器不会触发。

③AFTER 类型的触发器执行失败,SQL 会回滚。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值