Python基础知识整理

目录

1. Python的映射类型

2.python中的标识符

3. 装饰器

4.Python中的复数

5.函数参数定义

6.Python闭包

7. 已知a = [1, 2, 3]和b = [1, 2, 4],那么id(a[1])==id(b[1])的执行结果 

8.可变与不可变数据类型

9.最大公约(因)数

10.比较大小

11.字符串编解码:

12.质数: 

13.正则匹配字符串

14.python socket操作

15. 解释型语言的特性有什么

16. Python元组的定义方式

17. Python内存管理

18.列表 切片操作不会引起下标越界异常

19. Python中单下划线_foo与双下划线__foo与__foo__的成员,下列说法正确的是?

20. __new__和__init__的区别

21.Python函数

22.python参数传递是值传递还是引用传递

23.什么是GIL(Global Interpreter Lock)

24 with原理

25.标准库线程安全的队列是哪一个,不安全是哪一个?logging是线程安全的吗?

26.@staticmethod,@classmethod区别

27.迭代器、生成器

28.猴子补丁(Monkey Patching)

30.调度算法

31.死锁

32.Python运算符的优先顺序

33.Python是如何进行内存管理的?

34. 垃圾回收机制

35.什么是lambda函数?它有什么好处?

36.(赋值,浅拷贝,深拷贝的区别)

37.Python中pass语句的作用是什么?

38.Python查询和替换一个文本字符串

39.map,reduce,filter

40.Python使用简单的方式实现问号表达式:

41.正则提取网页链接

42.正则匹配ip 

43.inspect模块的作用

44.字符串格式化:%和.format的区别

45.实现一个字典类,要求元素只能被设置一次

46. 使用修饰器实现一个单例

47.MySQL case...when 和 left join

48.*args与**kwargs

49.Python命名空间(作用域)

50.为什么lambda没有语句

51.Python docstring 

52.简述函数式编程

53.如何捕获异常,常用的异常机制有哪些?

54.Python中的@property有什么作用?如何实现成员变量的只读属性

55.什么是Python

55.设计模式

56.Python自省

57.什么是PEP8

58.CRSF是什么

59.for-else

60.super在多继承的解析


1. Python的映射类型

映射是一种关联式的容器类型,它存储了对象与对象之间的映射关系,字典是python里唯一的映射类型,它存储了键值对的关联,是由键到键值的映射关系

2.python中的标识符

  • 第一个字符必须是字母表中字母或下划线  _  。
  • 标识符的其他的部分由字母、数字和下划线组成。
  • 标识符对大小写敏感。
  • 不可以是python中的关键字,如False、True、None、class等。
  • 注意:self不是python中的关键字。类中参数self也可以用其他名称命名,但是为了规范和便于读者理解,推荐使用self。

3. 装饰器

     装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。
     它经常用于有切面需求的场景,比如:插入日志、性能测 试、事务处理、缓存、权限校验等场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。
     概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能
    内置装饰器@staticmathod、@classmethod、@property
     @标记是语法糖(syntactic sugar),可以让你以简单易读得方式装饰目标对象

4.Python中的复数

  • 虚数不能单独存在,它们总是和一个值为 0.0 的实数部分一起来构成一个复数。
  • 复数由实数部分和虚数部分构成
  • 表示虚数的语法: real+image j
  • 实数部分和虚数部分都是浮点数
  • 虚数部分必须有后缀 j 或 J 
    Python2 与 Python3 均 不支持复数比较大小

5.函数参数定义

  • Python2参数顺序:必选参数、默认参数、可变参数和关键字参数。
  • Python3参数顺序:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。  

6.Python闭包

  1. 必须有一个内嵌函数
  2. 内嵌函数必须引用外部函数中的变量
  3. 外部函数的返回值必须是内嵌函数
    def w1():
          print('正在装饰')
          def inner():
                print('正在验证权限')
          return inner()
     w1()
     如果外层函数返回的是一个函数名[return inner]的话,运行结果应该是:正在装饰
     如果外层函数返回的是函数调用的话,运行结果是:正在装饰 正在验证权限 

7. 已知a = [1, 2, 3]和b = [1, 2, 4],那么id(a[1])==id(b[1])的执行结果 

     True
     python中对于小整数对象有一个小整数对象池,范围在[-5,257)之间。
     对于在这个范围内的整数,不会新建对象,直接从小整数对象池中取就行。

8.可变与不可变数据类型

   Python有6个标准的数据类型:黑体部分
