python基础知识思维导图

MyProcessOn

Python基础:

说说你眼中的python( 2 )

  1. 谈谈你对python和其他语言的区别

    1. python 中,变量是以内容为基准而不是像 c 中以变量名为基准;
    2. python 中,一个变量可以以多个名称访问;
    3. python 中,数字类型的值是不可变的;
    4. python 中,编译器会有一个小整数池的概念
  2. 谈谈你了了解的python种类以及相关特点
    Python的种类:
    - Cpython:使用 C 解释器来解释扩展名:.pyc C解释器 -> .pyc(字节码) -> 机器码 -> cpu
    - Jpython:使用 Java 解释器 java 字节码->机器码 -> cpu
    - ironpython:使用C#解释器 C# 字节码 -> 机器码 -> cpu
    PYPY:运行速度快,原理:解释器->字节码->编译成机器码->直接运行机器码,用户运行时直接使用机器码,所以运行速度快。
  3. 字节码和机器器码的关系和区别?
    - 机器码(machine code),学名机器语言指令,有时也被称为原生码(Native Code),是电脑的CPU可直接解读的数据。
    - 通常意义上来理解的话,机器码就是计算机可以直接执行,并且执行速度最快的代码。
    - 字节码是一种中间状态(中间码)的二进制代码(文件)。需要直译器转译后才能成为机器码。
  4. 为什么要学python
    1. 编译型语言:一次性,将全部的程序编译成二进制文件,然后在运行。(c,c++ ,go)
    优点:运行速度快。
    缺点:开发效率低,不能跨平台。
    2. 解释型语言:当你的程序运行时,一行一行的解释,并运行。(python , PHP)
    优点:调试代码很方便,开发效率高,并且可以跨平台。
    缺点:运行速度慢。
    3. 我对程序的定义是人可以读懂,而机器刚好可以执行的一段代码,注重于代码的可读性。
    而Python的定位是“优雅”、“明确”、“简单”,用它编写的程序简单易懂,这与我当初的想法不谋而合
  5. pep8规范
    代码编排
    - 缩进。4个空格的缩进
    - 每行最大长度79,换行可以使用反斜杠
    - 类和top-level函数定义之间空两行;类中的方法定义之间空一行;函数内逻辑无关段落之间空一行;其他地方尽量不要再空行。
    文档编排
    - 模块内容的顺序:按标准、三方和自己编写顺序依次排放,之间空一行
    - 不要在一句import中多个库
    空格的使用
    注释
    文档描述
  6. 123
  7. 123

py2与py3

  1. Python2和Python3的区别

    1. 性能
    - Py3.x性能比Py2.5慢15%,但还有很大的提升空间。
    2.编码
    - Py3.X源码文件默认使用utf-8编码
    3. 语法
    - 去除print语句
    - 关键词加入as 和with,还有True,False,None
    - 删除了raw_input,用input代替
    - 新的metaclass语法
    4. 字符串和字节串
    - 字符串只有str一种类型
    5.数据类型
    - 只有一种整型——int
    - 新增了bytes类型
    6.面向对象
    - 容器类和迭代器类被ABCs化,所以cellections模块里的类型比Py2.5多了很多
    - 迭代器的next()方法改名为__next__(),并增加内置函数next(),用以调用迭代器的__next__()方法
  2. range和xrange的区别
    两者的区别是xrange返回的是一个可迭代的对象,range返回的则是一个列表. 同时效率更高,更快。
    - 原因是实现的时候使用了 yield(此为python2.x回答,python3已删除xrange)
  3. Python3和Python2中 int 和 long 的区别
    int <= 32 位整数
    long > 32 位整数
  4. 文件操作时:xreadlines和readlines的区别
    xreadlines = 返回一个生成器对象,
    readlines = 遍历文件所有行
  5. 123
  6. 123

进制转换

  1. 二进制转换成十进制:v = "0b1111011"

    print(int(v,2)) # 可将任意进制数转换成十进制数(数字,这是多少进制)
    
  2. 十进制转换成二进制:v = 18
    print(bin(v))
    
  3. 八进制转换成十进制:v = "011"
    print(int(v,8)) # 可将任意进制数转换成十进制数(数字,这是多少进制)
    
  4. 十进制转换成八进制:v = 30
    print(oct(v))
    
  5. 十六进制转换成十进制:v = "0x12"
    print(int(v,16)) # 可将任意进制数转换成十进制数(数字,这是多少进制)
    
  6. 123

运算符 ( 8 )

  1. 各类运算符详解
  2. 各类运算符优先级
    运算符	                        描述
    ** 指数 (最高优先级)
    ~ + - 按位翻转, 一元加号和减号 (最后两个的方法名为 +@ 和 -@)
    * / % // 乘,除,取模和取整除
    + - 加法减法
    >> << 右移,左移运算符
    & 位 'AND'
    ^ | 位运算符
    <= < > >= 比较运算符
    <> == != 等于运算符
    = %= /= //= -= += *= **= 赋值运算符
    is is not 身份运算符
    in not in 成员运算符
    and or not 逻辑运算符
  3. 求结果:2 & 5
    按位与运算符:参与运算的两个值,如果两个相应位都为1,则该位的结果为1,否则为0
    Python结果:0
  4. 求结果:2 ^ 5
    按位异或运算符:当两对应的二进位相异时,结果为1
    Python结果:7
  5. 求结果:1 or 3
    x or y
    布尔"或" :如果 x 是 True,它返回 x 的值,否则它返回 y 的计算值。
    Python结果:1
  6. 求结果:1 and 3
    x and y
    布尔"与" - :
    如果 x 为 False,x and y 返回 False,否则它返回 y 的计算值。
    python结果:>1
  7. 求结果:0 and 2 and 1
    Python结果: 0
  8. 求结果:0 and 2 or 1
    Python结果: 1
  9. 求结果:0 and 2 or 1 or 4
    Python结果:1
  10. 求结果:0 or False and 1
    Python结果:False
  11. 用⼀行代码实现数值交换: a = 1 b = 2
    b,a = a,b
  12. 123

数据结构( 2 )

  1. 基本的数据类型和方法都有哪些

    列表:list
    - list.append(obj) # 在列表末尾添加新的对象
    - list.count(obj) # 统计某个元素在列表中出现的次数
    - list.extend(seq) # 在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表)
    - list.index(obj) # 从列表中找出某个值第一个匹配项的索引位置
    - list.insert(index, obj)# 将对象插入列表
    - list.pop(obj=list[-1]) # 移除列表中的一个元素(默认最后一个元素),并且返回该元素的值
    - list.remove(obj) # 移除列表中某个值的第一个匹配项
    - list.reverse() # 反向列表中元素
    - list.sort([func])# 对原列表进行排序
    - list.clear() # 清空列表
    - list.copy() # 复制列表
    字典:dict
    - popitem() # 随机返回并删除字典中的一对键和值(一般删除末尾对)。
    - key in dict # 如果键在字典dict里返回true,否则返回false
    - radiansdict.copy() # 返回一个字典的浅复制
    - radiansdict.keys() # 以列表返回一个字典所有的键
    - radiansdict.items() # 以列表返回可遍历的(键, 值) 元组数组
    - radiansdict.clear() # 删除字典内所有元素
    - radiansdict.values() # 以列表返回字典中的所有值
    - radiansdict.fromkeys() # 创建一个新字典,以序列seq中元素做字典的键,val为字典所有键对应的初始值
    - radiansdict.update(dict2) # 把字典dict2的键/值对更新到dict里
    - radiansdict.get(key, default=None) # 返回指定键的值,如果值不在字典中返回default值
    - radiansdict.setdefault(key, default=None) # 和get()类似, 但如果键不存在于字典中,将会添加键并将值设为default
    - pop(key[,default]) # 删除字典给定键 key 所对应的值,返回值为被删除的值。key值必须给出。 否则,返回default值。
    字符串:str
    - upper() # 转换字符串中的小写字母为大写。
    - title() # 返回"标题化"的字符串,就是说所有单词都是以大写开始,其余字母均为小写(见 istitle())。
    - lower() # 转换字符串中所有大写字符为小写。
    - rstrip() # 删除字符串字符串末尾的空格.
    - lstrip() # 截掉字符串左边的空格或指定字符。
    - max(str) # 返回字符串 str 中最大的字母。
    - min(str) # 返回字符串 str 中最小的字母。
    - join(seq) # 以指定字符串作为分隔符,将 seq 中所有的元素(的字符串表示)合并为一个新的字符串
    ...
    MySlef
    整数:int
    - bit_length() # 查询以二进制表示一个数字的值所需的位数
    - int.from_bytes(bytes,byteorder) # 返回给定字节数组所表示的整数。
    - int.to_bytes(length,byteorder) # 返回表示整数的字节数组。
    元组:tuple
    - len(tuple) # 计算元组元素个数。
    - max(tuple) # 返回元组中元素最大值。
    - min(tuple) # 返回元组中元素最小值。
    - tuple(seq) # 将列表转换为元组。
    集合:set
    - set1 = set({1, 2, 'barry'}) # 创建集合
    - set2 = {1, 2, 'barry'} # 创建集合
    - add # 将元素添加到集合中。如果元素已经存在,这不起作用。
    - del set1 # 删除集合- update # 迭代增加
    - clear # 删除此集合中的所有元素
    - remove # 删除一个元素
    - pop # 随机删除一个元素
    - issubset # 子集
    - issuperset # 超集
    - union # 并集。(| 或者 union)
    - difference # 差集。(- 或者 difference)
    - intersection # 交集。(& 或者 intersection)
    - isdisjoint # 如果两个集合有一个空交点,则返回True
    - intersection_update # 用它自己和另一个交集更新一个集合。
    - difference_update # 删除另一个集合中本集合所拥有的所有元素
    - symmetric_difference # 反交集。 (^ 或者 symmetric_difference)
    浮点:float
    - is_integer # 如果浮点数是整数,则返回True
    collections:Python内建的一个集合模块,提供了许多有用的集合类。
    - Counter # 是一个简单的计数器,例如,统计字符出现的个数:
    - OrderedDict # 可以实现一个FIFO(先进先出)的dict,当容量超出限制时,先删除最早添加的Key:
    - deque # 是为了高效实现插入和删除操作的双向列表,适合用于队列和栈:
    - defaultdict # 使用dict时,如果引用的Key不存在,就会抛出KeyError。如果希望key不存在时,返回一个默认值,就可以用defaultdict:
  2. 可变与不可变类型

    可变:
    - list, - dict
    不可变:
    -str, - int, - tuple, - float,
  3. 常⽤字符串格式化有哪些?
    1.占位符%
    %d 表示那个位置是整数;%f 表示浮点数;%s 表示字符串
    - print('Hello,%s' % 'Python')
    - print('Hello,%d%s%.2f' % (666, 'Python', 9.99)) # 打印:Hello,666Python10.00
    2.format
    - print('{k} is {v}'.format(k='python', v='easy')) # 通过关键字
    - print('{0} is {1}'.format('python', 'easy')) # 通过关键字
  4. 常用字符串格式化有哪些?
    - 0
    - ""
    - []
    - {}
    - (,)
    - None
  5. *Python2和Python3有差吗
    Python2和Python3有差吗
    
  6. Python2和Python3有差吗
    is和==的区别
    
  7. 123
  8. 123
  9. 123
  10. 123
  11. 123
  12. 123

