【测试】Python面试题

文章目录

1.python3基本数据类型?

Number(数字):int、float、bool、complex(复数)
String(字符串)
List(列表)
Tuple(元组)
Set(集合)
Dictionary(字典)

参考:https://blog.csdn.net/happy_p_/article/details/124291752

Python3 的六个标准数据类型中:
不可变数据(3 个):Number(数字)、String(字符串)、Tuple(元组);
可变数据(3 个):List(列表)、Dictionary(字典)、Set(集合)。
在这里插入图片描述
当一个引用传递给函数的时候,函数自动复制一份引用,这个函数里的引用和外边的引用没有半毛关系了.所以第一个例子里函数把引用指向了一个不可变对象,当函数返回的时候,外面的引用没半毛感觉.而第二个例子就不一样了,函数内的引用指向的是可变对象,对它的操作就和定位了指针地址一样,在内存里进行修改.

2.isinstance 和 type 的区别?

type()不会认为子类是一种父类类型,不考虑继承关系;
isinstance()会认为子类是一种父类类型,考虑继承关系;
isinstance根据继承链去查找,可以查找到的返回True。type可以查看实例化的类。

3.Python3中True和False为什么可以和数字相加?

因为bool 是 int 的子类。
True == 1
False == 0

4.如何删除对象的引用?

var1 =1 
var2 =2
del var1,var2

5.讲讲Python数值运算的注意点

/ 返回一个浮点数,// 返回一个整数。
混合计算时,Python会把整型转换成为浮点数。

6.String的索引位置

在这里插入图片描述
注意str[0,-1]是前闭后开,这个返回的是第一个到倒数第二个,-1位置上的并不返回

7.set有哪些创建方式?

site = {1,2,3}
set{"abcdefg"}

8.数据类型转换有哪两种?

隐式类型转换 : 自动完成。例如5/2.5=2.0
显式类型转换 :需要使用类型函数来转换。str()、int()

9.Python有哪些解释器?

有 CPython、IPython、Jython、PyPy 等。