可变(mutable)对象类型 :( 列表,字典,集合list、dict、set、bytearray、user-defined classes (unless specifically made immutable)
不可变(immutable)对象类型 :(数字,字符串,元组) int、float、decimal、complex、bool、 str、tuple、range、frozenset、bytes
     字典本身是可变数据类型,但字典的键值必须是不可变类型

9.最大公约(因)数

def f(a, b):
    if b == 0:
        return a
    else:
        f(b, a % b)

a, b = input("Enter two natural numbers: ")
ans=f(a, b)

   a % b 是求余数。辗转相除法,又称欧几里得算法,以除数和余数反复做除法运算,当余数为 0 时,取当前算式除数为最大公约数。

10.比较大小

 类似元组、字符串、列表这类格式,

在进行两者之间的比较时,先从第一个元素开始比较 ASCII 码值大小,如果相等,则依次向后比较,如果全部相等,则比较数量大小。

     ASCII码中:小写字母>大写字母>数字

11.字符串编解码:

     有一段python的编码程序如下:
       
urllib.quote(line.decode("gbk").encode("utf-16"))
    请问经过该编码的字符串的解码顺序
    
    字符串编译的过程:gbk==>unicode==>utf16==>url解码
    字符串解码顺序为:url解码==>utf16==>unicode==>gbk

12.质数: 

      质数是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数
       效率提升的关键在于 埃拉托斯特尼筛法 ,简称埃式筛,也叫厄拉多塞筛法: 
            要得到自然数n以内的全部质数,必须把不大于根号n的所有质数的倍数剔除,剩下的就是质数。
            为什么埃式筛只需要剔除根号n以内的质数倍数?为什么不是每个数的倍数都进行剔除?
              我们知道偶数的倍数肯定是偶数,可以剔除,那为什么不是剔除根号n以内的所有奇数的倍数呢?
       算术基本定理 任何一个合数(非质数),都可以以唯一的形式被写成有限个质数的乘积,即分解质因数。  
      
def countPrimes(self, n: int) -> int:
    import math
    """
    求n以内的所有质数个数
    """
    if n < 2:  # 小于2质数为0
        return 0
    sieve = [True] * n  # 使用bool类型降低内存消耗
    sieve[0] = False
    sieve[1] = False  # 0和1都不是质数,先排除掉
    for i in range(2, int(math.sqrt(n)) + 1):
        k = i * 2
        # 埃氏筛
        while k < n:  # 将所有k的倍数置为False/0
            sieve[k] = False
            k += i
    return sum(1 for x in sieve if x)

13.正则匹配字符串

    str1 = "Python's features" 
    str2 = re.match( r'(.*)on(.*?) .*', str1, re.M|re.I)

                  re.M:多行匹配,影响 ^ 和 $

                  re.I 使匹配对大小写不敏感
                  re.S:正则表达式会将这个字符串作为一个整体,在整体中进行匹配。
re模块实现正则的功能 
re.match(正则表达式,要匹配的字符串,[匹配模式])
 
要匹配的字符串为str1 = "Python's features" 
 
正则表达式r'(.*)on(.*?) .*'
r表示后面的字符串是一个普通字符串(比如\n会译为\和n,而不是换行符)
()符号包住的数据为要提取的数据,通常与.group()函数连用。
.匹配单个任意字符
*匹配前一个字符出现0次或无限次
?匹配前一个字符出现0次或1次
(.*)提取的数据为str1字符串中on左边的所有字符,即Pyth
(.*?)提取的数据为str1中on右边,空格前面,即's
        .group(0)输出的是 匹配正则表达式整体结果
. group(1) 列出第一个括号匹配部分,
.group(2) 列出第二个括号匹配部分

14.python socket操作

         sk.recv(bufsize[,flag]): 接受套接字的数据。
            数据以字符串形式返回,bufsize指定 最多 可以接收的数量。
            flag提供有关消息的其他信息,通常可以忽略。
sk.recvfrom(bufsize[.flag]): 与recv()类似,但返回值是(data,address)。
        其中data是包含接收数据的字符串,address是发送数据的套接字地址。
sk.getsockname(): 返回套接字自己的地址。
        通常是一个元组(ipaddr,port)
sk.connect(address): 连接到address处的套接字。
        一般,address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。
sk.listen(backlog): 开始监听传入连接。
        backlog指定在拒绝连接之前,可以挂起的最大连接数量。

15. 解释型语言的特性有什么

    非独立,效率低

16. Python元组的定义方式

      Python 中的 tuple 结构为 “不可变序列” ,用小括号表示。
            不可变,所以 a[1]=2这种操作会异常
      为了区别数学中表示优先级的小括号,当 tuple 中只含一个元素时,需要在元素后加上逗号(1,)

17. Python内存管理

  • Python 是弱类型脚本语言,变量就是变量, 没有特定类型 ,因此 不需要声明
  • 但每个变量在 使用前都必须赋值 ,变量赋值以后该变量才会被创建。
  • 用 del 语句可以 释放已创建的变量 (已占用的资源)

18.列表 切片操作不会引起下标越界异常

19. Python中单下划线_foo与双下划线__foo与__foo__的成员,下列说法正确的是?

  1.         _foo 不能直接用于’from module import *’
  2.         __foo解析器用_classname__foo来代替这个名字,以区别和其他类相同的命名
  3.         __foo__代表python里特殊方法专用的标识
  4.         __foo 可以直接用于’from module import *’

第四个错误

python中主要存在四种命名方式:
1、object #公用方法
2、_object #半保护
          #被看作是“protect”,意思是只有类对象和子类对象自己能访问到这些变量, 在模块或类外不可以使用,
                       不能用’from module import *’导入。
          # __object 是为了避免与子类的方法名称冲突, 对于该标识符描述的方法, 类的方法不能轻易地被子类的方法覆盖, 他们的名字实际上是 _classname__methodname。
3、_ _ object  #全私有,全保护
           # 私有成员“private”,意思是只有类对象自己能访问 连子类对象也不能访 问到这个数据, 不能用’from module import *’导入
4、_ _ object_ _     # 内建方法,用户不要这样定义

20. __new__和__init__的区别

  • __init__是当实例对象创建完成后被调用的,然后设置对象属性的一些初始值。
  • __new__是在实例创建之前被调用的,因为它的任务就是创建实例然后返回该实例,是个静态方法。
      即,__new__在__init__之前被调用,__new__的返回值(实例)将传递给__init__方法的第一个参数,
      然后__init__给这个实例设置一些参数
  • __new__是一个静态方法,而__init__是一个实例方法.
  • __new__方法会返回一个创建的实例,而__init__什么都不返回.
  • 只有在__new__返回一个cls的实例时后面的__init__才能被调用.
  • 当创建一个新实例时调用__new__,初始化一个实例时用__init__.

21.Python函数

  • 函数可以赋值给一个变量
  • 函数可以作为元素添加到集合对象中
  • 函数可以作为参数值传递给其它函数
  • 函数可以当做函数的返回值

22.python参数传递是值传递还是引用传递

    都是引用,对于不可改变的数据类型来说,不能改变,如果修改了,事实上是新建一个对象来对待。

23.什么是GIL(Global Interpreter Lock)

    Python代码的执行由Python 虚拟机(也叫解释器主循环,CPython版本)来控制,Python 在设计之初就考虑到要在解释器的主循环中,同时只有一个线程在执行,即在任意时刻,只有一个线程在解释器中运行。对Python 虚拟机的访问由 全局解释器锁(GIL)来控制,正是这个锁能保证同一时刻只有一个线程在运行。
     即Python为了保证线程安全而采取的独立线程运行的限制,说白了就是一个核只能在同一时间运行一个线程.
    对于io密集型任务,python的多线程起到作用,
    但对于cpu密集型任务,python的多线程几乎占不到任何优势,还有可能因为争夺资源而变慢。
    可以用多进程避免GIL的问题

24 with原理

with 语句实质是上下文管理。
1、上下文管理协议。包含方法__enter__() 和 __exit__(),支持该协议对象要实现这两个方法。
2、上下文管理器,定义执行with语句时要建立的运行时上下文,负责执行with语句块上下文中的进入与退出操作。
3、进入上下文的时候执行__enter__方法,如果设置as var语句,var变量接受__enter__()方法返回值。
4、如果运行时发生了异常,就退出上下文管理器。调用管理器__exit__方法。
with语句适用于对资源进行访问的场合,确保不管使用过程中是否发生异常都会执行必要的“清理”操作,释放资源,比如文件使用后自动关闭、线程中锁的自动获取和释放等。 
   #with语句使用上下文管理器对代码块进行包装,允许上下文管理器实现一些设置和清理操作
    #with用在支持上下文管理协议的对象中,如file,thread.LockType
    #当with语句执行时,便执行上下文表达式(context_expr)来获得一个上下文管理器,
    上下文管理器的职责是提供一个上下文对象,用于在with语句块中处理细节:
        #一旦获得了上下文对象,就会调用它的__enter__()方法,将完成with语句块执行前的所有准备工作,
            如果with语句后面跟了as语句,则用__enter__()方法的返回值来赋值;
        #当with语句块结束时,无论是正常结束,还是由于异常,都会调用上下文对象的__exit__()方法

25.标准库线程安全的队列是哪一个,不安全是哪一个?logging是线程安全的吗?

    线程安全即解决线程同步问题,Queue是线程安全队列,logging是线程安全的。

python queue模块有三种队列:
1、python queue模块的FIFO队列先进先出
2、LIFO类似于堆。即先进后出。
3、还有一种是优先级队列级别越低越先出来。
针对这三种队列分别有三个构造函数:
1、class Queue.Queue(maxsize) FIFO
2、class Queue.LifoQueue(maxsize) LIFO
3、class Queue.PriorityQueue(maxsize) 优先级队列

26.@staticmethod,@classmethod区别

  • 对于classmethod的参数,需要隐式地传递类名,而staticmethod参数中则不需要传递类名,其实这就是二者最大的区别。
  • 二者都可以通过类名或者类实例对象来调用,因为强调的是classmethod和staticmethod,所以在写代码的时候最好使用类名。
  • 对于staticmethod就是为了要在类中定义而设置的,一般来说很少这样使用,可以使用模块级(module-level)的函数来替代它。既然要把它定义在类中,想必有作者的考虑。
  • 对于classmethod,可以通过子类来进行重定义。

27.迭代器、生成器

     迭代器(Iterator) 是实现了__next__()方法的对象(这个方法在调用时不需要任何参数),它是访问可迭代序列的一种方式,通常其从序列的第一个元素开始访问,直到所有的元素都被访问才结束。 [注意]:迭代器只能前进不能后退
    [迭代器的优点]:
    使用迭代器不要求事先准备好整个迭代过程中的所有元素。迭代器仅仅在迭代到某个元素时才计算该元素,而在这之前或之后元素可以不存在或者被销毁。因此 迭代器适合遍历一些数量巨大甚至无限的序列
         可以直接作用于for循环的对象统称为可迭代对象:Iterable。
     生成器(Generator) 不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,直到最后抛StopIteration错误表示无法继续返回下一个值了。
    可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。
    生成器都是Iterator对象,但list、dict、str虽然是Iterable,却不是Iterator。

28.猴子补丁(Monkey Patching)

#在函数对象定义之后再去改变他们的行为
在运行时替换方法、属性等
在不修改第三方代码的情况下增加原来不支持的功能
在运行时为内存中的对象增加patch而不是在磁盘的源代码中增加
     因为猴子补丁破坏了封装,而且容易导致程序与补丁代码的实现细节紧密耦合,所以被视为临时的变通方案,不是集成代码的推荐方式。
29.进程,线程,协程
1、进程
  •     进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,
  •     进程是系统进行资源分配和调度的一个独立单位。
  •     每个进程都有自己的独立内存空间,不同进程通过进程间通信来通信。
  •     由于进程比较重量,占据独立的内存,所以上下文进程间的切换开销(栈、寄存器、虚拟内存、文件句柄等)比较大,但相对比较稳定安全。
2、线程
  •     线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.
  •     线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。
  •     线程间通信主要通过共享内存,上下文切换很快,资源开销较少,但相比进程不够稳定容易丢失数据。
    3、协程
  • 协程是一种用户态的轻量级线程,协程的调度完全由用户控制。
  • 协程拥有自己的寄存器上下文和栈。
  • 协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈,直接操作栈则基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快。

简单点说协程是进程和线程的升级版,

进程和线程都面临着内核态和用户态的切换问题而耗费许多切换时间,而协程就是用户自己控制切换的时机,不再需要陷入系统的内核态

        python可以通过 yield/send 的方式实现协程。在python 3.5以后,async/await 成为了更好的替代方案。
一、进程与线程比较
线程是指进程内的一个执行单元,也是进程内的可调度实体。线程与进程的区别:
1) 地址空间:线程是进程内的一个执行单元,进程内至少有一个线程,它们共享进程的地址空间,而进程有自己独立的地址空间
2) 资源拥有:进程是资源分配和拥有的单位,同一个进程内的线程共享进程的资源
3) 线程是处理器调度的基本单位,但进程不是
4) 二者均可并发执行
5) 每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口,但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制
二、协程多与线程进行比较
1) 一个线程可以多个协程,一个进程也可以单独拥有多个协程,这样python中则能使用多核CPU。
2) 线程进程都是同步机制,而协程则是异步
3) 协程能保留上一次调用时的状态,每次过程重入时,就相当于进入上一次调用的状态

