python开发工程师常见面试题汇总

  1. Django的生命周期,及其中间件

    生命周期:前端请求—>nginx—>uwsgi.—>中间件—>url路由---->view试图—>orm---->拿到数据返回给view---->试图将数据渲染到模版中拿到字符串---->中间件—>uwsgi---->nginx---->前端渲染

    中间件:中间件的作用非常大,可以处理所有的请求内容,中间件其实就是一个类,这个类中一共有5个方法, 分别是

    process_request, process_response,process_view, process_exception, process_render_template

    中间件的执行顺序:当一个请求,首先从上往下运行这些类中process_request方法,之后进入django的从上往下执行每个类中的process_view方法,在然后就进入我们自定义的view.py文件,如果你的试图中有错误,那就会从下往上执行中间件中的process_exception方法,然后把错误信息在通过process_response中返回给客户端,如果没有错误,那么就会走最终的 process_render_template渲染。

    注意:

    process_request:在这个方法中是没有return方法的,如果有那就会执行process_response方法,直接返回给客户端,一般情况下我们是不会在这里返回内容的,除非你有需求,判断发过来的请求过来的内容,如果不是很友好的请求,那么我们直接就可以在这返回,直接卡死,让这个请求直接都进不了我们的django中的内部程序。

    process_response:在这个方法中我们必须要有return方法,这样才能一步一步的返回给客户端,当然你也可以写一些东西在response里,在这里写就是会在所有的response里都会有你所添加的内容!

    process_view:这个方法中是没有return方法的,如果有那就走process_response方法;

    process_exception:在这个方法中是一定要有return方法的,这个方法是专门返回你的错误信息的,我可以在所有的视图函数只要出现错误就会执行这个方法,可以返回一个错误模版信息!

  2. python列表和元组的区别

    列表是动态数组,它们可变且可以重设长度(改变其内部元素的个数),他的符号是[]。
    元组是静态数组,它们不可变,且其内部数据一旦创建便无法改变,他的符号是()。
    元组缓存于Python运行时环境,这意味着我们每次使用元组时无须访问内核去分配内存。
    

    这些区别其实是两者在设计哲学上的不同:

    列表可被用于保存多个互相独立对象的数据集合
    元组用于描述一个不会改变的事务的多个属性
    
  3. python字典是有序的还是无序的,为什么?

    python3.7之前的字典是无序的,python3.7及以后版本进行了优化是有序的,会发现update方法添加一个key:value后,会添加至最后的位置。

  4. python字典的常用操作方法

    • dict.clear() 的方法用于清空所有的键值对,清空后字典变成空字典。代码示例如下:

      dict1 = {"name":"小明","age":20}
      print(dict1)
      # 输出结果:{'name': '小明', 'age': 20}
      print(dict1.clear())
      # 输出结果:None
      
    • dict.get() 的方法通过key获取value。代码示例如下:

      dict1 = {"name":"小明","age":20}
      print(dict1.get("name"))
      # 输出结果:小明
      

      **当key不存在时返回None,而不会报错。**如果直接通过键来获取相应的值,当键-值对不存在时,会出现KeyError错误

    • **dict.setdefault() 的方法有点像dict.get() 的方法,可用来获取字典中的key对应的值。**但不同于dict.get() 的方法,当访问的key值不存在时,dict.setfault() 的方法会将该值添加到原字典中,相应的value为None。代码示例如下:

      dict1 = {"name":"小明","age":20}
      dict1.setdefault("sex","男")
      print(dict1)
      # 输出结果:{'name': '小明', 'age': 20, 'sex': '男'}
      
    • **dict.update() 的方法用一个字典中的项更新另一个字典。**如果被更新的字典已含有对应的key值,这个key值对应的原value会被替换。代码示例如下:

      dict1 = {"name":"小明","age":20}
      dict1.update({"age":18})
      print(dict1)
      # 输出结果:{'name': '小明', 'age': 18}
      

      **如果被更新的字典中无对应的key-value,新的key-value会被添加到原字典中。**代码示例如下:

      dict1 = {"name":"小明","age":20}
      dict1.update({"sex":"男"})
      print(dict1)
      # 输出结果:{'name': '小明', 'age': 20, 'sex': '男'}
      
    • **dict.items() 的方法获取的是一个字典视图,包含所有的字典项,每个元素为一个键值对。**这些元素的排列顺序不定。代码示例如下:

      dict1 = {"name":"小明","age":20,"sex": "男"}
      print(dict1.items())
      # 输出结果:dict_items([('name', '小明'), ('age', 20), ('sex', '男')])
      

      **dict.items() 的方法获取的是一个字典视图,可获取其长度。**但若需要进一步的操作,可将其转换成列表。**代码示例如下:

      dict1 = {"name":"小明","age":20,"sex": "男","str1":"str1","str2":"str2","str3":"str3"}
      a = dict1.items()
      print(len(a)) #6
      print(list(a)) #[('name', '小明'), ('age', 20), ('sex', '男'), ('str1', 'str1'), ('str2', 'str2'), ('str3', 'str3')]
      
    • **dict.keys() 的方法获取的是一个字典视图,包含字典所有的键。**代码示例如下:

      dict1 = {"name":"小明","age":20,"sex": "男","str1":"str1"}
      print(dict1.keys())   #dict_keys(['name', 'age', 'sex', 'str1'])
      

      **dict.keys() 的方法获取的是一个字典视图,可获取其长度。但若需要进一步的操作,可将其转换成列表。**代码示例如下:

      dict1 = {"name":"小明","age":20,"sex": "男","str1":"str1"}
      print(list(dict1.keys()))   #['name', 'age', 'sex', 'str1']
      
    • **dict.values() 的方法获取的是一个字典视图,包含字典所有的值。**代码示例如下:

      dict1 = {"name":"小明","age":20,"sex": "男","str1":"str1"}
      print(dict1.values())   #dict_values(['小明', 20, '男', 'str1'])
      

      **dict.values() 的方法获取的是一个字典视图,可获取其长度。但若需要进一步的操作,可将其转换成列表。**代码示例如下:

      dict1 = {"name":"小明","age":20,"sex": "男","str1":"str1"}
      print(list(dict1.values()))   #['小明', 20, '男', 'str1']
      
    • **dict.pop() 的方法用于删除指定键值对,但这个删除的键值对仍可使用。**代码示例如下:

      dict1 = {"name":"小明","age":20,"sex": "男","str1":"str1"}
      print(dict1.pop('str1'))   #str1
      print(dict1)     #{'name': '小明', 'age': 20, 'sex': '男'}
      
    • dict.popitem() 的方法类似于list.pop() 的方法,用于删除字典中最后一个键值对(也有定义说这个方法用于删除字典中的随机项,但这个随机并非是真的随机)。代码示例如下:

      dict1 = {"name":"小明","age":20,"sex": "男","str1":"str1"}
      dict1.popitem()
      print(dict1)     #{'name': '小明', 'age': 20, 'sex': '男'}
      
  5. Django的ORM常用命令,Book为models里面创建的书籍类,即数据库的一个Book表:

    • models.Book.objects.all() # 获取到所有的书籍对象,结果是对象列表

    • models.Book.objects.get(条件) # 获取符合条件的对象

    • models.Book.objects.filter(条件) # 筛选所有符合条件的,结果是对象列表

    • models.Book.objects.exclude(条件) # 筛选出所有不符合条件的,结果是对象列表

    • models.Book.objects.all().values( ) # 字典列表,[ {id:1,name:20} , {id:2,name:18} values(‘id’)括号内不指定时显示全部,如指定则只显示指定的,[ {id:1} , {id:2,} ]

    • models.Book.objects.all().values_list( ) # 元组列表,[ (1,20) , (2,18) ]同上,指定时显示指定内容

    • models.Book.objects.all().order_by(‘id’) # 按照id升序就行排列

    • models.Book.objects.all().order_by(‘-id’) # 按照id降序就行排列

    • models.Book.objects.all().order_by(‘age’ , ‘-id’) # 先按age升序,age相同的按id进行降序排列

    • models.Book.objects.all().order_by(‘id’).reverse() # 对结果反转; 注意reverse前必须排序,否则reverse无效; 或在model.py文件中Book类中的Meta中指定ordering=(‘id’ , )注意逗号必须有

    • distinct(): # 去重,当获取到的结果Queryset列表中同一对象出现多次时去重,只留一个

    • models.Book.objects.all().count() # 计数,可统计结果个数,如对Queryset内元素数进行统计.

    • models.Book.objects.all().first() # 获取结果中的第一条,即使前面结果列表为空,也不会报错

    • models.Book.objects.filter().last() # 获取结果中的最后一条

    • models.Book.objects.filter().exists() # 判断Queryset列表是否有东西,结果为True或False;

    • 模糊查询

      进行模糊查询
      开始进行查找前我们先来认识filter()方法。
      这是一个过滤器方法用于过滤掉不符合条件的元素。
      值得一提的是其内自带方法函数的引用方式为‘__方法名称’。
      __exact 精确等于 like ‘aaa’
      __iexact 精确等于 忽略大小写 ilike ‘aaa’
      __contains 包含 like ‘%aaa%’
      __icontains 包含 忽略大小写 ilike ‘%aaa%’,但是对于sqlite来说,contains的作用效果等同于icontains。
      __gt 大于
      __gte 大于等于
      __lt 小于
      __lte 小于等于
      __in 存在于一个list范围内
      __startswith 以…开头
      __istartswith 以…开头 忽略大小写
      __endswith 以…结尾
      __iendswith 以…结尾,忽略大小写
      __range 在…范围内
      __year 日期字段的年份
      __month 日期字段的月份
      __day 日期字段的日
      __isnull=True/False 
      
  6. MongoDB的存储方式

    mongodb的数据是存储在硬盘上的,只不过需要经常读取的数据会被加载到内存中,这样提高查询效率,所谓内存数据映射,所以

    mongodb本身很吃内存。

    相关底层参考博客:https://blog.csdn.net/liuhuayang/article/details/106681954

  7. Django中大写的Q:

    • 查询的时候当做“或”,(Q(条件)|Q(条件))

    • 查询的时候当做“非”,(~Q(条件))

    • 构建一个Q对象,供count使用

      我们在进行聚合的时候,比如使用Count,如果我们想要在聚合的过程中,进行条件过滤,可能你觉得不会发生,如果想过滤,直接在前面使用filter不就好了,但是,如果我们的表关系足够复杂,并且查询条件比较复杂,是需要的

      Count('pk', filter=Q(account_type=True))
      
  8. nginx正向代理和反向代理

    简单的说正向代理对于服务端是无感的,主动权在客户端;反向代理对于客户端是无感的,主动权在服务端,多用于负载均衡。我的博客Nginx+uwsgi部署Django项目上线貌似没有用到代理,对于nginx代理的配置一般会配置proxy字段,多位于sever下的location配置。正向反向代理参考博客:

    https://blog.csdn.net/qq_37960603/article/details/112299316

另外一篇的参考博客:
https://blog.csdn.net/qq_34615112/article/details/103813223

毕设没思路看这里https://blog.csdn.net/Q893448322/article/details/107642349?spm=1001.2014.3001.5501

如果对您有帮助,赏口饭吃❤蟹蟹٩(‘ω’)و❤

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值