函数( 9 )

  1. 函数参数传递的是什么? 引用、内存地址

    # 默认参数尽量避免使用可变数据类型
    # 默认参数只会被执行一次:第一次调用函数时,默认参数被初始化为【】,以后每次调用时都会使用已经初始化的【】。
    >>> def func(a,a1 = []): #默认参数
    ... a1.append(a)
    ... print(a1) >>> func()
    [1]
    >>> func()
    [1, 1]
    >>> func()
    [1, 1, 1]
    >>> func()
    [1, 1, 1, 1]
  2. 闭包函数
    def foo():
    m, n=3, 5
    def bar():
    a=4
    return m+n+a
    return bar
    >>>bar = foo()
    >>>bar()
    12 说明:
    bar在foo函数的代码块中定义。我们称bar是foo的内部函数。
    在bar的局部作用域中可以直接访问foo局部作用域中定义的m、n变量。
    简单的说,这种内部函数可以使用外部函数变量的行为,就叫闭包。 - 闭包的意义与应用: 延迟计算;
    - 闭包的意义: 返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域 #应用领域:延迟计算(原来我们是传参,现在我们是包起来) 装饰器就是闭包函数的一种应用场景
  3. 谈谈你对闭包的理解?
    说明:
    bar在foo函数的代码块中定义。我们称bar是foo的内部函数。 在bar的局部作用域中可以直接访问foo局部作用域中定义的m、n变量。
    简单的说,这种内部函数可以使用外部函数变量的行为,就叫闭包。 闭包的意义与应用:
    # 装饰器就是闭包函数的一种应用场景
    # 闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域
    # 应用领域:延迟计算(原来我们是传参,现在我们是包起来)
    from urllib.request import urlopen
    def index(url):
    def get():
    return urlopen(url).read()
    return get baidu=index('http://www.baidu.com')
    print(baidu().decode('utf-8'))
  4. 必会内置函数 - map
    介绍:
    会根据提供的函数对指定序列做映射。
    第一个参数 function 以参数序列中的每一个元素调用 function 函数,返回包含每次 function 函数返回值的新列表。
    语法:
    map(function, iterable, ...)
    - function -- 函数,有两个参数
    - iterable -- 一个或多个序列
    应用示例:
    >>>def square(x) : # 计算平方数
    ... return x ** 2
    ...
    >>> map(square, [1,2,3,4,5]) # 计算列表各个元素的平方
    [1, 4, 9, 16, 25]
    >>> map(lambda x: x ** 2, [1, 2, 3, 4, 5]) # 使用 lambda 匿名函数
    [1, 4, 9, 16, 25] # 提供了两个列表,对相同位置的列表数据进行相加
    >>> map(lambda x, y: x + y, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10])
    [3, 7, 11, 15, 19]
  5. 必会内置函数 - filter
    介绍:
    函数用于过滤序列,过滤掉不符合条件的元素,返回由符合条件元素组成的新列表。
    该接收两个参数,第一个为函数,第二个为序列,序列的每个元素作为参数传递给函数进行判,然后返回 True 或 False,最后将返回 True 的元素放到新列表中。
    语法:
    filter(function, iterable)
    - function -- 判断函数。
    - iterable -- 可迭代对象。
    应用示例1:过滤出列表中的所有奇数:
    def is_odd(n):
    return n % 2 == 1
    newlist = filter(is_odd, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
    print(newlist)
    >>>[1, 3, 5, 7, 9]
    应用示例2:过滤出1~100中平方根是整数的数
    import math
    def is_sqr(x):
    return math.sqrt(x) % 1 == 0
    newlist = filter(is_sqr, range(1, 101))
    print(newlist)
    >>>[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
    应用示例3:filter相较于py2的区别
    python2中返回的是过滤后的列表, 而python3中返回到是一个filter类
    filter类实现了__iter__和__next__方法, 可以看成是一个迭代器, 有惰性运算的特性, 相对python2提升了性能, 可以节约内存。
    a = filter(lambda x: x % 2 == 0, range(10))
    print(a)
    >>><filter object at 0x000001CC57668518>
  6. 必会内置函数 - zip
    介绍:
    函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。
    如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * 号操作符,可以将元组解压为列表。
    语法:
    zip([iterable, ...])
    - iterabl -- 一个或多个迭代器;
    返回值:
    - 返回元组列表。
    应用示例:
    >>>a = [1,2,3]
    >>> b = [4,5,6]
    >>> c = [4,5,6,7,8]
    >>> zipped = zip(a,b) # 打包为元组的列表
    [(1, 4), (2, 5), (3, 6)]
    >>> zip(a,c) # 元素个数与最短的列表一致
    [(1, 4), (2, 5), (3, 6)]
    >>> zip(*zipped) # 与 zip 相反,可理解为解压,返回二维矩阵式
    [(1, 2, 3), (4, 5, 6)]
  7. 必会内置函数 - isinstance
    介绍:
    函数来判断一个对象是否是一个已知的类型,类似 type()。
    语法:
    isinstance(object, classinfo)
    - object -- 实例对象。
    - classinfo -- 可以是直接或间接类名、基本类型或者由它们组成的元组。
    返回值:
    如果对象的类型与参数二的类型(classinfo)相同则返回 True,否则返回 False。。
    应用示例:
    >>>a = 2
    >>> isinstance (a,int)
    True
    >>> isinstance (a,str)
    False
    >>> isinstance (a,(str,int,list)) # 是元组中的一个返回 True
    True
  8. isinstance() 与 type()的区别
    介绍
    1. type() 不会认为子类是一种父类类型,不考虑继承关系。
    2. isinstance() 会认为子类是一种父类类型,考虑继承关系。
    # 如果要判断两个类型是否相同推荐使用 isinstance()。
    示例:
    class A:
    pass
    class B(A):
    pass isinstance(A(), A) # returns True
    type(A()) == A # returns True
    isinstance(B(), A) # returns True
    type(B()) == A # returns False
  9. pass的作用
     - 1. 不做任何事情,一般用做占位语句。
    - 2. pass是空语句,是为了保持程序结构的完整性。
  10. *args和**kwarg的作用
    位置参数(positional argument)
    关键词参数(keyword argument)
    - *args表示任何多个无名参数,它本质是一个 tuple ;
    - **kwargs表示关键字参数,它本质上是一个 dict ;
    - 并且同时使用*args和**kwargs时,必须*args参数列要在**kwargs前。
  11. is和==的区别
      - is 比较的是两个实例对象是不是完全相同,它们是不是同一个对象,占用的内存地址是否相同。莱布尼茨说过:“世界上没有两片完全相同的叶子”,这个is正是这样的比较,
    比较是不是同一片叶子(即比较的id是否相同,这id类似于人的身份证标识)。
    - == 比较的是两个对象的内容是否相等,即内存地址可以不一样,内容一样就可以了。这里比较的并非是同一片叶子,可能叶子的种类或者脉络相同就可以了。
    默认会调用对象的 __eq__()方法。
  12. 123
  13. 123
  14. 123

函数的应用

  1. ⼀⾏代码实现9*9乘法表

    print('\n'.join([' '.join(['%s*%s=%-2s' % (j, i, i * j) for j in range(1, i + 1)]) for i in range(1, 10)]))
    
  2. 如何实现 “1,2,3” 变成 [‘1’,’2’,’3’]
     - list("1,2,3".split(','))
    
  3. 如何实现[‘1’,’2’,’3’]变成[1,2,3]
    [int(x) for x in ['1','2','3']]
    
  4. 如何⽤⼀⾏代码⽣成[1,4,9,16,25,36,49,64,81,100]
    [i*i for i in range(1,11)]
    
  5. ⼀行代码实现删除列表中重复的值
    list(set([1, 2, 3, 4, 45, 1, 2, 343, 2, 2]))
    
  6. 请编写一个函数实现将IP地址转换成一个整数
    如 10.3.9.12 转换规则为:
    10 00001010
    3   00000011
    9   00001001
    12 00001100
    再将以上二进制拼接起来计算十进制结果:00001010 00000011 00001001 00001100 = ?

    a = "10.3.9.12"
    def func(ip):
    Iplist = ip.split(".") # ['10', '3', '9', '12']
    res = " "
    temp = []
    for i in Iplist: # <class 'str'>
    i = int(i) # <class 'int'>
    i = bin(i)[2:] # <class 'str'>
    temp.append(i.rjust(8, "0")) # 右对齐,向左填充数据
    res = res.join(temp)
    return res # 一行代码实现:
    b = "".join([" ".join(str(bin(int(i))[2:]).rjust(8,"0") for i in a.split("."))])
    print(func(a)) - "00001010 00000011 00001001 00001100"
  7. 用Python实现⼀个⼆分查找的函数 二分查找算法:
            简单的说,就是将一个列表先排序好,比如按照从小到大的顺序排列好,当给定一个数据,比如3,查找3在列表中的位置时,可以先找到列表中间的数li[middle]和3进行比较,当它比3小时,那么3一定是在列表的右边,反之,则3在列表的左边,比如它比3小,则下次就可以只比较[middle+1, end]的数,继续使用二分法,将它一分为二,直到找到3这个数返回或者列表全部遍历完成(3不在列表中)
            优点:效率高,时间复杂度为O(logN);
            缺点:数据要是有序的,顺序存储。
    li = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    
    def search(someone, li):
    l = -1
    h = len(li) while l + 1 != h:
    m = int((l + h) / 2)
    if li[m] < someone:
    l = m
    else:
    h = m
    p = h
    if p >= len(li) or li[p] != someone:
    print("元素不存在")
    else:
    str = "元素索引为%d" % p
    print(str) search(3, li) # 元素索引为2
  8. 1
  9. 1
  10. 1
  11. 1
  12. 1
  13. 1
  14. 请⽤代码简答实现stack
    1. Stack() 创建一个新的空栈
    2. push(item) 添加一个新的元素item到栈顶
    3. pop() 弹出栈顶元素
    4. peek() 返回栈顶元素
    5. is_empty() 判断栈是否为空
    6. size() 返回栈的元素个数 class Stack(object):
    """栈"""
    def __init__(self):
    self.items = [] def is_empty(self):
    """判断是否为空"""
    return self.items == [] def push(self, item):
    """加入元素"""
    self.items.append(item) def pop(self):
    """弹出元素"""
    return self.items.pop() def peek(self):
    """返回栈顶元素"""
    return self.items[len(self.items)-1] def size(self):
    """返回栈的大小"""
    return len(self.items) if __name__ == "__main__":
    stack = Stack()
    stack.push("hello")
    stack.push("world")
    stack.push("lcg")
    print stack.size()
    print stack.peek()
    print stack.pop()
    print stack.pop()
    print stack.pop()
  15. 内置函数:map、reduce、filter的用法和区别
    map:遍历序列,对序列中每个元素进行操作,最终获取新的序列。
    - 每个元素增加100:
    - li = [11, 22, 33]
    - new_list = map(lambda a: a + 100, li)
    - 两个列表对应元素相加
    - li = [11, 22, 33]
    - sl = [1, 2, 3, 4]
    - new_list = map(lambda a, b: a + b, li, sl) filter:对于序列中的元素进行筛选,最终获取符合条件的序列。
    - 获取列表中大于12的所有元素集合
    - li = [11, 22, 33]
    - new_list = filter(lambda arg: arg > 22, li)
    - # filter第一个参数为空,将获取原来序列 reduce:对于序列内所有元素进行累计操作。
    - 获取序列所有元素的和
    - li = [11, 22, 33]
    - result = reduce(lambda arg1, arg2: arg1 + arg2, li)
    - # reduce的第一个参数,函数必须要有两个参数
    - # reduce的第二个参数,要循环的序列
    - # reduce的第三个参数,初始值

函数的骚操作( 8 )

  1. 手写:三元运算符

    >>> val = "aaa" if 1==1 else "bbb"
    >>> val
    'aaa'
    >>>
  2. 手写:lambda表达式
    my_lambda = lambda arg : arg + 1
  3. 手写:列表推导式
    def func(x):
    return x+1 variable = [ func for num in range(10) if num == 2]
    func:   # 列表生成元素表达式,可以是有返回值的函数或者 lambda 函数。
    for num in range(10): # 迭代 range(10) 将 num 传入 func 表达式中。
    if num == 2: # 根据条件过滤哪些值可以。
  4. 手写:列表推导式 + lambda表达式 :# 一行代码写出30以内所有能被3整除的数的平方:
    # 错误示例:不能使用列表生成式
    a = [lambda :i*i for i in range(31) if i%3 is 0]
    # 错误调用方式: # 每次只会返回最后一个被循环的range(30)!
    >>>a
    [. at 0x000002C97... ,>> a[0]
    . at 0x000002C977B96BF8>
    >>> a[0]()
    900
    # 正确示例:使用生成器迭代执行 # 注意括号!
    a = (lambda :i*i for i in range(31) if i%3 is 0)
    # 调用方式:
    >>> a.__iter__
    <method-wrapper '__iter__' of generator object at 0x000002C977AF5938>
    >>> a.__iter__()
    at 0x000002C977AF5938>
    >>> a.__iter__().__next__
    <method-wrapper '__next__' of generator object at 0x000002C977AF5938>
    >>> a.__iter__().__next__()
    . at 0x000002C977B8CF28>
    >>> a.__iter__().__next__()()
    9
  5. 手写字典推导式
    # 推导式示例:
    >>> mcase = {'a': 10, 'b': 34}
    >>> mcase_frequency = {mcase[k]: k for k in mcase}
    >>> print(mcase_frequency)
    {10: 'a', 34: 'b'}
  6. 手写:字典推导式:合并大小写对应的value值,将k统一成小写
    #   _._
    >>> mcase = {'a': 10, b': 34, 'A': 7, 'Z': 3}
    >>> mcase_frequency = {k.lower(): mcase.get(k.lower(), 0) + mcase.get(k.upper(), 0) for k in mcase.keys()}
    >>> print(mcase_frequency)
    {'a': 17, 'b': 34, 'z': 3}
  7. 手写:集合推导式
    # 集合推导式示例
    >>> squared = {x**2 for x in [ i for i in range(-5,10) ]}
    >>> print(squared)
    {1, 4}
  8. 列表推导式list comprehension和生成器的优劣

    1. 列表推导式是将所有的值一次性加载到内存中
    2. 生成器是将列表推导式的[]改成(),不会将所有的值一次性加载到内存中,延迟计算,一次返回一个结果,
    它不会一次生成所有的结果,这对大数据量处理,非常有用
    # 生成器函数: 一个函数中包含了yield关键词,那么这个函数就不是普通的函数,是一个生成器函数
    # 调用生成器函数,不会立马执行该函数里面的代码, 而是会返回一个 生成器对象

python三神器( 7 )

  1. 生成器、迭代器、装饰器、可迭代对象的区别

    容器:
    - 是一系列元素的集合,str、list、set、dict、file、sockets对象都可以看作是容器,容器都可以被迭代(用在for,while等语句中),因此他们被称为可迭代对象。
    可迭代对象实现了__iter__方法,该方法返回一个迭代器对象。
    迭代器:
    - 持有一个内部状态的字段,用于记录下次迭代返回值,它实现了__next__和__iter__方法,迭代器不会一次性把所有元素加载到内存,而是需要的时候才生成返回结果。
    生成器:
    - 是一种特殊的迭代器,它的返回值不是通过return而是用yield。
    装饰器
    - 在不改变原函数代码的基础上,在执行前后进行定制操作
  2. 生成器
    - 生成器,一个函数内部存在yield关键字;v = 函数()。
    应用场景:
    - range/xrange
    - py2: range(100000000),立即创建;xrange(100000000)生成器;
    - py3: range(100000000)生成器;
    - redis获取值
    conn = Redis(...)
    def hscan_iter(self, name, match=None, count=None):
    """
    Make an iterator using the HSCAN command so that the client doesn't
    need to remember the cursor position.
    ``match`` allows for filtering the keys by pattern
    ``count`` allows for hint the minimum number of returns
    """
    cursor = '0'
    while cursor != 0:
    # 去redis中获取数据:12
    # cursor,下一次取的位置
    # data:本地获取的12条数数据
    cursor, data = self.hscan(name, cursor=cursor, match=match, count=count)
    for item in data.items():
    yield item
  3. 迭代器
    - 迭代器,内部实现__next__方法,帮助我们向后一个一个取值。
    
  4. 可迭代对象
    可迭代对象介绍
    - 一个类内部实现 __iter__ 方法且返回一个迭代器
    - 实例:
    class Foo(object):
    def __iter__(self):
    return iter([11,22,33,44])
    obj = Foo()
    - 应用场景:
    - wtform中对form对象进行循环时,显示form中包含的所有字段。
    - 列表、字典、元组
  5. 什么是装饰器
    装饰器介绍
    - 在不改变原函数代码的基础上,在执行前后进行定制操作
    - 手写
    - 应用场景:
    - Flask : 路由、before_request、after_request
    - Django: csrf、缓存、内置用户登录认证
    - functools:缓存、warper
  6. 手写一个装饰器
    def waper(func):
    def inner(*args, **kwargs):
    res = func(*args, **kwargs)
    return res
    return inner
  7. 带参数的装饰器
    def waper(func, x,y):
    print( int(x) + int(y) )
    @functools.wapper # 保留原函数信息
    def inner(*args, **kwargs):
    """blabla的一些注释"""
    res = func(*args, **kwargs)
    return res
    return inner @wapper(1,2)
    def func(a):
    return a
    func(123)

面向对象 ( 10 )

  1. 谈谈你对面向对象的认识

    - 简单描述 :继承、封装、多态 
    - 系统描述 :先对代码进行分类:按属性进行划分(file,DB),按功能划分,将同一类方法分为一类。将方法中共同的参数封装到对象中,把共用值封装到对象中。
    面向对象的私有字段:
    - python中一切皆对象
    1. 封装:对数据的,对对象的封装。
    2. 继承:在类的基础上进行二次开发,通过函数super() 或者"基类名.方法名() "的方式实现这一目的的。
    3. 多态:同一个方法处于不同对象中,可以产生不同的结果
    - 多态示例
    # 鸭子模型
    class A:
    def send(self):
    pass
    class B:
    def send(self):
    pass
    def func(arg):
    arg.send()
    obj = B()
    func(obj)
  2. 你知道哪些双下划线方法
    - 双下划线:
    1. __getattr__:反射
    应用场景:
    - CBV
    - Django 配置文件
    - wtforms中的Form()实例化中 将"_fields中的数据封装到Form类中"
    2. __mro__:定义解析类继承的顺序
    应用场景:wtforms中 FormMeta中继承的优先级
    3. __dict__:用来存储对象属性的一个字典,其键为属性名,值为属性的值
    - __dict__ 与 dir()的区别:
    1. dir()是一个函数,返回值是list
    2. dir用来寻找一个对象的所有属性值,包括__dict__中的属性,__dict__是dir()的子集
    4. __new__ :
    - 当你继承一些不可变的class时(比如int, str, tuple), 提供给你一个自定义这些类的实例化过程的途径。
    - 实现自定义 metaclass
    应用场景:
    - wtforms 字段实例化时返回:不是StringField,而是UNboundField
    - rest_framework:many=Ture 中的序列化
    - 单例模式
    5. __call__:作用是使实例能够像函数一样被调用,同时不影响实例本身的生命周期, (__call__()不影响一个实例的构造和析构)
    但是__call__()可以用来改变实例的内部成员。
    __call__ 与 __init__的区别
    应用场景:
    - FLask 请求的入口app.run()
    - 字段生成标签时:字段.__str__ ==> 字段.__call__ ==> 插件.__call__
    6. __iter__:
    迭代器为什么要一定实现__iter__方法(为什么要返回自身) 应用场景:wtforms中BaseForm中循环所有字段时自定义了__iter__方法
  3. metaclass的作用
    - 作用:用于指定当前类事业那个类来创建
    - 场景:在类创建之前定制的操作
    示例:wtforms中对字段进行排序
  4. super的作用:

    子类继承父类的方法,其继承顺序按照 __mro__来定义
  5. 新式类与经典类的区别
    新式类跟经典类的差别主要是以下几点:
    1. 新式类对象可以直接通过__class__属性获取自身类型:type
    2. 继承搜索的顺序发生了改变,经典类多继承属性搜索顺序 :
    - 先深入继承树左侧,再返回,开始找右侧;
    - 新式类多继承属性搜索顺序: 先水平搜索,然后再向上移动。
    ps:(经典类深度优先,新式类广度优先)
    3. 新式类增加了__slots__内置属性, 可以把实例属性的种类锁定到__slots__规定的范围之中。
    4. 新式类增加了__getattribute__方法 Python 2.x中默认都是经典类,只有显式继承了object才是新式类
    Python 3.x中默认都是新式类,不必显式的继承object
  6. 深度优先和广度优先是什么
    python的类可以继承多个类,python的类如果继承了多个类,那么其寻找的方法有两种:
    - 当类是经典类时:多继承情况下,会按照深度优先的方式查找
    - 当类是新式类时:多继承情况下,会按照广度优先的方式查找
    简单点说就是:经典类是纵向查找,新式类是横向查找
  7. 什么是函数什么是方法?
    from types import MethodType,FunctionType
    
    class func(object):
    def foo(self):
    print(1)
    Fun = func()
    print(type(func.foo))
    >>> <class 'function'>
    print(type(Fun.foo))
    >>> <class 'method'>
    print(isinstance(func.foo,FunctionType))
    >>> True
    print(isinstance(Fun.foo,MethodType))
    >>> True 通过类去调用函数foo时,不需要传self参数。此时foo为函数
    如果通过对象Fun去调用foo时,对象自动传参self。而foo则是一个方法
  8. 手写三个使用不同方法实现的单例模式

    单例模式:一个类只能有一个实例化对象
    应用场景:Django中的admin组件中admin.site()就是由单例模式创建的,其中封装了所有的表对象

    1. 文件导入 :import方法
    # 作为python的模块是天然的单例模式
    class My_Singleton(object):
    def foo(self):
    pass
    my_singleton = My_Singleton()
    # to use
    from mysingleton import my_singleton
    my_singleton.foo() 2. 使用 __new__ 方法:
    --------------------------------(1. # 无法支持多线程 :)------------------------------
    class Singleton(object):
    def __init__(self,name):
    self.name = name
    def __new__(cls, *args, **kwargs):
    if not hasattr(Singleton, "instance"):
    Singleton.instance = object.__new__(cls)
    return Singleton.instance
    # to use :
    obj0 = Singleton("alex")
    obj1 = Singleton("alex")
    obj2 = Singleton("alex") ----------------------------------(2. # 支持多线程:)---------------------------------
    import threading
    class Singleton(object):
    instance_lock = threading.Lock() # 为线程加互斥锁
    def __init__(self):
    pass
    def __new__(cls, *args, **kwargs):
    if not hasattr(Singleton, "instance"):
    with Singleton.instance_lock:
    if not hasattr(Singleton, "instance"):
    Singleton.instance = object.__new__(cls)
    return Singleton.instance
    return Singleton.instance
    def task():
    obj = Singleton()
    print(obj)
    for i in range(5):
    t = threading.Thread(target=task)
    t.start() 3. 使用类实现
    --------------------------------(1. # 无法支持多线程 :)------------------------------
    import threading
    class Singleton(object):
    def __init__(self):
    pass
    @classmethod
    def instance(cls, *args, **kwargs):
    if not hasattr(Singleton, "_instance"):
    Singleton._instance = Singleton(*args, **kwargs)
    return Singleton._instance
    # to use
    obj = Singleton.instance()
    obj2 = Singleton.instance()
    print(id(obj), id(obj2))
    ----------------------------------(2. # 支持多线程:)---------------------------------
    import time
    import threading
    class Singleton(object):
    _instance_lock = threading.Lock()
    def __init__(self):
    time.sleep(1)
    @classmethod
    def instance(cls, *args, **kwargs):
    if not hasattr(Singleton, "_instance"):
    with Singleton._instance_lock:
    if not hasattr(Singleton, "_instance"):
    Singleton._instance = Singleton(*args, **kwargs)
    return Singleton._instance
    # 第一次调用
    def task(arg):
    obj = Singleton.instance()
    print(obj)
    for i in range(10):
    t = threading.Thread(target=task,args=[i,])
    t.start()
    # 第二次调用
    time.sleep(20)
    obj = Singleton.instance()
    obj2 = Singleton.instance()
    print(id(obj, id(obj2) 4. 基于metaclass
    --------------------------------------( 方法一 )--------------------------------------
    # 创建对象
    class SingletonType(type):
    def __call__(cls, *args, **kwargs):
    obj = super(SingletonType,cls).__call__(*args, **kwargs) #type类帮创建__new__和__init__并返回
    return obj
    class Foo(metaclass=SingletonType):
    def __init__(self,name):
    self.name = name
    # to use
    obj = Foo("alex")
    print(id(obj1))
    --------------------------------------( 方法二 )-------------------------------------- import threading
    class SingletonType(type):
    _instance_lock = threading.Lock()
    def __call__(cls, *args, **kwargs):
    if not hasattr(cls, "_instance"):
    with SingletonType._instance_lock:
    if not hasattr(cls, "_instance"):
    cls._instance = super(SingletonType,cls).__call__(*args, **kwargs)
    return cls._instance
    class Foo(metaclass=SingletonType):
    def __init__(self,name):
    self.name = name
    # to use
    obj1 = Foo('name')
    obj2 = Foo('name')
    print(id(obj1),id(obj2))
  9. __new__, __init__的区别

    1. __new__是一个静态方法,而__init__是一个实例方法.
    2. __new__方法会返回一个创建的实例,而__init__什么都不返回.
    3. 只有在__new__返回一个cls的实例时后面的__init__才能被调用.
    4. 当创建一个新实例时调用__new__,初始化一个实例时用__init__.
    5. 继承自object的新式类才有__new__
    6. __new__至少要有一个参数cls,代表当前类,此参数在实例化时由Python解释器自动识别
    7. __new__必须要有返回值,返回实例化出来的实例,这点在自己实现__new__时要特别注意,
      可以return父类(通过super(当前类名, cls))__new__出来的实例,或者直接是object的__new__出来的实例
    8. __init__有一个参数self,就是这个__new__返回的实例,__init__在__new__的基础上可以完成一些其它初始化的动作,__init__不需要返回值
    9. 如果__new__创建的是当前类的实例,会自动调用__init__函数,通过return语句里面调用的__new__函数的第一个参数是cls来保证是当前类实例,
    10. 如果是其他类的类名,;那么实际创建返回的就是其他类的实例,其实就不会调用当前类的__init__函数,也不会调用其他类的__init__函数。

    new与init的关系:

    1. new优于init加载执行

    2. 只能通过重写new方法来自定义不可变的类对象:(int,str,tuple),--->init方法不行

    3. 通过new方法可以实现单例模式

    lass Singleton(object):

    def __new__(cls):

    # 关键在于这,每一次实例化的时候,我们都只会返回这同一个instance对象

    if not hasattr(cls, 'instance'):

    cls.instance = super(Singleton, cls).__new__(cls)

    return cls.instance

    obj1 = Singleton()

    obj2 = Singleton()

    obj1.attr1 = 'value1'

    print obj1.attr1, obj2.attr1

    print obj1 is obj2

  10. 知道有哪些类的双下划线方法,并说明作用,返回值?
    https://www.zybuluo.com/kingwhite/note/136247
  11. 面向对象中super的作用?
    用于执行子类继承基类的方法
    
  12. 123
  13. 123
  14. 123

模块 ( 26 )

  1. 你的常用模块都有哪些 ( 1 )

    copy : 用于深浅拷贝
    os :与操作系统交互的一个接口 比如用来处理文件和目录
    random :随机模块
    sys:负责程序与python解释器的交互,提供了一系列的函数和变量,用于操控python的运行时环境。
    json:序列化
    re : 正则模块
    logging : 日志模块
    requests: 爬取数据
    timeit :
    subprocess:与OS模块相同,区别与异步提交命令不等待输出。与OS模块的区别

copy模块 ( 1 )

  1. 浅拷贝与深拷贝的实现方式及区别,如果你来设计Deepcopy,如何实现
    浅拷贝:只拷贝父对象,不会拷贝对象的内部的子对象(父对象不同,子对象进行引用,ID相同)

    >>> a = [1,[1,3],3]
    >>> import copy
    >>> b = copy.copy(a)
    >>> b
    [1, [1, 3], 3]
    >>> a[1].append(3)
    >>> b
    [1, [1, 3, 3], 3]
    <>>> a
    [1, [1, 3, 3], 3]

    深拷贝:拷贝对象及其子对象(父, 子对象不同)

    >>> a = [1,[1,2],3]
    >>> import copy
    >>> b = copy.deepcopy(a)
    >>> a[1].append(3)
    >>> b
    [1, [1, 2], 3]
    >>> a
    [1, [1, 2, 3], 3]

    如何进行实现:

    deepcopy优化版:
    class FiveCardStudInfo(roomai.abstract.AbstractInfo):
    public_state = None
    person_state = None
    def __deepcopy__(self, memodict={}):
    info = FiveCardStudInfo()
    info.public_state = self.public_state.__deepcopy__()
    info.public_state = self.person_state.__deepcopy__()
    return info

     由于深拷贝需要维护一个 memo 用于记录已经拷贝的对象,所以这也是它比较慢的原因

OS模块 ( 3 )

  1. 你知道哪些OS模块的方法

    os.remove(‘path/filename’)  # 删除文件
    os.rename(oldname, newname) # 重命名文件
    os.walk() # 生成目录树下的所有文件名
    os.chdir('dirname') # 改变目录
    os.getcwd() # 取得当前工作目录
    os.path.getsize() # 返回文件大小
  2. 创建、删除文件

    1. # 创建一个文件
    2. open("chao.txt","w",encoding="utf-8")
    3. import os
    #删除文件
    4. os.remove("chao.txt")
  3. 给出路径找文件

    --------------------------------( 方法一 )------------------------------
    使用os.walk:
    file-- 是你所要便利的目录的地址, 返回的是一个三元组(root,dirs,files)。 root 所指的是当前正在遍历的这个文件夹的本身的地址
    dirs 是一个 list ,内容是该文件夹中所有的目录的名字(不包括子目录)
    files 同样是 list , 内容是该文件夹中所有的文件(不包括子目录)
    def open_2(file): for root, dirs , files in os.walk(file):
    print("ss",files)
    for filename in files:
    print(os.path.abspath(os.path.join(root, filename))) #返回绝对路径 open_2("F:\搜索") --------------------------------( 方法二 )------------------------------
    import os
    def open(files): for dir_file in os.listdir(files):
    # print("ss",dir_file) #递归获取所有文件夹和文件
    files_dir_file = os.path.join(files, dir_file) if os.path.isdir(files_dir_file): #是不是文件夹
    open(files_dir_file)
    else:
    print(files_dir_file) open("F:\搜索") 并将下面的所有文件内容写入到一个文件中
    def open_2(file):
    for root, dirs , files in os.walk(file):
    for filename in files:
    with open(os.path.abspath(os.path.join(root, filename)), "r") as f:
    for i in f.readlines():
    print(i)
    with open("./cao.txt","a",encoding="utf-8") as f2:
    f2.write(i)
    f2.write("\n")
    open_2("F:\搜索")
  4. 使用python打印路径下的所有文件
    # 方法一:(面试要求不使用os.walk)
    def print_directory_contents(sPath):
    import os for sChild in os.listdir(sPath):
    sChildPath = os.path.join(sPath, sChild)
    if os.path.isdir(sChildPath):
    print_directory_contents(sChildPath)
    else:
    print(sChildPath) # 方法二:(使用os.walk)
    def print_directory_contents(sPath):
    import os
    for root, _, filenames in os.walk(sPath):
    for filename in filenames:
    print(os.path.abspath(os.path.join(root, filename))) print_directory_contents('.')
  5. 如何使⽤python删除⼀个⽂件

    import os
    file = r'D:\test.txt'
    if os.path.exists(file):
    os.remove(file)
    print('delete success')
    else:
    print('no such file:%s' % file)
  6. 123

random模块

  • 如何⽣成⼀个随机数?

    import random
    
    print(random.random())          # 用于生成一个0到1的随机符点数: 0 <= n < 1.0
    print(random.randint(1, 1000)) # 用于生成一个指定范围内的整数
  • 123
  • 123

co

re模块 ( 4 )

  1. re模块的基本方法:

    .     匹配除换行符以外的任意字符
    \w 匹配字母或数字或下划线
    \s 匹配任意的空白符
    \d 匹配数字
    \n 匹配一个换行符
    \t 匹配一个制表符
    \b 匹配一个单词的结尾
    ^ 匹配字符串的开始
    $ 匹配字符串的结尾
    \W
    匹配非字母或数字或下划线
    \D
    匹配非数字
    \S
    匹配非空白符
    a|b
    匹配字符a或字符b
    ()
    匹配括号内的表达式,也表示一个组
    [...]
    匹配字符组中的字符
    [^...]
    匹配除了字符组中字符的所有字符 用法说明
    * 重复零次或更多次
    + 重复一次或更多次
    ? 重复零次或一次
    {n} 重复n次
    {n,} 重复n次或更多次
    {n,m} 重复n到m次
  2. 手写正则

    匹配邮箱:
    - [\w!#$%&'*+/=?^_`{|}~-]+(?:\.[\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\w](?:[\w-]*[\w])?\.)+[\w](?:[\w-]*[\w])?
    - \w[-\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\.)+[A-Za-z]{2,14}
    匹配URL地址:
    - [a-zA-z]+://[^\s]*
    匹配国内手机号:
    - \d{3}\d{8}|\d{4}\{7,8}
    匹配身份证号码:
    - ^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)$
  3. match和search的区别

    - re.match :只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;
    - re.search:匹配整个字符串,直到找到一个匹配。

    应用示例:

    import re
    s = "fnfffidvvgf"
    m = re.match("fi",s)
    print(m)
    >>> #None
    s = re.search("fi",s).group()
    print(s)
    >>> #fi
  4. 贪婪匹配与非贪婪匹配
    - 匹配0次或多次 <.*>
    - 非贪婪匹配:匹配0次或1次 <.?>

functools模块

  1. 是否使⽤过functools中的函数?其作⽤是什么?

    # 用于修复装饰器
    import functools
    def deco(func):
    @functools.wraps(func) # 加在最内层函数正上方
    def wrapper(*args, **kwargs):
    return func(*args, **kwargs)
    return wrapper @deco
    def index():
    '''哈哈哈哈'''
    x = 10
    print('from index') print(index.__name__)
    print(index.__doc__) # 加@functools.wraps
    # index
    # 哈哈哈哈 # 不加@functools.wraps
    # wrapper
    # None
  2. reduce
    在Python 3里,reduce()函数已经被从全局名字空间里移除了,它现在被放置在fucntools模块里 用的话要 先引入:
    >>> from functools import reduce reduce函数,reduce函数会对参数序列中元素进行累积。
    reduce函数的定义:
    reduce(function, sequence[, initial]) -> value
    function参数是一个有两个参数的函数,reduce依次从sequence中取一个元素,和上一次调用function的结果做参数再次调用function。
    第一次调用function时,如果提供initial参数,会以sequence中的第一个元素和initial作为参数调用function,否则会以序列sequence中的前两个元素做参数调用function。
    reduce(lambda x, y: x + y, [2, 3, 4, 5, 6], 1)
    结果为21( (((((1+2)+3)+4)+5)+6) )
    reduce(lambda x, y: x + y, [2, 3, 4, 5, 6])
    结果为20
  3. 123

其他函数

  1. 如何判断是函数还是方法

    from types import FunctionType
    from types import MethodType print(isinstance(obj.func, FunctionType)) # False
    print(isinstance(obj.func, MethodType)) # True

其他

  1. 你知道几种设计模式

    设计模式分为三大类:
    创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
    结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
    行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
    其实还有两类:并发型模式和线程池模式。
  2. 编码和解码了解过么

  3. 什么是装饰器,如果想在函数之后进行装饰应该怎么做
    一个函数,想在运行时动态的增加功能,又不会改动函数本身的代码

  4. 使用装饰器的单例模式和使用其他方法的单例,在后续使用中有什么区别

  5. 介绍下垃圾回收机制引用计数 / 分代回收 / 孤立引用环

    引⽤计数机制的优点:
    1、简单
    2、实时性:⼀旦没有引⽤,内存就直接释放了。不⽤像其他机制等到特定时机。实时性还带来⼀个好处:处理回收内存的时间分摊到了平时。
    引⽤计数机制的缺点:
    1、维护引⽤计数
    2、消耗资源循环引⽤
    list1 = []; list2 =[]
    list1.append(list2); list2.append(list1)
    3、list1与list2相互引⽤,如果不存在其他对象对他们的引用,list1与list2的引用计数也仍然1,所占⽤的内存永远无法被回收,这将是致命的。
    对于如今的强⼤硬件,缺点1尚可接受,但是循环引⽤导致内存泄露,注定python会将引⼊新的回收机制。(分代收集)
    有三种情况会触发垃圾回收:
    1、当 gc 模块的计数器达到阀值的时候,自动回收垃圾
    2、调⽤ gc.collect(),手动回收垃圾
    3、程序退出的时候,python解释器来回收垃圾
  6. 多进程与多线程的区别CPU密集型应用适合用什么

    多线程可以共享全局变量,多进程不能。多线程中,所有子线程的进程号相同;多进程中,不同的子进程进程号不同。
    python的threading和multiprocessing模块
  7. 进程通信有哪几种方式

    无名管道( pipe ): - 管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
    高级管道(popen): - 将另一个程序当做一个新的进程在当前程序进程中启动,则它算是当前程序的子进程,这种方式我们成为高级管道方式。
    有名管道(named pipe) : - 有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
    消息队列( message queue ) : - 消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
    信号量( semophore ) :- 信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
    信号 ( sinal ) : - 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。
    共享内存( shared memory ) : - 共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号两,配合使用,来实现进程间的同步和通信。
    套接字( socket ):- 套解口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同机器间的进程通信。
  8. 介绍下协程,为何比线程还快
    关于GIL锁的解释协程的优缺点

  9. 写出将IP地址127.0.0.1转换为32位二进制和数的函数
  10. 单向链表和双向链表
  11. 写出将IPv4地址转换为IPv6的函数
  12. 面向对象的应用场景
    # 需要传过多的参数:
    class Foo(object):
    def __init__(self, a1, a2, a3, ... , an):
    self.a1 = a1
    self.a2 = a2
    ...
    def index(self):
    pass # 给了一些值,对数据进行加工:Django的自定义分页
    class Foo(object):
    def __init__(self, a1, a2, a3, ... , an):
    self.a1 = a1
    self.a2 = a2
    ...
    def index(self):
    return self.a1 + self.a2
  13.  
  14. QAQ

RESTful ( 12 )

  1. 谈谈你对rest api的认识
  2. 用过哪些rest 框架
    - Django的rest_framework
    - 原生CBV
  3. 不使用rest_framework
    利用Django的CBV来实现RESTful,使开发者代码会多一些。
    通过使用rest_framework框架提高开发效率。
  4. 这个框架使用最多的是什么?
    Serializers
    用户登录认证
    分页
    频率等
  5. rest_framework视图中你都用过哪些基类
    GenericAPIView
  6. !rest_framework的GenericAPIView都继承过哪些类
  7. rest_framework框架有哪些优点?
  8. rest_framework都有哪些组件?
  9. - 路由:自动帮助开发者快速为一个视图创建四个URL
    - 版本
    - URL
    - GET
    - 请求头
    - 认证
    - !认证的流程是什么
    - 权限
    - 权限能不能在中间件做
    - 访问频率的控制
    - 视图
    - 解析器:根据Content-Type请求体中的格式数据进行处理。request,data
    - 分页
    - 序列化
    - 序列化
    - source
    - 定义方法
    - 请求的数据格式校验
    - 渲染器
  10. 频率组件是怎么做的
  11. 限制的频率是多少?
    1分钟:60-80次/每秒钟1-2次
  12. 什么是幂等性?
    幂等性:
    一个接口进行一次或多次访问,对资源不造成影响(是否会对资源造成二次伤害),那么我们就认为这个接口具有幂等性。
    例如:GET:
    putdelete请求
    非幂等性:
    例如:请求等
    具有争议性的请求:
    patch:
  13. 0
  14. 2

算法排序部分(9)

  1. 手写快排;堆排;几种常用排序的算法复杂度是多少;快排平均复杂度多少,最坏情况如何优化;
  2. 手写:已知一个长度n的无序列表,元素均是数字,要求把所有间隔为d的组合找出来,你写的解法算法复杂度多少;
  3. 手写:一个列表A=[A1,A2,…,An],要求把列表中所有的组合情况打印出来;
  4. 手写:用一行python写出1+2+3+…+10**8 ;
  5. 手写python:用递归的方式判断字符串是否为回文;
  6. 单向链表长度未知,如何判断其中是否有环;
  7. 单向链表如何使用快速排序算法进行排序;
  8. 手写:一个长度n的无序数字元素列表,如何求中位数,如何尽快的估算中位数,你的算法复杂度是多少;
  9. 如何遍历一个内部未知的文件夹(两种树的优先遍历方式)

网络基础部分(11)

  1. TCP/IP分别在模型的哪一层;
  2. socket长连接是什么意思;
  3. select和epoll你了解么,区别在哪;
  4. TCP UDP区别;三次握手四次挥手讲一下;
    # TCP三次握手
    # 1. 客户 --> 服务:SYN=1(发起新连接) seq = J(随机值)
    # 2. 服务 --> 客户:
    # SYN=1,
    # ACK=1(确认接受这次连接请求),
    # ack=J+1(从广播的众多连接请求响应中中发现针对自己的响应,网络是广播的)
    # seq = K
    # 3. 客户 --> 服务
    # ACK=1(我知道你接受我了)
    # ack=K+1(服务端从众多的连接连理响应中发现针对自己的)
    # 当然,第三次握手消息,服务端也可能没有接收到,但不可能两边一直这样ACK下
    # 去。但是还可以基于超时时间,重新发起连接请求。
  5. TIME_WAIT过多是因为什么;
  6. http一次连接的全过程:你来说下从用户发起request——到用户接收到response时的全过程;
  7. http连接方式。get和post的区别,你还了解其他的方式么;
  8. restful你知道么;
  9. 状态码你知道多少,比如200/403/404/504等等# 更多信息跳转w3
  10. TCP/UDP
  11. socket连接和HTTP连接的区别
  12. Q^Q

HTTP部分( 11 )

  1. 常用的HTTP方法有哪些?

    GET: 用于请求访问已经被URI(统一资源标识符)识别的资源,可以通过URL传参给服务器
    POST:用于传输信息给服务器,主要功能与GET方法类似,但一般推荐使用POST方式。
    PUT: 传输文件,报文主体中包含文件内容,保存到对应URI位置。
    HEAD: 获得报文首部,与GET方法类似,只是不返回报文主体,一般用于验证URI是否有效。
    DELETE:删除文件,与PUT方法相反,删除对应URI位置的文件。
    OPTIONS:查询相应URI支持的HTTP方法。
  2. GET方法与POST方法的区别
    区别一:
    - get重点在从服务器上获取资源,post重点在向服务器发送数据;
    区别二:
    - get传输数据是通过URL请求,以field(字段)= value的形式,置于URL后,并用"?"连接,多个请求数据间用"&"连接,
    如http://127.0.0.1/Test/login.action?name=admin&password=admin,这个过程用户是可见的;
    - post传输数据通过Http的post机制,将字段与对应值封存在请求实体中发送给服务器,这个过程对用户是不可见的;
    区别三:
    - Get传输的数据量小,因为受URL长度限制,但效率较高;
    - Post可以传输大量数据,所以上传文件时只能用Post方式;
    区别四:
    - get是不安全的,因为URL是可见的,可能会泄露私密信息,如密码等;
    - post较get安全性较高;
    区别五:
    - get方式只能支持ASCII字符,向服务器传的中文字符可能会乱码。
    - post支持标准字符集,可以正确传递中文字符。
  3. HTTP请求报文与响应报文格式
    请求报文包含三部分:
    - 请求行:包含请求方法、URI、HTTP版本信息
    - 请求首部字段
    - 请求内容实体
    响应报文包含三部分:
    - 状态行:包含HTTP版本、状态码、状态码的原因短语
    - 响应首部字段
    - 响应内容实体
  4. 常见的HTTP相应状态码
    200:请求被正常处理
    204:请求被受理但没有资源可以返回
    206:客户端只是请求资源的一部分,服务器只对请求的部分资源执行GET方法,相应报文中通过Content-Range指定范围的资源。
    301:永久性重定向
    302:临时重定向
    303:与302状态码有相似功能,只是它希望客户端在请求一个URI的时候,能通过GET方法重定向到另一个URI上
    304:发送附带条件的请求时,条件不满足时返回,与重定向无关
    307:临时重定向,与302类似,只是强制要求使用POST方法
    400:请求报文语法有误,服务器无法识别
    401:请求需要认证
    403:请求的对应资源禁止被访问
    404:服务器无法找到对应资源
    500:服务器内部错误
    503:服务器正忙
  5. HTTP1.1版本新特性
    1. 默认持久连接节省通信量,只要客户端服务端任意一端没有明确提出断开TCP连接,就一直保持连接,可以发送多次HTTP请求
    2. 管线化,客户端可以同时发出多个HTTP请求,而不用一个个等待响应
    3. 断点续传原理
  6. 常见HTTP首部字段
    1. 通用首部字段(请求报文与响应报文都会使用的首部字段)
    - Date:创建报文时间
    - Connection:连接的管理
    - Cache-Control:缓存的控制
    - Transfer-Encoding:报文主体的传输编码方式
    2. 请求首部字段(请求报文会使用的首部字段)
    - Host:请求资源所在服务器
    - Accept:可处理的媒体类型
    - Accept-Charset:可接收的字符集
    - Accept-Encoding:可接受的内容编码
    - Accept-Language:可接受的自然语言
    3. 响应首部字段(响应报文会使用的首部字段)
    - Accept-Ranges:可接受的字节范围
    - Location:令客户端重新定向到的URI
    - Server:HTTP服务器的安装信息
    4. 实体首部字段(请求报文与响应报文的的实体部分使用的首部字段)
    - Allow:资源可支持的HTTP方法
    - Content-Type:实体主类的类型
    - Content-Encoding:实体主体适用的编码方式
    - Content-Language:实体主体的自然语言
    - Content-Length:实体主体的的字节数
    - Content-Range:实体主体的位置范围,一般用于发出部分请求时使用
  7. HTTP与HTTPS的区别
    对传输内容加密
    端口:
    HTTP:80
    HTTPS:443
    自定义证书
  8. HTTP的缺点与HTTPS
    1. 通信使用明文不加密,内容可能被窃听
    2. 不验证通信方身份,可能遭到伪装
    3. 无法验证报文完整性,可能被篡改
    # HTTPS就是HTTP加上加密处理(一般是SSL安全通信线路)+认证+完整性保护
  9. HTTP优化

    利用负载均衡优化和加速HTTP应用

    利用HTTP Cache来优化网站

  10. 从浏览器输入域名网址到看到页面都发生了什么

    1.浏览器向DNS服务器询问域名对应的IP地址
    
    2.得到域名对应的IP地址后,组装HTTP请求报文
    
    3.由TCP协议将请求报文分割成多个报文段,可靠的传给对方
    
    4.由IP协议搜索对方地址,并传送报文,此过程可能经过多个路由器
    
    5.服务器端的TCP从对方接收到报文
    
    6.服务器端的HTTP解析请求报文,处理并生成响应报文
    
    7.按照相反的顺序,将响应报文发回给浏览器
    
    8.浏览器根据响应报文解析数据(一般为html文档),并渲染页面,文档中也很可能引用了其他资源,这些资源同样使用HTTP协议想服务器请求
    
  11. 什么是websocket
    websocket是一种类似HTTP的协议:
    - 让C/S创建链接不断开,以此可以完成:S向C主动推送消息
    - websocket协议额外做的一些前提操作:
    - 握手,连接前进行校验
    - 发送数据,进行加密
    websocket的本质
    ...
    应用场景:
    5月17日13:19:13,141
    - Django: channel
    - Flask : gevent-websocket
    - tornado:内置

    QAQ

  12. q^q

数据库部分( 20 )

  1. MySQL有几种引擎查询表数据练习题

    InnoDB:
    - 支持事务
    - 行锁/表锁
    - 表锁:
    - select * from tb for update
    - 行锁:
    - select * from tb where id=2 for update;
    MyISAM:
    - 全文索引<
    - 表锁
    - 查询速度快
    - 表锁语句:
    - select * from tb for update; - Innodb是索引和数据是紧密捆绑的,没有使用压缩;
    - 而MyISAM的索引和数据是分开的,并且索引是有压缩的,内存使用率就对应提高了不少,能加载更多索引,因此,用MyISAM可节省不少硬盘空间。
  2. 数据库中函数用过哪些?
    聚合函数:max/sum/min/avg
    时间格式化:date_format
    字符串拼接:concat
  3. 索引有哪几种?区别是什么?
    单列:B+树/哈希索引  --> 查询速度快更新速度慢
    - 普通索引 :加速查找
    - 唯一索引 :加速查询 + 约束(不能重复)
    - 主键索引 :加速查询 + 约束(不能重复) + 不能为空
    - 全文索引 :
    多列:遵循最左前缀规则
    - 联合索引 :
    - 联合唯一索引 :
    其他:
    - 索引合并 :利用多个单例索引查询
    - 覆盖索引 :在索引表中就能将想要的数据查询到
    - 组合索引遵循最左前缀规则
    如果组合索引为:(name,email)
    name and email -- 使用索引
    name -- 使用索引
    email -- 不使用索引
  4. 慢日志如何开启?
    slow_query_log = OFF                 # 是否开启慢日志记录
    long_query_time = 2 # 时间限制,超过此时间,则记录
    slow_query_log_file = /usr/slow.log # 日志文件
    log_queries_not_using_indexes = OFF # 为使用索引的搜索是否记录
  5. MySQL锁有几种;死锁是怎么产生的;
    mysql锁能在并发情况下的mysql进行更好的优化
    MySQL有三种锁的级别:页级、表级、行级,这3种锁的特性可大致归纳如下:
    表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。
    行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
    页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。
  6. 为何,以及如何分区、分表;
  7. MySQL的char varchar text的区别;
  8. select的几种区别
    1. select 1与select * 的区别:
    “selelct 常量 from 表名” 对应所有行,返回的永远只有一个值,即常量 ,所以一般只用来判断是否有表记录;
    而“select * from 表名” 是返回所有行的所有列。
    性能上的差异,关键看from和where子句。如果where条件中可以通过索引,那显然 “selelct 常量 from 表名” 的性能比“select * from 表名” 好。
    2. select count(1) 与select count(*) 的区别 :
    性能上的差异,跟表结构有关系:
    如果表中没有主键,那么count(1)比count(*)快
    如果有主键,那么count(主键,联合主键)比count(*)快
    如果表中只有一个字段,count(*)最快
    3. select sum(1)的使用:
    select count(*)返回所有满足条件的记录数,此时等同于select sum(1)
    但是sum()可以传任意数字,负数、浮点数都可以,返回的值是传入值n*满足条件记录数m
  9. 存储过程和函数的区别
    函数:
    - 参数
    - 返回值:return
    存储过程:
    - 参数
    - 返回值:out/inout
    - 返回结果集:select * from tb;
  10. 什么是视图
    虚拟表 --> 通过SQL帮助我们实时查询数据
  11. 什么是触发器
    在对表进行 增删改查 前后定义一些SQL操作
  12. 对前端产生的分页是如何处理的
    - 数据库分页
    存在问题:
    查询的页面数越大,速度就会越慢,这是因为每次数据库都会从第一条开始扫描
    selsct * from tb limit 3 offset 5
    models.User.object.all()[0:10] 解决方法:
    根据业务场景来说:
    1.如果业务对历史数据不要求的话,就显示一定的页数,就可以避免这样的问题
    2.记录当前页数据id的最大最小值,根据记录的id和需要查询的范围来定。
    但是在url上面会有page的值,如果用户随意改url上的页码的值的时候,可以参考restfromwork的分页来做,
    对当前的url进行加密,加密之后它里面就带了当前页的最大和最小id,解密出来之后就可以直接拿来用,而且用户也没有办法在url上随便修改了
  13. 了解join么,有几种,有何区别,A LEFT JOIN B,查询的结果中,B没有的那部分是如何显示的(NULL);
  14. 写出SQL语句:获取一条name="alex"的数据
    select * from tb name='alex' limit 1
  15. BTree索引和hash索引的区别(在磁盘结构上的区别);
  16. 手写:如何对查询命令进行优化;
    1. 不用 select *
    2. 固定长度字段列,往前放
    3. char 和 varchar
    4. 固定数据放入内存 choice
    5. 数据库读写分离
    6. 分库:当数据库中表过多,将表分到不同的数据库()
    7. 分表:
    - 水平分表:将某些列拆分到另一张表:博客+博客详细
    - 垂直分表:将一些历史信息分到另一张表中:历史账单
    8. 缓存:利用redis、memcache进行存储
    ps:当缓存宕机,如果没有进行持久化则将所有请求转接MySQL,
    而MySQL承受不了压力时会造成无法启动
    9. 其它
    - 慢日志
    - 执行计划
    10. 分页
  17. NoSQL了解么,和关系数据库的区别;
  18. redis有几种常用存储类型;
  19. 乐观锁和悲观锁
  20. 触发器是什么?
  21. QAQ

Linux部分( 4 )

  1. 讲一下你常用的Linux/git命令和作用;
  2. 查看当前进程是用什么命令,除了文件相关的操作外,你平时还有什么操作命令;
  3. Apache和Nginx的区别
  4. 介绍下中间人攻击:
    # 中间人攻击(Man-in-the-middle attack,通常缩写为MITM)是指攻击者与通讯的两端分别创建独立的联系,并交换其所收到的数据,
    使通讯的两端认为他们正在通过一个私密的连接与对方直接对话,但事实上整个会话都被攻击者完全控制。
  5. 1

前端部分( 2 )

  1. 你用过什么框架和类库

    - jQuery
    - BootStrap
    - Vue.js、React、Angular.js
  2. 什么是响应式布局
     通过浏览器和设备分辨率的改变做出相应的变化 
    本质是通过 @media属性来完成:
    <style>
    body{
    margin:0;}
    .pg-header{
    background-color:red;
    height: 48px;}
    @media( min-width: 768px ){
    .pg-header{background-color: green;}}
    @media( min-width: 992px ){
    .pg-header{background-color: pink;}}
    </style>

django项目部分( 19 )

  1. 简单的介绍下你在公司的项目,不管是不是后端相关的,主要是要体现出你干了什么;
  2. 你在项目中遇到最难的部分是什么,你是怎么解决的;
  3. Django和Flask框架的区别
    Django:
    - 内置很多组件:
    - ORM、admin、Form、ModelForm、中间件、信号、缓存、csrf等
    Flask:
    - 一个轻量级框架内置组件少,可扩展很多第三方组件:
    - flask-session、flask-script、flask-redis、flask-flask-migrate
    - flask-SQLAlchemy、wtforms、blinker 两个框架都是基于wsgi协议实现的,默认使用的wsgi模块不一样,
    还有一个显著的特点:处理请求的方式不一样
    - Django:通过将请求封装成request对象,再通过参数进行传递
    - flask: 通过上下文管理实现
    延伸:
    - Django组件
    - flask组件、用途
    - wsgi
    - 上下文管理
  4. MVC / MTV;
  5. Django请求生命周期
    1. wsgi:创建socket服务端,用于接收用户请求并对请求进行初次封装
    2. 中间件:对所有请求到来之前,响应之前定制一些操作
    3. 路由: 匹配路由,在url和视图函数对应关系中,根据当前请求url找到相应的函数
    4. 视图函数:执行视图函数,业务处理【通过ORM去数据库中获取数据,再去拿到模板,然后将数据和模板进行渲染】
    5. 在经过中间件
    6. 通过wsgi将响应返回给用户
  6. 什么是wsgi
    是web服务网关接口,是一套协议。以下模块实现了wsgi协议:
    - wsgiref :性能低,易配置
    - werkzurg
    - uwsgi
    以上模块本质:实现socket监听请求,获取请求后将数据封装,然后交给web框架处理
    详解:
    本质是编写了socket服务端,用来监听用户的请求,如果有请求到来,则将请求进行一次封装然后将【请求】交给web框架来进行下一步处理
  7. 中间件是干嘛的;
    所有请求都要穿过中间件:
    - 对所有的请求进行批量处理
    - 在视图函数执行之前后进行一些自定义操作。
  8. 你用中间件做过什么;
    - 解决cors跨域请求
    - csrf
    - csrf的本质:
    - 用户先发送get获取csrf token:Form表单中一个隐藏的标签 + cookie
    - 发起post请求时,需要携带之前发送给用户的csrf token;
    - 在中间件的process_view 方法中进行校验
  9. 中间件中有几个方法分别是什么;(五个方法)
      - process_request(self,request)
    - process_view(self, request, callback, callback_args, callback_kwargs)
    - process_template_response(self,request,response) # 当视图函数的返回值对象中有render方法时,该方法才会被调用
    - process_exception(self, request, exception)
    - process_response(self, request, response)
    中间件的执行流程:
    1 请求先执行所有中间件的process_request,然后做路由匹配,找到函数不执行。
    2 再执行所有的process_view,在执行视图函数。
    3 再执行process_response
    4 如果程序报错执行process_exception
    5 如果程序有render方法则执行process_template_response
  10. 中间件的应用:
    # 为什么要在中间件用这些:
    - 一些内置组件上的应用:
    - csrf
    - session
    缓存
    - 用户登录校验 # 如果不使用就需要为每个函数添加装饰器,太过繁琐。
    - 权限处理 # 用户登录后将权限放到session中,然后再每次请求时都需要判断当前用户是否有权访问当前url,这些检查的东西可以放到中间件中统一处理。
    - session
    - 跨域:
    - 前后端分离时,本地测试开发时使用的
  11. CSRF原理
    目标:防止用户直接向服务端发起POST请求。
    方案:先发送GET请求时,将token保存到:cookie、Form表单中(隐藏的input标签),以后再发送请求时只要携带过来即可。
    问题:如果想后台发送POST请求?
    form表单提交:
    <form method="POST">
    {% csrf_token %}
    <input type='text' name='user' />
    <input type='submit' />
    </form> ajax提交:
    $.ajax({
    url:'/index',
    type:'POST',
    data:{csrfmiddlewaretoken:'{{ csrf_token }}',name:'alex'}
    })
    前提:引入jquery + 引入jquery.cookie
    $.ajax({
    url: 'xx',
    type:'POST',
    data:{name:'oldboyedu'},
    headers:{
    X-CSRFToken: $.cookie('csrftoken')
    },
    dataType:'json', // arg = JSON.parse('{"k1":123}')
    success:function(arg){
    console.log(arg)
    }
    })
    <body>
    <input type="button" onclick="Do1();" value="Do it"/>
    <input type="button" onclick="Do2();" value="Do it"/>
    <input type="button" onclick="Do3();" value="Do it"/> <script src="/static/jquery-3.3.1.min.js"></script>
    <script src="/static/jquery.cookie.js"></script>
    <script>
    $.ajaxSetup({ // 为所有Ajax请求添加函数
    beforeSend: function(xhr, settings) {
    xhr.setRequestHeader("X-CSRFToken", $.cookie('csrftoken'));
    }
    }); function Do1(){
    $.ajax({
    url:"/index/",
    data:{id:1},
    type:'POST',
    success:function(data){
    console.log(data);
    }
    });
    } function Do2(){
    $.ajax({
    url:"/index/",
    data:{id:1},
    type:'POST',
    success:function(data){
    console.log(data);
    }
    });
    } function Do3(){
    $.ajax({
    url:"/index/",
    data:{id:1},
    type:'POST',
    success:function(data){
    console.log(data);
    }
    });
    }
    </script>
    </body>

    优化方案

  12. Django的Form的作用
    1. 帮助我们生成HTML标签
    2. 对用户输入的数据进行校验
    ps:form对象是个可迭代对象
    Q:从数据库获取数据时,下拉框无法实时刷新。
    A:重写构造方法,在构造方法中重新去获取数据
    def __str__(self):
    return self.title
  13. 缓存怎么用;
  14. CSRF是什么,django是如何避免的;XSS呢;
  15. 如果你来设计login,简单的说一下思路;
  16. session和cookie的联系与区别;session为什么说是安全的;
  17. WSGI和Nginx的作用;
  18. 浏览器缓存机制
  19. 你看过django的admin源码么;看过flask的源码么;你如何理解开源;
  20. QAQ

Flask部分( 14 )

  1. FLask和Django的区别

    - 对于Django来说:内部组件全面,自身功能强大,给人一种大而全的感觉,
    ( 你知 或者不知他,Django就在那里,不悲不喜。
    你念 或者不念他,功能就在那里,不來不去。
    你愛 或者不愛他,組件就在那里,不增不減。
    你用,或者不用他,Django就在你手裡。不捨不棄。)
    而Flask:内置组件就很少,但它的第三方组件很多,可扩展性强,还可以自定义组件,
    - 两个框架本身都没有写sockte,都是基于wsgi协议做的,而flask框架中的上下文管理较为耀眼。
     - 相同点:它们两个框架都没有写sockte,都是基于wsgi协议做的
      请求相关数据传递的方式不同:django:通过传递request参数取值
                    flask:见问题二
               组件不同:django组件多
                    flask组件少,第三方组件丰富
  2. 谈谈你对Flask与Django框架的认识
    相同:
    都基于wsgi,
    不同:
    对请求处理不同:Flask基于上下文管理;Django通过传值来处理
    Django功能多,内置组件全面:缺点不能自定义添加或删除组件
    Flask内置组件少,但是可以通过第三方组件来扩展:Flask-email,Flask-SQLAlchemy,Flask-session等
  3. Flask中的session是什么时候创建,什么时候销毁的?
      当请求进来时,会将 requset 和 session 封装为一个 RequestContext 对象,通过 LocalStack 将 RequestContext 放入到Local对象中,
    因为请求第一次来 session 是空值,所以执行 open_session,给 session(uuid4())赋值,再通过视图函数处理,请求响应时执行save.session,
    将签名 session 写入 cookie 中,再将 Local 中的数值pop掉。
  4. Flask为什么把请求放到RequestContext中?
        因为 request 和 session 都是在视图中操作频繁的数据,也是用户请求需要用的数据,
    将 request 和 session 封装在 RequestContext 中 top,pop 一次就可以完成,而单独不封装在一起就会多次操作,
  5. flask中一共有几个LocalStack和Local对象
    两个LocalStack,两个Local:
    - request、session 共同用一个 LocalStack 和 Local
    - g、app 共同用一个 Localstack 和 Local
  6. Flask上下文管理是如何实现的:
    - 前提:记得不太清楚了,/or 最近刚看过
     简单来说,falsk上下文管理可以分为三个阶段:
      1、请求进来时,将请求相关的数据放入上下文管理中
      2、在视图函数中,要去上下文管理中取值
      3、请求响应,要将上下文管理中的数据清除
     详细点来说:
      1、请求刚进来,将request,session封装在RequestContext类中,app,g封装在AppContext类中,并通过LocalStack将requestcontext和appcontext放入Local类中
      2、视图函数中,通过localproxy--->偏函数--->localstack--->local取值
      3、请求相应时,先执行save.session()再各自执行pop(),将local中的数据清除
  7. Local的作用?
    - 用于保存:
    - 请求上下文对象
    - App上下文对象
    - 并且可以做到"线程"间的数据隔离。
    线程:threading.local
    协程:greenlet.get_current as get_get_ident
    - localstack 的源码与 threading.local(线程处理)的作用相似,
    不同之处是 Local 是通过 greenlet(协程)获取唯一标识,粒度更细
  8. LocalStack的作用?
    将local对象中的数据维护成一个栈【ctx,ctx】(先进后出)
    {
    “协程或线程的唯一标识”: { stack:[ctx,ctx,ctx,] }
    }
  9. 为什么要将Local对象中的数据维护成一个栈
    当是web应用时:不管是单线程还是多线程,栈中只有一个数据
    - 服务端单线程:
      {
    111:{stack: [ctx, ]}
      }
    - 服务端多线程:
      {
    111:{stack: [ctx, ]}
    112:{stack: [ctx, ]}
      }
    离线脚本:可以在栈中放入多个数据,在任何情况下都可以获取到当前app的请求和响应
    with app01.app_context():
    print(current_app)
       with app02.app_context():
    print(current_app)
    print(current_app)
  10. 什么是G?
      - G 相当于一次请求的全局变量,当请求进来时将 G 和 current_app 封装为一个 APPContext 类,在通过 LocalStack 将 Appcontext 放入 Local 中,
    取值时通过偏函数,LocalStack、loca 中取值,响应时将 Local 中的 g 数据删除:
    - 应用场景:
    befor_request + G = 权限认证系统
  11. 如何获取session/g
    通过 、偏函数(lookup_req_object)、Localstack、Local 取值
  12. Flask内置功能:
    - 内置组件
    - 配置 - 路由 - 视图
    - 模板 - session - 蓝图
    - 闪现 - 装饰器 - 中间件
    - 第三方组件
    - Flask-session # 将原来保存在cookie中的session数据,放到Redis/memcache/文件/数据库中
    - Flask-migrate # 做数据库迁移
    - Flask-script #
    - Flask-SQLAlchemy # ORM
    - blinker
    - 公共:
    - DButils # 数据库连接池: 两种模式; 为每个参数设置一个连接/共享一个连接;全局参数
    - wtforms # form组件:做表单验证+生成HTML标签
    - gevent-websocket
    - 自定义组件:
    - flask-login
  13. 手写:自己写一个类+列表, 实现栈的功能(LocalStack)
    分组函数 : group by 字段  having   判断条件   (固定语法)分组和聚合函数搭配
    分组函数 : group by 字段 having 判断条件 (固定语法)分组和聚合函数搭配
    class Stack():
    def __init__(self,size):
    self.size=size
    self.stack=[] def getstack(self):
    """
    #获取栈当前数据
    :return:
    """
    return self.stack def __str__(self):
    return str(self.stack) def top(self,x):
    # 入栈之前检查栈是否已满
    if self.isfull():
    raise Exception("stack is full")
    else:
    self.stack.append(x) def pop(self):
    """
    # 出栈之前检查栈是否已空
    :return:
    """
    if self.isempty():
    raise Exception("stack is empty")
    else:
    self.stack.pop() def isfull(self):
    """
    判断栈满
    :return:
    """
    if len(self.stack)==self.size:
    return True
    return False def isempty(self):
    """
    判断栈空
    :return:
    """
    if len(self.stack)==0:
    return True
    return False if __name__ == '__main__' :
    stack=Stack(4) for i in range(11):
    stack.top(i)
    print(stack.getstack()) for i in range(3):
    stack.pop()
    print(stack.getstack())
  14. 什么是threading.local,以及他的作用
  15. 原生SQL和ORM的区别
    # 关系对象映射,本质是
    - SQL
    - 执行效率更高,但是代码更多,开发效率低
    - ORM
    - 开发效率高,编写速度快,执行效率相比于优化后的SQL较低些
  16. 反射在哪里用到过

Redis (  )

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6

那些坑爹的python面试题的更多相关文章

  1. Python面试题 —— 获取列表中位数

    中位数是一个可将数值集合划分为相等的上下两部分的一个数值.如果列表数据的个数是奇数,则列表中间那个数据就是列表数据的中位数:如果列表数据的个数是偶数,则列表中间那2个数据的算术平均值就是列表数据的中位 ...

  2. python公司面试题集锦 python面试题大全

    问题一:以下的代码的输出将是什么? 说出你的答案并解释. class Parent(object): x = 1 class Child1(Parent): pass class Child2(Par ...

  3. 【Python】【面试必看】Python笔试题

    前言 现在面试测试岗位,一般会要求熟悉一门语言(python/java),为了考验求职者的基本功,一般会出 2 个笔试题,这些题目一般不难,主要考察基本功.要是给你一台电脑,在编辑器里面边写边调试,没 ...

  4. Python面试题整理-更新中

    几个链接: 编程零基础应当如何开始学习 Python ? - 路人甲的回答 网易云课堂上有哪些值得推荐的 Python 教程? - 路人甲的回答 怎么用最短时间高效而踏实地学习 Python? - 路 ...

  5. python 面试题4

    Python面试题 基础篇 分类: Python2014-08-08 13:15 2071人阅读 评论(0) 收藏 举报 最近,整理了一些python常见的面试题目,语言是一种工具,但是多角度的了解工 ...

  6. 一道Python面试题

    无意间,看到这么一道Python面试题:以下代码将输出什么? def testFun():    temp = [lambda x : i*x for i in range(4)]    return ...

  7. 很全的 Python 面试题

    很全的 Python 面试题 Python语言特性 1 Python的函数参数传递 看两个例子:           Python   1 2 3 4 5 a = 1 def fun(a):      ...

  8. SQL + Python 面试题:之二(难度:中等)

    SQL + Python 面试题:之二(难度:中等)

  9. Python面试题之一:解密

    Python面试题之一: 说明:就是Python工程师面试题 一.字典转换与正则提取值 1:key与Value交换 a = {'a':1,'b':2} print({value:key for key ...

随机推荐

  1. 对云资源服务商资源读写的架构思考:前端代码走token

    第一.统一了访问端接口.提高前端开发速度:第二统一了阿里各个产品的 数据读写模式: 第三,我们的服务器产生token时对读写规则做限制,特定的token由特定的规则产生,而不是让前端代代码去管控限制 ...

  2. SHOW PROCESSLIST Syntax

    https://dev.mysql.com/doc/refman/5.7/en/show-processlist.html SHOW PROCESSLIST shows you which threa ...

  3. Deep Learning 31: 不同版本的keras,对同样的代码,得到不同结果的原因总结

    一.疑问 这几天一直纠结于一个问题: 同样的代码,为什么在keras的0.3.3版本中,拟合得比较好,也没有过拟合,验证集准确率一直高于训练准确率. 但是在换到keras的1.2.0版本中的时候,就过 ...

  4. vue、react、angular三大框架对比

    前端的三大框架当属vue.react以及angular了,个人比较偏向react,它的社区比较繁荣,有很多丰富的组件 .angular的话感觉编译时间有点长,等待很恼火. vue与react vue和 ...

  5. VC FTP服务器程序分析(一)

    想在QT上移植一个FTP服务器程序,先学习windows下的FTP服务器例子,然后随便动手写点东西. 在pudn上搜索 "FTP服务器端和客户端实现 VC“这几个关键字,就可以搜到下面要分析 ...

  6. iOS自定义提示弹出框(类似UIAlertView)

    菜鸟一枚,大神勿喷.自己在牛刀小试的时候,发现系统的UIAlertView有点不喜欢,然后就自己自定义了一个UIAlertView,基本上实现了系统的UIAlertView,可以根据项目的需求修改UI ...

  7. c语言中为什么左移不分符号数无符号数,而右移分呢??

    因为在C语言标准中,只规定了无符号数的移位操作是采用逻辑移位(即左移.右移都是使用的逻辑左移和逻辑右移).而对于有符号数,其左移操作还是逻辑左移,但右移操作是采用逻辑右移还是算术右移就取决于机器了!( ...

  8. uestc 250 windy数(数位dp)

    题意:不含前导零且相邻两个数字之差至少为2的正整数被称为windy数. windy想知道,在A和B之间,包括A和B,总共有多少个windy数? 思路:数位dp #include<iostream ...

  9. Android 增,删,改,查 通讯录中的联系人

    一.权限 操作通讯录必须在AndroidManifest.xml中先添加2个权限, <uses-permission android:name="android.permission. ...

  10. dba操作之archivelog清理

    下面的命令用于校验归档日志的有效性,列出无效的归档日志,以及以何种方式清除归档日志,列出几种常用的: crosscheck archivelog all;                        ...