30.调度算法

     先来先服务,最高优先权调度,时间片轮转,短作业优先

31.死锁

    指多个进程在运行过程中因争夺资源而造成的一种僵局,当进程处于这种僵持状态时,若无外力作用,它们都将无法再向前推进
产生死锁的必要条件
  •  互斥条件:进程要求对所分配的资源进行排它性控制,即在一段时间内某资源仅为一进程所占用。
  •  请求和保持条件:当进程因请求资源而阻塞时,对已获得的资源保持不放。
  •  不剥夺条件:进程已获得的资源在未使用完之前,不能剥夺,只能在使用完时由自己释放。
  •  环路等待条件:在发生死锁时,必然存在一个进程--资源的环形链。
预防死锁:
  • 资源一次性分配:一次性分配所有资源,这样就不会再有请求了:(破坏请求条件)
  • 只要有一个资源得不到分配,也不给这个进程分配其他的资源:(破坏请保持条件)
  • 可剥夺资源:即当某进程获得了部分资源,但得不到其它资源,则释放已占有的资源(破坏不可剥夺条件)
  • 资源有序分配法:系统给每类资源赋予一个编号,每一个进程按编号递增的顺序请求资源,释放则相反(破坏环路等待条件)
避免死锁(银行家算法)
检测死锁(资源分配图):
  1. 首先为每个进程和每个资源指定一个唯一的号码;
  2. 然后建立资源分配表和进程等待表。