顾名思义,CPython 就是用 C 语言开发的了,是官方标准实现,拥有良好的生态,所以应用也就最为广泛了。
而 IPython 是在 CPython 的基础之上在交互式方面得到增强的解释器(http://ipython.org/)。
Jython 是专为 Java 平台设计的 Python 解释器(http://www.jython.org/),它把 Python 代码编译成 Java 字节码执行。
PyPy 是 Python 语言(2.7.13和3.5.3)的一种快速、兼容的替代实现(http://pypy.org/),以速度快著称。

10.列表如何当堆栈用?

用pop()后进先出

stack = [3, 4, 5]
stack.append(6)
 stack.append(7)
 stack.pop()

11.列表如何当队列使用?

用leftpop()先进先出

>>> from collections import deque
>>> queue = deque(["Eric", "John", "Michael"])
>>> queue.append("Terry")           # Terry arrives
>>> queue.append("Graham")          # Graham arrives
>>> queue.popleft()                 # The first to arrive now leaves
'Eric'

12.如何处理异常?

在这里插入图片描述

13.如何抛出异常?

在这里插入图片描述

x = 10
if x > 5:
    raise Exception('x 不能大于 5。x 的值为: {}'.format(x))

14.面向对象的一些定义?

  • 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
  • 方法:类中定义的函数。
  • 类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
  • 数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。
  • 方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
  • 局部变量:定义在方法中的变量,只作用于当前实例的类。
  • 实例变量:在类的声明中,属性是用变量来表示的,这种变量就称为实例变量,实例变量就是一个用 self 修饰的变量。
  • 继承:即一个派生类(derived class)继承基类(base
    class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。
  • 实例化:创建一个类的实例,类的具体对象。
  • 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。

15.深拷贝和浅拷贝之间的区别是什么?

深拷贝就是将一个对象拷贝到另一个对象中,这意味着如果你对一个对象的拷贝做出改变时,不会影响原对象。b=copy.deepcopy(a)
在这里插入图片描述
浅拷贝则是将一个对象的引用拷贝到另一个对象上,所以如果我们在拷贝中改动,会影响到原对象。

16.列表和元组之间的区别是?

列表是可变的。创建后可以对其进行修改。
元组是不可变的。元组一旦创建,就不能对其进行更改。
列表表示的是顺序。它们是有序序列。
元组表示的是结构。

元组中存储的是对象的引用, 如果元组中对象本身是不可变对象,则不能再引用其它对象,
如果元组中的对象是可变对象(list等),则可变对象的引用不允许改变,但数据可以改变。

17.Python如何运用三元运算符?

Java中的三元运算符?:组合Python没有,但是Python有

[a] if [expression] else [b]

如果表达式为True,就执行[a]中的语句。否则,就执行[b]中的语句。
举例:

>>> a,b=2,3
>>> min=a if a<b else b
>>> min

18.Python中如何实现多线程?

https://www.runoob.com/python3/python3-multithreading.html

Python中的GIL(全局解释器锁)确保一次执行单个线程。一个线程保存GIL并在将其传递给下个线程之前执行一些操作,这会让我们产生并行运行的错觉。但实际上,只是线程在CPU上轮流运行。当然,锁的传递会增加程序执行的内存压力。

引入GIL是因为CPython的内存管理并不是线程安全的,为了保护多线程下对python对象的访问,每个线程在执行过程中都需要先获取GIL,保证同一时刻只有一个线程在执行代码。GIL使得python的多线程不能充分发挥多核CPU的性能,对CPU密集型程序的影响较大

GIL 全局解释器
在非python环境中,单核情况下,同时只能有一个任务执行。多核时可以支持多个线程同时执行。但是在python中,无论有多少个核
同时只能执行一个线程。究其原因,这就是由于GIL的存在导致的。
GIL的全程是全局解释器,来源是python设计之初的考虑,为了数据安全所做的决定。某个线程想要执行,必须先拿到GIL,我们可以
把GIL看做是“通行证”,并且在一个python进程之中,GIL只有一个。拿不到线程的通行证,并且在一个python进程中,GIL只有一个,
拿不到通行证的线程,就不允许进入CPU执行。GIL只在cpython中才有,因为cpython调用的是c语言的原生线程,所以他不能直接操
作cpu,而只能利用GIL保证同一时间只能有一个线程拿到数据。而在pypy和jpython中是没有GIL的
python在使用多线程的时候,调用的是c语言的原生过程。

19.如何避免GIL

19.python中有哪几种继承?

单继承:一个类继承自单个基类
多继承:一个类继承自多个基类
多级继承:一个类继承自单个基类,后者则继承自另一个基类
分层继承:多个类继承自单个基类
混合继承:两种或多种类型继承的混合

20.多继承的搜索顺序?

当多继承的几个父类都有同样的方法的时候,子类执行的是先继承父类的方法,比如下面的例子中pig和dog类中都有eat的方法,但是turtle在继承的时候先继承了dog类,所以在turtle实例调用eat方法的时候,使用的是dog中的eat方法。
在这里插入图片描述

22.多级的多继承(混合继承)的搜索顺序?

https://zhuanlan.zhihu.com/p/459504171

深度优先:也就是查找顺序为1、2、3、4,即先沿着一边找,找到头找不到再找另一边
在这里插入图片描述

23.Python中是如何管理内存的?

参考https://blog.csdn.net/somenzz/article/details/119745623

你说的是官方的CPython解释器吗?
Python有一个私有堆空间来保存所有的对象和数据结构。作为开发者,我们无法访问它,是解释器在管理它。但是有了核心API后,我们可以访问一些工具。Python内存管理器控制内存分配。
另外,内置垃圾回收器会回收使用所有的未使用内存,所以使其适用于堆空间。
以 CPython 解释器为例,它的内存管理有三个关键点:引用计数、标记清理、分代收集。

24.讲讲Python的垃圾回收机制?

参考:https://www.jianshu.com/p/8c8d370855d6

引用计数为主,标记清除 和 分代回收为辅。

引用计数:对于 CPython 解释器来说,Python 中的每一个对象其实就是 PyObject 结构体,它的内部有一个名为
ob_refcnt 的引用计数器成员变量。程序在运行的过程中 ob_refcnt 的值会被更新,并用 ob_refcnt
来反映有多少个变量引用到该对象。当对象的引用计数值为 0 时,它的内存就会被释放掉。

当对象被创建,被引用,作为参数传递,存储到容器中,引用计数+1,
当对象离开作用域,引用指向别的对象,del,从容器中移除,引用计数-1,当引用计数降为0,python就会自动回收该对象所在的内存空间。

但是引用计数无法解决循环引用的问题,所以引入了标记清除和分代回收机制。

24.当退出Python时,是否释放全部内存?

具有对象循环引用或者全局命名空间引用的变量,在 Python 退出是往往不会被释放。

会由操作系统统一回收, 确保资源不会泄漏。

25.Python为什么叫解释型语言?

Python 不像 C++,Java 等语言一样,他们可以不用事先声明变量类型而直接对变量进行赋值。对 Python 语言来讲,对象的类型和内存都是在运行时确定的。这也是为什么我们称 Python 语言为动态类型的原因。

26.迭代器与可迭代对象的区别?

迭代器类,必须自定义__iter__()和__next__()魔法方法,用iter()函数可以创建可迭代对象的迭代器。

可迭代对象类,必须自定义__iter__()魔法方法,range,list类的实例化对象都是可迭代对象。

27.解释Python中的help()和dir()函数?

Help()函数是一个内置函数,用于查看函数或模块用途的详细说明。(说明书)
dir() 函数不带参数时,返回当前模块内的变量、方法和定义的类型列表;带参数时,返回参数的属性、方法列表。

28.什么是猴子补丁monkey patch?

源码不适合直接修改,比如引用的一些第三方库。此时要做修改可以用猴子补丁。

在运行期间动态修改一个类或模块。

class A:
    def func(self):
        print("Hi")


def monkey():
	print("Hi, monkey")

A.func = monkey
A.func()

执行结果就是“Hi,monkey”

29.*args和**kwargs的区别?

*args和 **args都具有储存多余变量的功能。只是存的东西不一样。

1、*args保存多余变量,保存方式为元组。
2、**args保存带有变量名的多余变量,保存方式为字典。

不知道向函数传递多少参数时,我们就使用*args。

#args的使用
def fun(x, y, *args):
    print("x=", x)
    print("y=", y)
    print("args=", args)

fun(1, 2, 3, 4, 5, 6, 7)

执行结果:

x= 1
y= 2
args= (3, 4, 5, 6, 7)

不知道该传递多少关键字参数时,使用**kwargs来收集关键字参数。

# **args的使用
def fun(x, y, **args):
    print("x=", x)
    print("y=", y)
    print("args=", args)

fun(1, 2, c=3, d=4, e=5, f=6, g=7)

执行结果:

x= 1
y= 2
args= (3, 4)
kwargs= {'e': 5, 'f': 6, 'g': 7}

30.请写一个Python逻辑,计算一个文件中的大写字母数量?

>>> import os

>>> os.chdir('C:\\Users\\lifei\\Desktop')
>>> with open('Today.txt') as today:
    count=0
    for i in today.read():
        if i.isupper():
            count+=1
print(count)

31.解释join()和split()函数?

join() 方法用于将序列中的元素以指定的字符连接生成一个新的字符串

str = "-";
seq = ("a", "b", "c"); # 字符串序列
print str.join( seq );

执行结果:a-b-c

split()能让我们用指定字符分割字符串,返回的是列表。

str = '1,2,3,4,5'
str.split(',')

执行结果:[‘1’, ‘2’, ‘3’, ‘4’, ‘5’]

32.怎么移除一个字符串中的前导空格?

str.lstrip()移除最左侧空格。

rstrip()移除最右侧空格,strip()移除最左侧和最右侧空格。想移除指定字符,用replace()

33.什么是闭包?

Python中,闭包的主要用途就是用于装饰器的实现

将闭包理解为一种特殊的函数,这种函数由两个函数的嵌套组成,且称之为外函数和内函数,外函数返回值是内函数的引用,此时就构成了闭包。

def func(a, b):
    def line(x):
        return a * x - b
    return line

a = func(2, 3)
print(a(5))

结果得到 7。
在这个案例中,外函数func有接收参数 a=2,b=3,内函数line接收参数x=5,在内函数体中计算了a*x-b 即 2×5-3的值作为返回值,外函数返回内函数的引用,这里的引用指的是内函数line在内存中的起始地址,最终调用内函数line()得到返回值7。

34.如何获取字典中所有键的列表?

>>> mydict={'a':1,'b':2,'c':3,'e':5}
>>> mydict.keys()
dict_keys(['a', 'b', 'c', 'e'])

35.什么是解包/解封装?

一个list/tuple是一个整体,想把list中每个元素当成一个个个体剥离出来,这个过程就是解包。

>>> a,b,c = ['a', 'b', 'c']
>>> a
'a'

>>> first, *new, last = [94, 85, 73, 46]
>>> new
[85, 73]

>>> a,b,c = ('a', 'b', 'c')
>>> a
'a'

>>> a,b,c = {'a':1, 'b':2, 'c':3}
>>> a
'a'

>>> a,b,c = 'abc'
>>> a
'a'

36.什么是压包?

压包是解包的逆过程,用zip函数实现,下面例子可以对压包有一个直观的感受:

>>> a = ['a', 'b', 'c']
>>> b = [1, 2, 3]
>>> for i in zip(a, b):
...     print(i)
...
('a', 1)
('b', 2)
('c', 3)

37.is和==的区别?

is比较的是id即地址是不是一样,==比较的是值是不是一样。

大多数情况下当用is和的结果是一样时,用is的效率是会高于的效率。
要清楚python为每个对象分配内存的机制:
1、python在为数字分配内存时,按照数字的内容来分配内存,即a = 5;b = 5时,python只对数字5分配一块内存空间,而不是对变量a和b各分配一块内存;
在计算机中,每一块内存都有一个唯一的地址以供变量去访问内存中的内容,这个地址会被赋给变量的id属性,所以a = 5;b = 5时a和b的id是一样的,都是5所在内存的地址。

38.__new__和__init__的区别?

  • __new__是一个静态方法,而__init__是一个实例方法.
  • __new__方法会返回一个创建的实例,而__init__什么都不返回.
  • 只有在__new__返回一个cls的实例时后面的__init__才能被调用.
    当创建一个新实例时调用__new__,初始化一个实例时用__init__

39.作用域搜索顺序?

Python 中变量的访问权限取决于其赋值的位置,这个位置被称为变量的作用域。Python
的作用域共有四种,分别是:局部作用域(Local,简写为 L)、作用于闭包函数外的函数中的作用域(Enclosing,简写为
E)、全局作用域(Global,简写为 G)和内置作用域(即内置函数所在模块的范围,Built-in,简写为 B)。

当 Python 遇到一个变量的话他会按照这样的顺序进行搜索:
本地作用域(Local)→当前作用域被嵌入的本地作用域(Enclosing locals)→全局/模块作用域(Global)→内置作用域(Built-in)

40.list tuple dict set的底层结构?

list和tuple底层都是顺序表结构。
list底层是可变数组,数组里存放的是元素对象的指针。
dict底层是哈希表。
set底层是哈希表,key就是元素,value都是空

41.进程、线程和协程?

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

42.Java和Python的区别?

43.函数参数里面的self和cls是什么意思?

class A(object):
    def foo(self,x):
        print "executing foo(%s,%s)"%(self,x)

    @classmethod
    def class_foo(cls,x):
        print "executing class_foo(%s,%s)"%(cls,x)

这个self和cls是对类或者实例的绑定,实例方法的调用离不开实例,我们需要把实例自己传给函数,调用的时候是这样的a.foo(x)(其实是foo(a, x)),类方法一样,只不过它传递的是类而不是实例,A.class_foo(x)。注意这里的self和cls可以替换别的参数,但是python的约定是这俩,还是不要改的好。

44.什么是静态方法?

静态方法其实和普通的方法一样,不需要对谁进行绑定,唯一的区别是调用的时候需要使用a.static_foo(x)或者A.static_foo(x)来调用。

class A(object):
    def foo(self,x):
        print "executing foo(%s,%s)"%(self,x)

    @classmethod
    def class_foo(cls,x):
        print "executing class_foo(%s,%s)"%(cls,x)

    @staticmethod
    def static_foo(x):
        print "executing static_foo(%s)"%x

在这里插入图片描述

45.类变量和实例变量的区别?

类变量是该类所有实例共享的属性和方法。
实例变量是对于每个实例独有的数据。

class Dog:
 
    kind = 'canine'         # class variable shared by all instances
 
    def __init__(self, name):
        self.name = name    # instance variable unique to each instance

类Dog中,类属性kind为所有实例所共享;实例属性name为每个Dog的实例独有。

46.什么是Python的自省?

自省就是面向对象的语言所写的程序在运行时,能知道对象的类型。
简单一句就是运行时能够获得对象的类型。比如type(),dir(),getattr(),hasattr(),isinstance()。

47.字典推导式怎么写?

d = {key: value for (key, value) in iterable}

#字典推导式
arry = [('a',3),('b',4),('c',5)]  
 
dict_ = {key:value for (key,value) in arry}
print(dict)
#结果
{'a': 3, 'b': 4, 'c': 5}

name = ['美琳','梦洁','雪丽','美莲']
age = [18,19,19,18]
a = {i:j for i,j in zip(name,age)}
print(a)
#结果
{'美琳': 18, '梦洁': 19, '雪丽': 19, '美莲': 18}

48.变量单双下划线的含义?

  • 表示这是一个保护成员(属性或者方法),只有类对象和子类对象自己能访问到这些变量,是用来指定私有变量和方法的一种方式(约定而已)。如果使用from a_module import *导入时,这部分变量和函数不会被导入。不过值得注意的是,如果使用import a_module这样导入模块,仍然可以用a_module._pythonPoint这样的形式访问到这样的对象。
  • __xxx 双下划线的表示的是私有类型的变量。只允许这个类本身进行访问了,子类也不可以调用。
  • __xxx__定义的是特殊方法(也叫魔法方法magic method)。像__init__之类的。

类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。

私有变量:两个下划线开头,声明该属性为私有,不能在类的外部或子类中被使用或直接访问。在类内部的方法中使用时 self.__private

保护变量:一个下划线开头,声明该属性为protected。即保护类型只能允许其本身与子类进行访问。在类内部的方法中使用时self._private

49.字符串格式化%和format()的区别?

#定义一个坐标
point = (250,250)
#使用%来格式化
s = '朝着敌人的坐标%s开炮'%point
print(s)  #直接报错
#TypeError: not all arguments converted during string formatting
 
#将s改为如下就不会报错了
s = '朝着敌人的坐标%s开炮'%(point,)
print(s)  # 不报错
#使用format格式化
s = '朝着敌人的坐标{}开炮'.format(point)
print(s)  # 正常输出

50.将列表生成式中[]改成() 之后数据结构是否改变?

是,从列表变为生成器。


>>> L = [x*x for x in range(10)]
>>> L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> g = (x*x for x in range(10))
>>> g
<generator object <genexpr> at 0x0000028F8B774200>

通过列表生成式,可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含百万元素的列表,不仅是占用很大的内存空间,如:我们只需要访问前面的几个元素,后面大部分元素所占的空间都是浪费的。因此,没有必要创建完整的列表(节省大量内存空间)。在Python中,我们可以采用生成器:边循环,边计算的机制,称为生成器—>generator

51.怎么创建生成器?

1)生成器表达式,上面第50题的例子就是
2)生成器函数。外表看上去像是一个函数,但是没有用return语句一次性的返回整个结果对象列表,取而代之的是使用yield语句一次返回一个结果。

def gen_squares(num):
    for x in range(num):
        yield x ** 2

52.生成器函数的运行过程/原理?

参考https://www.zhihu.com/question/24807364

通过yield关键字返回一个值后,还能从其退出的地方继续运行,因此可以随时间产生一系列的值。
运行的过程是这样的生成器函数返回一个迭代器,for循环等迭代环境对这个迭代器不断调用next函数,不断的运行到下一个yield语句,逐一取得每一个返回值,直到没有yield语句可以运行,最终引发StopIteration异常。

def gen_squares(num):
    for x in range(num):
        yield x ** 2

for i in gen_squares(5):
    print(i, end=' ')
    
0 1 4 9 16 

原理:在每次循环的时候,生成器函数都会在yield处产生一个值,并将其返回给调用者,即for循环。然后在yield处保存内部状态,并挂起中断退出。在下一轮迭代调用时,从yield的地方继续执行,并且沿用上一轮的函数内部变量的状态,直到内部循环过程结束。

53.生成器和迭代器的关系?

参考上面第52题里的运行过程。
生成器是一个特殊的迭代器,它保存的是算法,每次调用next()就计算出下一个元素的值,直到计算出最后一个元素,抛出StopIteration异常。

54.生成器和迭代器、可迭代对象的关系?

参考:https://blog.csdn.net/weixin_45722047/article/details/102604829
在这里插入图片描述

55.可迭代对象和迭代器的关系?

可迭代对象:可以使用 for 来循环遍历的对象。

isinstance('abc', Iterable)     # str是否可迭代

迭代器:实现了 iternext 两个方法的对象,都是迭代器。
迭代器是带状态的对象,它会记录当前迭代所在的位置,以方便下次迭代的时候获取正确的元素。__iter__返回迭代器自身,__next__返回容器中的下一个值,如果容器中没有更多元素了,则抛出StopIteration异常。

可迭代对象调用 dir() 方法时,会发现他们都实现了 iter 方法。这样就可以通过 iter(object) 来返回一个迭代器。

>>> x = [1, 2, 3]
>>> y = iter(x)     #创建迭代器
>>> next(y)
1
>>> next(y)
2
>>> next(y)
3
>>> next(y)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

56.装饰器是什么?

参考https://zhuanlan.zhihu.com/p/433668652
https://www.zhihu.com/question/325817179/answer/798679602

通过闭包来实现装饰器,函数作为外层函数的传入参数,然后在内层函数中运行、附加功能,随后把内层函数作为结果返回。

56.写一个简单的装饰器

装饰器本质也是函数。

# 函数,用来装饰其他的函数,其他函数征文执行之前或者之后,执行一些代码逻辑
def A(fun):
    def printer():
        print("双11机器人5折开始")
        fun()
        print("双11机器人5折结束")
    return printer
 
 # 函数作为外层函数的传入参数,然后在内层函数中运行、附加功能,随后把内层函数作为结果返回
 
@A
def say_hello():     
    print("您好")
 
@A
def goodbye():
    print("在家")
 
 
say_hello()

执行结果:
在这里插入图片描述

57.带参数的装饰器怎么用?

作者:Jackpop
链接:https://www.zhihu.com/question/325817179/answer/798679602
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

def logger(msg=None):
    def run_time(func):
        def wrapper(*args, **kwargs):
            start = time()
            func()                  # 函数在这里运行
            end = time()
            cost_time = end - start
            print("[{}] func three run time {}".format(msg, cost_time))
        return wrapper
    return run_time
​
@logger(msg="One")
def fun_one():
    sleep(1)
    
@logger(msg="Two")
def fun_two():
    sleep(1)
    
@logger(msg="Three")
def fun_three():
    sleep(1)
    
fun_one()
fun_two()
fun_three()

执行结果:
[One] func three run time 1.0013229846954346
[Two] func three run time 1.000720500946045
[Three] func three run time 1.0001459121704102

57.装饰器的使用场景有哪些?

适合有切面需求的场景,比如权限校验,日志记录和性能测试等等。比如你想要执行某个函数前记录日志或者记录时间来统计性能,又不想改动这个函数,就可以通过装饰器来实现。
不用装饰器,我们会这样来实现在函数执行前插入日志:

def foo():
    print('i am foo')
    
def foo():
    print('foo is running')
    print('i am foo')

用装饰器来写:

bar = use_log(bar)def use_log(func):
    def wrapper(*args,**kwargs):
        logging.warn('%s is running' % func.__name___)
        return func(*args,**kwargs)
    return wrapper
 
@use_log
def bar():
    print('I am bar')
    
@use_log
def haha():
    print('I am haha')
    
bar()
haha()

58.为什么要用装饰器?

开放封闭原则。
开放:指的是对拓展功能是开放的
封闭:指的是对修改源代码是封闭的

装饰器传入的参数就是一个函数,然后通过实现各种功能来对这个函数的功能进行增强。

59.read,readline和readlines的区别?

read 读取整个文件
readline 读取下一行,使用生成器方法
readlines 读取整个文件到一个迭代器以供我们遍历

60.Python2和Python3的区别?

https://zhuanlan.zhihu.com/p/161380701

61.range和xrange的区别?

range返回一个列表。xrange返回一个生成器对象。

62.怎么实现单例模式?

单例模式: 一个类只能创建一个实例化对象。

class Foo():
    __instance = None

    def __new__(cls):
        if cls.__instance is None:
            cls.__instance = super().__new__(cls)
        return cls.__instance

63.什么是工厂模式?

根据不同条件创建不同的类实例化对象

class CarFactory():
    def produce(self,name):
        if name == 'BYD':
            return BYD()
        elif name == 'BMW':
            return BMW()
        
class BYD():
    pass
    
class BMW():
    pass

car = CarFactory().produce('BMW')

64.a,b=b,a交换值的原理

Python的变量并不直接存储值,而只是引用一个内存地址,交换变量时,只是交换了引用的地址。

65.交换字典的key、value

mydict={“a”:1,“b”:2,“c”:3}
mydict_new={}

for key,val in mydict.items():
	mydict_new[val]=key

66.什么是魔法函数?

在类对象中,以双下滑线开头以及结尾的成为魔法函数,比如常见的__init__。

67.如何在函数内部修改全局变量?

用global关键词在函数的开头声明这个变量是全局变量

count = 30888 #麦叔粉丝数

# 关注
def guanzhu():
    global count
    count = count + 1
    print('麦叔的粉丝数是{}'.format(count))

# 取关
def quguan():
    global count
    count = count - 1
    print('麦叔的粉丝数是{}'.format(count))

68.什么是单例模式?

确保某一个类只有一个实例存在。
实现方式:

  • 使用函数装饰器实现单例
  • 使用类装饰器实现单例
  • 使用__new__关键字实现单例
  • 使用 metaclass 实现单例

69.pytest框架里的断言有哪些类型?

assert xx :判断 xx 为真
assert not xx :判断 xx 不为真
assert a in b :判断 b 包含 a
assert a == b :判断 a 等于 b
assert a != b :判断 a 不等于 b

70.解释Range函数?

Range函数可以用来创建一个整数列表,一般用在for循环中。它有3种使用方法。

[i for i in range(10)]#=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[i for i in range(2,10)]#=> [2, 3, 4, 5, 6, 7, 8, 9]
[i for i in range(2,10,2)]#=> [2, 4, 6, 8]

71.Python中的实例方法、静态方法和类方法有什么区别?

实例方法:接受self参数,并且与类的特定实例相关。
静态方法:使用装饰器 @staticmethod,与特定实例无关,并且是自包含的(不能修改类或实例的属性)。
类方法:接受cls参数,并且可以修改类本身。

72.Python是按引用调用还是按值调用?

不可变对象(如字符串、数字和元组等)是按值调用的。请注意下面的例子,当在函数内部修改时,name的值在函数外部不会发生变化。name的值已分配给内存中该函数作用域的新块。

name = 'chr'
def add_chars(s):
	 s += 'is' 
	 print(s)

add_chars(name) 
#=> chris

print(name)
#=> chr

可变对象(如列表等)是通过引用调用的。注意下面的例子中,函数外部定义的列表在函数内部的修改是如何影响到函数外部的。函数中的参数指向内存中存储li值的原始块。

# 可变数据类型按引用调用
li = [1,2]
def add_element(seq):
    seq.append(3)
    print(seq)

add_element(li)
#=> [1, 2, 3]
print(li)
#=> [1, 2, 3]

73.如何在Python中连接列表?

a = [1,2]
b = [3,4,5]
print(a + b)
#=> [1, 2, 3, 4, 5]

74.如何将一个数字四舍五入到小数点后三位?

a = 1.34564443
print(round(a,3))

75.如何分割一个列表?

list = [1,2,3,4,5,6,7]
print(list[1:3])
=>[2, 3]

76.讲讲Python的序列化和反序列化?

序列化: 将对象转换为字节序列。
反序列化:将字节序列转换为对象。

person={"name":"lala","age":23,"is_married":True}
print("序列化之前的数据:",person)#序列化之前的数据
 
json1=json.dumps(person)#序列化操作
print("序列化之后的数据:",repr(json1))#repr是一个展示对象的函数
 
person2=json.loads(json1)#反序列化操作
print("反序列化之后的数据:",person2)
 
"""
执行结果:
    序列化之前的数据: {'name': 'lala', 'age': 23, 'is_married': True}
    序列化之后的数据: '{"name": "lala", "age": 23, "is_married": true}'
    反序列化之后的数据: {'name': 'lala', 'age': 23, 'is_married': True}
"""

77.字典和JSON有什么区别?

Dict是Python的一种数据类型,是经过索引但无序的键和值的集合。
JSON只是一个遵循指定格式的字符串,用于传输数据。

78.字典和列表的查找速度哪个更快?

字典更快。
在列表中查找一个值需要O(n)时间,因为需要遍历整个列表,直到找到值为止。
在字典中查找一个值只需要O(1)时间,因为它是一个哈希表。
如果有很多值,这会造成很大的时间差异,因此通常建议使用字典来提高速度。但字典也有其他限制,比如需要唯一键。

79.模块(module)和包(package)有什么区别?

模块是可以一起导入的文件(或文件集合)。import sklearn
包是模块的目录。from sklearn import cross_validation
因此,包是模块,但并非所有模块都是包。

80.如何返回一个整数的二进制值?

bin(5)#=> ‘0b101’

81.如何从列表中删除重复的元素?

a = [1,2,3,7,7]
print(list(set(a)))

82.如何检查一个值是不是在列表中存在?

'a' in ['a','b','c']
#=> True
'a' in [1,2,3]
#=> False

83.append和extend有什么区别?

Append将一个值添加到一个列表中,而extend将另一个列表的值添加到一个列表中。

a = [1,2,3]
b = [1,2,3]
a.append(6)
print(a)
#=> [1, 2, 3, 6]
b.extend([4,5])
print(b)
#=> [1, 2, 3, 4, 5]

84.如何取一个整数的绝对值?

abs(2)#=> 2
abs(-2)#=> 2

85.如何将两个列表组合成一个元组列表?

b = [1,2,3]
a = ['a','b','c']
new = [(k,v) for k,v in zip(a,b)]
print(new)

86.如何按字母顺序对字典进行排序?

你不能对字典进行排序,因为字典没有顺序,但是你可以返回一个已排序的元组列表,其中包含字典中的键和值。

b = [1,2,3]
a = ['a','b','c']
new = [(k,v) for k,v in zip(a,b)]
print(new)

87.如何删除字符串中的所有空白?

空白拆分字符串,然后将拆分成的字符串重新连接在一起。

a = 'a is car'
print(''.join(a.split()))

88.continue和break的区别?

参考:https://www.jb51.net/article/221443.htm

break:在for循环或while循环结构中使用break语句,用于结束整个循环。
continue:在for循环或while循环结构中使用break语句,用于结束当前循环。

89.如何将一个字符串转化为全大写和全小写?

你可以使用upper和lower字符串方法。

90.lamda表达式的用法?

lambda [arguments] : expression

>>> a=lambda x,y:x+y
>>> a(1,2)
3

可以在lamda表达式里设置默认值:

>>> (lambda x,y=2:x+y)(x=1)
3
>>> (lambda x,y=2:x+y)(x=1,y=3)
4

高级用法:

>>> def my2(x):
...     return lambda y:x+y
...
>>> d=my2(2)
>>> d(5)
7

91.map、reduce、filter函数的使用

参考:https://blog.csdn.net/tianheihei__/article/details/124545827

92.os和sys模块的作用?

os模块负责程序与操作系统的交互,提供了访问操作系统底层的接口;
sys模块负责程序与python解释器的交互,提供了一系列的函数和变量,用于操控python的运行时环境。
详细:https://blog.csdn.net/qq_38276669/article/details/83687738

93.对super的理解

super 是个类,当我们调用 super() 的时候,实际上是实例化了一个 super 类。
https://blog.csdn.net/wanzew/article/details/106993425

94.新式类和经典类的区别?

继承 object 类的是新式类,不继承 object 类的是经典类。
python3中没有影响,class A()和class A(object)都是新式类,只有Python2中这两种写法会区分成经典类和新式类。

95.鸭子类型(Python的多态)?

https://blog.csdn.net/qq_39478403/article/details/107371850

96.Python的作用域

有四种作用域:
L(Local):最内层,包含局部变量,比如一个函数/方法内部。
E(Enclosing):包含了非局部(non-local)也非全局(non-global)的变量。比如两个嵌套函数,一个函数(或类) A 里面又包含了一个函数 B ,那么对于 B 中的名称来说 A 中的作用域就为 nonlocal。
G(Global):当前脚本的最外层,比如当前模块的全局变量。
B(Built-in): 包含了内建的变量/关键字等,最后被搜索。
规则顺序: L –> E –> G –> B。
在这里插入图片描述

g_count = 0  # 全局作用域
def outer():
    o_count = 1  # 闭包函数外的函数中
    def inner():
        i_count = 2  # 局部作用域
  • 3
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值