写点什么

学习 Python 一年,基础忘记了,看看面试题回忆回议,Python 面试题 No3

发布于: 刚刚

这边有几个面试题,好棒

第 1 题:你如何管理不同版本的代码?

git,svn 两个都要说到,github,码云也要提及,面试官想要的就是版本管理工具,你只要选择一个你熟悉的,疯狂的说一通就可以了,最好说一下自己以前做过哪些开源的项目,放在上面,没有,就另当别论了。

第 2 题:python 中生成随机整数、随机小数、0~1 之间小数方法?

python 中生成随机整数


import randomrandom.randint(1,10)
复制代码


随机小数


看自己习惯,可以用 random 库,也可以用 numpy 库


import randomrandom.random()
# 利用np.random.randn(5)生成5个随机小数import numpy as npnp.random.randn(5)
复制代码


0~1 之间小数


random.random()
复制代码

第 3 题:迭代器、可迭代对象、生成器?

第一步,你要知道什么是迭代


对 list、tuple、str 等类型的数据使用 for...in...的循环语法从其中依次拿到数据进行使用,我们把这样的过程称为遍历,也叫迭代


从结果去分析原因,能被 for 循环的就是“可迭代的”,但是如果正着想,for 怎么知道谁是可迭代的呢?


假如我们自己写了一个数据类型,希望这个数据类型里的东西也可以使用 for 被一个一个的取出来,那我们就必须满足 for 的要求--- 这个要求就叫做 协议


可以被迭代要满足的要求就叫做:可迭代协议


可迭代协议的定义非常简单,就是内部实现了__iter()__方法


如果某个对象中有_ iter _()方法,这个对象就是可迭代对象 (Iterable)


if '__iter__' in dir(str)
复制代码


通俗易懂 :可以被 for 循环迭代的对象就是可迭代对象。


从代码上面可以使用isinstance()判断一个对象是否是Iterable对象


from collections import Iterablea = isinstance([], Iterable)
b = isinstance({}, Iterable)
c = isinstance('abc', Iterable)
d = isinstance((x for x in range(10)), Iterable)
e = isinstance(100, Iterable)
print(a,b,c,d,e)
复制代码


结论


True True True True False
复制代码


只有最后的数字不是可迭代对象


可迭代对象的本质


我们分析对可迭代对象进行迭代使用的过程,发现每迭代一次(即在 for...in...中每循环一次)都会返回对象中的下一条数据,一直向后读取数据直到迭代了所有数据后结束。


那么,在这个过程中就应该有一个“人”去记录每次访问到了第几条数据,以便每次迭代都可以返回下一条数据。


我们把这个能帮助我们进行数据迭代的“人”称为迭代器(Iterator)


可迭代对象的本质就是可以 向我们提供一个这样的中间“人”即迭代器 帮助我们对其进行迭代遍历使用。


可迭代对象通过__iter__方法向我们提供一个迭代器,在迭代一个可迭代对象的时候,实际上就是先获取该对象提供的一个迭代器,然后通过这个迭代器来依次获取对象中的每一个数据。


综上所述,一个具备了__iter__方法的对象,就是一个可迭代对象。


class MyList(object):    def __init__(self):        self.container = []    def add(self, item):        self.container.append(item)    def __iter__(self):        """返回一个迭代器"""        # 我们暂时忽略如何构造一个迭代器对象        pass    mylist = MyList()from collections import Iterableisinstance(mylist, Iterable)
复制代码


iter()函数与 next()函数


listtuple等都是可迭代对象,我们可以通过iter()函数获取这些可迭代对象的迭代器。然后我们可以对获取到的迭代器不断使用 next()函数来获取下一条数据。iter()函数实际上就是调用了可迭代对象的__iter__方法。


>>> i = iter('spam')>>> next(i)'s'>>> next(i)'p'>>> next(i)'a'>>> next(i)'m'>>> next(i)Traceback (most recent call last):  File "<pyshell#5>", line 1, in <module>    next(i)StopIteration>>> 
复制代码


当序列遍历完时,将抛出一个StopIteration异常。这将使迭代器与循环兼容,因为它们将捕获这个异常以停止循环。要创建定制的迭代器,可以编写一个具有next方法的类。


迭代器 Iterator


通过上面的分析,现在你应该已经知道了,迭代器是用来帮助我们记录每次迭代访问到的位置,当我们对迭代器使用next()函数的时候,迭代器会向我们返回它所记录位置的下一个位置的数据。实际上,在使用next()函数的时候,调用的就是迭代器对象的__next__方法(Python3 中是对象的__next__方法,Python2 中是对象的next()方法)。


所以,我们要想构造一个迭代器,就要实现它的__next__方法。但这还不够,python 要求迭代器本身也是可迭代的,所以我们还要为迭代器实现__iter__方法,而__iter__方法要返回一个迭代器,迭代器自身正是一个迭代器,所以迭代器的__iter__方法返回自身即可。


一个实现了__iter__方法和__next__方法的对象,就是迭代器。


class MyList(object):    """自定义的一个可迭代对象"""    def __init__(self):        self.items = []     def add(self, val):        self.items.append(val)     def __iter__(self):        myiterator = MyIterator(self)        return myiterator  class MyIterator(object):    """自定义的供上面可迭代对象使用的一个迭代器"""    def __init__(self, mylist):        self.mylist = mylist        # current用来记录当前访问到的位置        self.current = 0     def __next__(self):        if self.current < len(self.mylist.items):            item = self.mylist.items[self.current]            self.current += 1            return item        else:            raise StopIteration     def __iter__(self):        return self  if __name__ == '__main__':    mylist = MyList()    mylist.add(1)    mylist.add(2)    mylist.add(3)    mylist.add(4)    mylist.add(5)    for num in mylist:        print(num)
复制代码