解除死锁:
 
  • 剥夺资源:从其它进程剥夺足够数量的资源给死锁进程,以解除死锁状态;
  • 撤消进程:可以直接撤消死锁进程或撤消代价最小的进程,直至有足够的资源可用,死锁状态.消除为止;所谓代价是指优先级、运行代价、进程的重要性和价值等。

32.Python运算符的优先顺序

1.算术运算符中的优先级顺序和数学运算里一样,先乘除后加减。
2.位运算符优先级低于算术运算符,其中移位运算符优先级又高于按位运算符。
3.关系运算符优先级低于位运算符和算术运算符。
4.逻辑运算符优先级又低于关系运算符,其中的优先级从高到低是not、and、or。
5.赋值运算符优先级最低。

33.Python是如何进行内存管理的?

    从三个方面来说:
        对象的引用计数机制,垃圾回收机制,内存池机制
一、对象的引用计数机制
Python内部使用引用计数,来保持追踪内存中的对象,所有对象都有引用计数。
引用计数增加的情况:
1,一个对象分配一个新名称
2,将其放入一个容器中(如列表、元组或字典)
引用计数减少的情况:
1,使用del语句对对象别名显示的销毁
2,引用超出作用域或被重新赋值
sys.getrefcount( )函数可以获得对象的当前引用计数
多数情况下,引用计数比你猜测得要大得多。对于不可变数据(如数字和字符串),解释器会在程序的不同部分共享内存,以便节约内存。
二、垃圾回收
1,当一个对象的引用计数归零时,它将被垃圾收集机制处理掉。
2,当两个对象a和b相互引用时,del语句可以减少a和b的引用计数,并销毁用于引用底层对象的名称。然而由于每个对象都包含一个对其他对象的应用,因此引用计数不会归零,对象也不会销毁。(从而导致 内存泄露 )。为解决这一问题,解释器会定期执行一个循环检测器,搜索不可访问对象的循环并删除它们。
3,  分代回收,
    将系统中的所有内存块根据其存活时间划分为不同的集合,每一个集合就成为一个“代”,Python默认定义了三代对象集合,垃圾收集的频率随着“代”的存活时间的增大而减小  , 存活时间通常是利用几次垃圾收集动作来衡量
         也就是说,活得越长的对象,就越不可能是垃圾,就应该减少对它的垃圾收集频率。
    三、内存池机制
Python提供了对内存的垃圾收集机制,但是它将不用的内存放到内存池而不是返回给操作系统。
1,Pymalloc机制。为了加速Python的执行效率,Python引入了一个内存池机制,用于管理对小块内存的申请和释放。
2,Python中所有小于256个字节的对象都使用pymalloc实现的分配器,而大的对象则使用系统的malloc。
3,对于Python对象,如整数,浮点数和List,都有其独立的私有内存池,对象间不共享他们的内存池。也就是说如果你分配又释放了大量的整数,用于缓存这些整数的 内存就不能再分配给浮点数。

34. 垃圾回收机制

        Python GC主要使用引用计数(reference counting)来跟踪和回收垃圾。在引用计数的基础上,通过“标记-清除”(mark and sweep)解决容器对象可能产生的循环引用问题,通过“分代回收”(generation collection)以空间换时间的方法提高垃圾回收效率
    1) 引用计数
     当一个对象的引用被创建或者复制时,对象的引用计数加1;
     当一个对象的引用被销毁时,对象的引用计数减1,
     当对象的引用计数减少为0时,就意味着对象已经再没有被使用了,可以将其内存释放掉。
        优点: 简单 实时性
        缺点: 维护引用计数消耗资源 循环引用
    2) 标记清除
     基本思路是先按需分配,等到没有空闲内存的时候从寄存器和程序栈上的引用出发,遍历以对象为节点、以引用为边构成的图,把所有可以访问到的对象打上标记,然后清扫一遍内存空间,把所有没标记的对象释放。
         1. 寻找跟对象(root object)的集合作为垃圾检测动作的起点,跟对象也就是一些全局引用和函数栈中的引用,这些引用所指向的对象是不可被删除的;
         2. 从root object集合出发,沿着root object集合中的每一个引用,如果能够到达某个对象,则说明这个对象是可达的,那么就不会被删除,这个过程就是垃圾检测阶段;
         3. 当检测阶段结束以后,所有的对象就分成可达和不可达两部分,所有的可达对象都进行保留,其它的不可达对象所占用的内存将会被回收,这就是垃圾回收阶段。(底层采用的是链表将这些集合的对象连接在一起)
 
    3) 分代回收
     将系统中的所有内存块根据其存活时间划分为不同的集合,每一个集合就成为一个“代”,Python默认定义了三代对象集合,垃圾收集的频率随着“代”的存活时间的增大而减小, 存活时间通常是利用几次垃圾收集动作来衡量。
     也就是说,活得越长的对象,就越不可能是垃圾,就应该减少对它的垃圾收集频率。