本部分代码来源: https://blog.csdn.net/weixin_42225318/article/details/81274348 博主这篇博客写的真好


可迭代对象与迭代器


  1. 可迭代对象包含迭代器。

  2. 如果一个对象拥有__iter__方法,那么它是可迭代对象;如果一个对象拥有next方法,其是迭代器。

  3. 定义可迭代对象,必须实现__iter__方法;定义迭代器,必须实现__iter__next方法。


  • _iter_()该方法返回的是当前对象的迭代器类的实例。因为可迭代对象与迭代器都要实现这个方法

  • next()返回迭代的每一步,实现该方法时注意要最后超出边界要抛出 StopIteration 异常。


迭代器一定是可迭代对象,反过来则不一定成立。用 iter()函数可以把 list、dict、str 等 Iterable 变成 Iterator


生成器


  1. 生成器是一种特殊的迭代器,生成器自动实现了“迭代器协议”(即__iter__next方法),不需要再手动实现两方法。

  2. 生成器在迭代的过程中可以改变当前迭代值,而修改普通迭代器的当前迭代值往往会发生异常,影响程序的执行。

  3. 具有yield关键字的函数都是生成器,yield可以理解为return,返回后面的值给调用者。不同的是return返回后,函数会释放,而生成器则不会。在直接调用next方法或用 for 语句进行下一次迭代时,生成器会从 yield 下一句开始执行,直至遇到下一个 yield。

第 4 题:单引号,双引号,三引号的区别?

  • 单引号和双引号主要用来表示字符串

  • 三引号


三单引号:'''python ''',也可以表示字符串一般用来输入多行文本,或者用于大段的注释;三双引号:"""python""",一般用在类里面,用来注释类,这样省的写文档,直接用类的对象__doc__访问获得文档。


区别


若你的字符串里面本身包含单引号,必须用双引号


例子:"can't find the log\n"
复制代码

第 5 题:Python 是如何进行内存管理的?

对象的引用计数机制 Python 内部使用引用计数,来保持追踪内存中的对象,所有对象都有引用计数。


引用计数增加的情况:


总结一下对象会在一下情况下引用计数加 1:


  1. 对象被创建:x='spam'

  2. 另外的别人被创建:y=x

  3. 被作为参数传递给函数:foo(x)

  4. 作为容器对象的一个元素:a=[1,x,'33']


引用计数减少情况


  1. 一个本地引用离开了它的作用域。比如上面的 foo(x)函数结束时,x 指向的对象引用减 1。

  2. 对象的别名被显式的销毁:del x ;或者 del y

  3. 对象的一个别名被赋值给其他对象:x=789

  4. 对象从一个窗口对象中移除:myList.remove(x)

  5. 窗口对象本身被销毁:del myList,或者窗口对象本身离开了作用域。


垃圾回收


  1. 当内存中有不再使用的部分时,垃圾收集器就会把他们清理掉。它会去检查那些引用计数为 0 的对象,然后清除其在内存的空间。当然除了引用计数为 0 的会被清除,还有一种情况也会被垃圾收集器清掉:当两个对象相互引用时,他们本身其他的引用已经为 0 了。

  2. 垃圾回收机制还有一个循环垃圾回收器, 确保释放循环引用对象(a 引用 b, b 引用 a, 导致其引用计数永远不为 0)。


在 Python 中,许多时候申请的内存都是小块的内存,这些小块内存在申请后,很快又会被释放,由于这些内存的申请并不是为了创建对象,所以并没有对象一级的内存池机制。这就意味着 Python 在运行期间会大量地执行 malloc 和 free 的操作,频繁地在用户态和核心态之间进行切换,这将严重影响 Python 的执行效率。为了加速 Python 的执行效率,Python 引入了一个内存池机制,用于管理对小块内存的申请和释放。


内存池机制


  1. Python 提供了对内存的垃圾收集机制,但是它将不用的内存放到内存池而不是返回给操作系统;

  2. Pymalloc 机制:为了加速 Python 的执行效率,Python 引入了一个内存池机制,用于管理对小块内存的申请和释放;

  3. 对于 Python 对象,如整数,浮点数和 List,都有其独立的私有内存池,对象间不共享他们的内存池。也就是说如果你分配又释放了大量的整数,用于缓存这些整数的内存就不能再分配给浮点数。

第 6 题:写一个函数, 输入一个字符串, 返回倒序排列的结果?

使用字符串本身的翻转


def order_by(str):    return str[::-1] print(order_by('123456')) 输出:654321
复制代码


把字符串变为列表,用列表的 reverse 函数


def reverse2(text='abcdef'):    new_text=list(text)    new_text.reverse()    return ''.join(new_text)
reverse2('abcdef')
复制代码


新建一个列表,从后往前取


def reverse3(text='abcdef'):    new_text=[]    for i in range(1,len(text)+1):        new_text.append(text[-i])    return ''.join(new_text)
reverse3('abcdef')
复制代码


利用双向列表 deque 中的 extendleft 函数


from collections import dequedef reverse4(text='abcdef'):    d = deque()    d.extendleft(text)    return ''.join(d)
reverse4('abcdef')
复制代码


发布于: 刚刚阅读数: 2
用户头像

爬虫 100 例作者,蓝桥签约作者,博客专家 2021.02.06 加入

6 年产品经理+教学经验,3 年互联网项目管理经验; 互联网资深爱好者; 沉迷各种技术无法自拔,导致年龄被困在 25 岁; CSDN 爬虫 100 例作者。 个人公众号“梦想橡皮擦”。

评论

发布
暂无评论
学习Python一年,基础忘记了,看看面试题回忆回议,Python面试题No3