35.什么是lambda函数?它有什么好处?

    lambda 表达式,通常是在需要一个函数,但是又不想费神去命名一个函数的场合下使用,也就是指匿名函数
    lambda函数:首要用途是指点短小的回调函数

36.(赋值,浅拷贝,深拷贝的区别)

赋值(=):
    就是创建了对象的一个新的引用,修改其中任意一个变量都会影响到另一个。
浅拷贝:
    创建一个新的对象,但它包含的是对原始对象中包含项的引用(如果用引用的方式修改其中一个对象,另外一个也会修改改变){1,完全切片方法;2,工厂函数,如list();3,copy模块的copy()函数}
深拷贝:
    创建一个新的对象,并且递归的复制它所包含的对象(修改其中一个,另外一个不会改变){copy模块的deep.deepcopy()函数}

37.Python中pass语句的作用是什么?

         pass语句不会执行任何操作,一般作为占位符或者创建占位程  

38.Python查询和替换一个文本字符串

  可以使用re模块中的sub()函数
  sub(replacement, string,count=0)
       re模块中 match(pattern,string[,flags]),检查string的开头是否与pattern匹配。
       re模块中research(pattern,string[,flags]),在string搜索pattern的第一个匹配值。

39.map,reduce,filter

    map(func,iterable)将传入的函数依次应用到可迭代对象的每个元素,并把结果作为Iterator返回
        list(map(str,[1,2,3]))#['1','2','3']
    reduce(func,iterable) 把一个函数作用在一个序列[x1, x2, x3, ...]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算
         reduce(lambda x,y:x*10+y,[1,2,3,4] )#结果:1234
    filter (func,iterable) 把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素
        list(filter(lambda x: x % 2 == 1, [1, 2, 4, 5, 6, 9, 10, 15]))# 结果: [1, 5, 9, 15]

40.Python使用简单的方式实现问号表达式:

    int n=a>b?a:b
    n = (a > b) and a or b  
#主要用到逻辑运算符的优先级(not >and > or)以及隔断性质

41.正则提取网页链接

    string=<a href=http://www.baidu.com/html/category/it-interview/flex>Flex</a>
            href=re.findall(r'<a.*?href=(http://.*?)>',string)

42.正则匹配ip 

    src="security/afafsff/?ip=123.4.56.78&id=45"
        m=re.search('ip=(\d(1,3)\.\d(1,3).\d(1,3).\d(1,3))',src,re.S)
        print(m.group(1))

43.inspect模块的作用

      inspect模块用于收集python对象的信息,可以获取类或函数的参数的信息,源码,解析堆栈,对对象进行类型检查等等
       getargspec(func)    返回一个命名元组ArgSpect(args, varargs, keywords, defaults),
                args是函数位置参数名列表,varargs是*参数名,keywords是**参数名,defaults是默认参数值的元组
       getmembers(object, predicate)  返回一个包含对象的所有成员的(name, value)列表。
                返回的内容比对象的__dict__包含的内容多,源码是通过dir()实现的。
    predicate是一个可选的函数参数,被此函数判断为True的成员才被返回。
getmodule(object)   返回定义对象的模块
getsource(object)    返回对象的源代码
getsourcelines(object)  返回一个元组,元组第一项为对象源代码行的列表,第二项是第一行源代码的行号
ismodule,isclass,ismethod,isfunction,isbuiltin
一系列判断对象类型的方法,大都是包装了isinstance(object, types.FunctionType)之类语句的函数。

44.字符串格式化:%和.format的区别

    字符串的format函数非常灵活,可以接受的参数不限个数,并且位置可以不按顺序,
    而且有较为强大的格式限定符,比如(填充,对其,精度等)

45.实现一个字典类,要求元素只能被设置一次

class CDict(dict):   
    def __setitem__(self, key, value):
        if self.__contains__(key):
            raise ValueError('The Value Existes')
        else:
            super(CDict, self).__setitem__(key, value)
if __name__ == '__main__':
    d=CDict()
    d['hello']='world'
    d['hello']='1111'

 

46. 使用修饰器实现一个单例

    实现单例模式主要有四种方法:__new__、共享属性、装饰器、import。

     单例模式:系统中一个类只有一个实例而且该实例易于外界访问
def singleton(cls, *args, **kw):
    instances = {}
    def _singleton():
        if cls not in instances:
            instances[cls] = cls(*args, **kw)
        return instances[cls]
    return _singleton

@singleton
class MyClass(object):
    a = 1
    def __init__(self, x=0):
          self.x = x
if __name__ == '__main__':
    one = MyClass()
    two = MyClass()
    one.x = 2
    two.a = 5
    print(one.x)# 2
    print(two.x)# 2
    print(one.a)# 5
    print(one.a)# 5
       

47.MySQL case...when 和 left join

  表demo1如下:               表 demo2如下:
name   subject  score       name      level
张三     数学         97        张三         1
张五     数学         63         张五        5
杨七     科学         84         杨七        4
杨三     科学         88         杨三        8
王五     语文         54         王五        2
王六     语文         72         王六        6
赵七     英语         91         赵七        7
赵六     英语         78         赵六        3
1)请用一句话SQL统计60,70,80,90分各档次的人数,并输出人数大于2的记录,val1为分数,val2为人数。
select *from (
select case
when (score >=60 and score <70) then "60-70"
when (score >=70 and score <80) then "70-80"
when (score >=80 and score <90) then "80-90"
when (score >=90 ) then "90-100"
else '100'
end "val1",
count(*) 'val2' from demo1
group by
case
when (score >=60 and score <70) then "60-70"
when (score >=70 and score <80) then "70-80"
when (score >=80 and score <90) then "80-90"
when (score >=90 ) then "90-100"
end
order by 1
) as bbb
where bbb.val2>=2

 

    2) 请用SQL输出demo1左连接demo2,并且level大于5的记录。
        
select distinct
demo2.name,level from demo1 left join demo2 on (demo2.level>5);

48.*args与**kwargs

    当我们不能确定往函数中传入多少个参数,或者我们想往函数中以列表或元祖的形式传参数时,那就需要使用*args
    当我们不知道往函数中传入多少个关键词参数,或者想以字典的形式传参时,那就要使用 **kwargs
 

49.Python命名空间(作用域)

        命名空间的定义
        Python使用叫做命名空间的东西来记录变量的轨迹。命名空间是一个 字典(dictionary) ,它的键就是变量名,它的值就是那些变量的值。
        在一个 Python 程序中的任何一个地方,都存在几个可用的命名空间。
     1、每个函数都有着自已的命名空间,叫做局部命名空间,它记录了函数的变量,包括函数的参数和局部定义的变量。
     2、每个模块拥有它自已的命名空间,叫做全局命名空间,它记录了模块的变量,包括函数、类、其它导入的模块、模块级的变量和常量。
     3、还有就是内置命名空间,任何模块均可访问它,它存放着内置的函数和异常。
         命名空间查找顺序
当一行代码要使用变量 x 的值时,Python 会到所有可用的名字空间去查找变量,按照如下顺序:
     1、局部命名空间:特指当前函数或类的方法。如果函数定义了一个局部变量 x,或一个参数 x,Python 将使用它,然后停止搜索。
     2、全局命名空间:特指当前的模块。如果模块定义了一个名为 x 的变量,函数或类,Python 将使用它然后停止搜索。
     3、内置命名空间:对每个模块都是全局的。作为最后的尝试,Python 将假设 x 是内置函数或变量。
     4、如果 Python 在这些名字空间找不到 x,它将放弃查找并引发一个 NameError 异常,如,NameError: name 'aa' is not defined。
Python的变量名解析机制也称为 LEGB 法则:本地作用域(Local)→当前作用域被嵌入的本地作用域(Enclosing locals)[存在嵌套函数]→全局/模块作用域(Global)→内置作用域(Built-in)
        命名空间的生命周期
不同的命名空间在不同的时刻创建,有不同的生存期。
     1、内置命名空间在 Python 解释器启动时创建,会一直保留,不被删除。
     2、模块的全局命名空间在模块定义被读入时创建,通常模块命名空间也会一直保存到解释器退出。
     3、当函数被调用时创建一个局部命名空间,当函数返回结果 或 抛出异常时,被删除。
            每一个递归调用的函数都拥有自己的命名空间。
命名空间的访问
    locals();
    globals()
    locals 与 globals 之间的一个重要的区别locals 是只读的,globals 不是

50.为什么lambda没有语句

     它被用于在代码被执行的时候构建新的函数对象并且返回

51.Python docstring 

    Python中文档字符串被称为docstring,它在Python中的作用是为函数、模块和类注释生成文档

52.简述函数式编程

    在函数式编程中,函数是基本单位,可以像变量一样作为另一个函数的参数。除了匿名函数外,Python还使用fliter(),map(),reduce(),apply()函数来支持函数式编程。

53.如何捕获异常,常用的异常机制有哪些?

  •   try...except...finally语句
  •   assert语句:判断assert后面紧跟的语句是True还是False,如果是True则继续执行print,如果是False则中断程序,调用默认的异常处理器,同时输出assert语句逗号后面的提示信息。
  •   with语句:如果with语句或语句块中发生异常,会调用默认的异常处理器处理,但文件还是会正常关闭。

54.Python中的@property有什么作用?如何实现成员变量的只读属性

     @property装饰器就是负责把一个方法变成属性调用,通常用在属性的get方法和set方法, 通过设置@property可以实现实例成员变量的直接访问 ,又保留了参数的检查。另外通过设置get方法而不定义set方法可以实现成员变量的只读属性。

55.什么是Python

  1. Python是一种解释型语言。这就是说,与C语言和C的衍生语言不同,Python代码在运行之前不需要编译。其他解释型语言还包括PHP和Ruby。
  2. Python是动态类型语言,指的是你在声明变量时,不需要说明变量的类型。你可以直接编写类似x=111和x="I'm a string"这样的代码,程序不会报错。
  3. Python非常适合面向对象的编程(OOP),因为它支持通过组合(composition)与继承(inheritance)的方式定义类(class)。Python中没有访问说明符(access specifier,类似C++中的public和private),这么设计的依据是“大家都是成年人了”。
  4. 在Python语言中,函数是第一类对象(first-class objects)。这指的是它们可以被指定给变量,函数既能返回函数类型,也可以接受函数作为输入。类(class)也是第一类对象。
  5. Python代码编写快,但是运行速度比编译语言通常要慢。好在Python允许加入基于C语言编写的扩展,因此我们能够优化代码,消除瓶颈,这点通常是可以实现的。numpy就是一个很好地例子,它的运行速度真的非常快,因为很多算术运算其实并不是通过Python实现的。
  6. Python用途非常广泛——网络应用,自动化,科学建模,大数据应用,等等。它也常被用作“胶水语言”,帮助其他语言和组件改善运行状况。
  7. Python让困难的事情变得容易,因此程序员可以专注于算法和数据结构的设计,而不用处理底层的细节。

55.设计模式

    23种设计模式:单例模式,工厂模式,装饰器模式等等

56.Python自省

        运行时能够获得对象的类型.
            比如type(),dir(),getattr(),hasattr(),isinstance()

57.什么是PEP8

     PEP8是一种编程规范,内容是一些关于如何让你的程序更具可读性的建议。

58.CRSF是什么

     CSRF是伪造客户端请求的一种攻击,CSRF的英文全称是Cross Site Request Forgery,字面上的意思是跨站点伪造请求。

59.for-else

    当for循环没有被break掉,那么遍历结束就会执行else语句
for i in range(4):
    print(i)
    #break
else:
    print('end')

 

60.super在多继承的解析

super(),当出现多继承时,调用的顺序是根据类实例化时的执行顺序决定。

另,python3的继承寻址方式是广度优先,先从左到右,最后到基类
class A:
    def __init__(self):
        print('Enter A')
        print('Exit A')

class B(A):
    def __init__(self):
        print('Enter B')
        super(B, self).__init__()
        print('Exit B')
class C(A):
    def __init__(self):
        print('Enter C')
        print(super())
        super(C, self).__init__()
        print('Exit C')
class D(B,C):
    def __init__(self):
        print('Enter D')
        print(super())
        super(D, self).__init__()
        print('Exit D')
if __name__ == '__main__':
    # single=B()#单继承情况
    # print(B.mro())#[<class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
    '''
    创建B类的实例化对象时,执行初始化函数:
        打印输出Enter B,
    当遇到super()调用父类初始化函数(此时是调用B类的父类A的__init__函数),
        输出Enter A、Exit A,
    调用完成父类初始化函数后,继续执行下一句代码,
        输出Leave B
    '''
    multi=D()
    print(D.mro())#[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
    '''
    解析:
        1、执行顺序:D->B->C->A->object
        2、根据执行顺序,执行D类,
        输出Enter D,
     第一次执行super()时,调用D的父类B的__init__(),
            输出Enter B,
     第二次执行super()时,则调用D的父类C的__init__(),
        输出Enter C,
      第三次执行super()时,则调用A类的__init__(),
        输出Enter A和Exit A
        C类执行完super().__init__()后,继续执行下一句,
        输出Exit C
        B类执行完super().__init__()后,继续执行下一句,
        输出Exit B
        D类执行完super().__init__()后,继续执行下一句,
        输出Exit D

    '''

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值