Python面试基础2

Python面试基础2

写一个删除列表中重复元素的函数,要求去重后元素相对位置保持不变。

点评:这个题目在初中级Python岗位面试的时候经常出现,题目源于《Python Cookbook》这本书第一章的第10个问题,有很多面试题其实都是这本书上的原题,所以建议大家有时间好好研读一下这本书。

def dedup(items):
    no_dup_items = []
    seen = set()
    for item in items:
        if item not in seen:
            no_dup_items.append(item)
            seen.add(item)
    return no_dup_items

如果愿意也可以把上面的函数改造成一个生成器,代码如下所示。

def dedup(items):
    seen = set()
    for item in items:
        if item not in seen:
            yield item
            seen.add(item)

扩展:由于Python中的集合底层使用哈希存储,所以集合的innot in成员运算在性能上远远优于列表,所以上面的代码我们使用了集合来保存已经出现过的元素。集合中的元素必须是hashable对象,因此上面的代码在列表元素不是hashable对象时会失效,要解决这个问题可以给函数增加一个参数,该参数可以设计为返回哈希码或hashable对象的函数。

假设你使用的是官方的CPython,说出下面代码的运行结果。

点评:下面的程序对实际开发并没有什么意义,但却是CPython中的一个大坑,这道题旨在考察面试者对官方的Python解释器到底了解到什么程度。

a, b, c, d = 1, 1, 1000, 1000
print(a is b, c is d)

def foo():
    e = 1000
    f = 1000
    print(e is f, e is d)
    g = 1
    print(g is a)

foo()

运行结果:

True False
True False
True

上面代码中a is b的结果是Truec is d的结果是False,这一点的确让人费解。CPython解释器出于性能优化的考虑,把频繁使用的整数对象用一个叫small_ints的对象池缓存起来造成的。small_ints缓存的整数值被设定为[-5, 256]这个区间,也就是说,在任何引用这些整数的地方,都不需要重新创建int对象,而是直接引用缓存池中的对象。如果整数不在该范围内,那么即便两个整数的值相同,它们也是不同的对象。

CPython底层为了进一步提升性能还做了另一个设定,对于同一个代码块中值不在small_ints缓存范围内的整数,如果同一个代码块中已经存在一个值与其相同的整数对象,那么就直接引用该对象,否则创建新的int对象。需要大家注意的是,这条规则对数值型适用,但对字符串则需要考虑字符串的长度,这一点大家可以自行证明。

扩展:如果你用PyPy(另一种Python解释器实现,支持JIT,对CPython的缺点进行了改良,在性能上优于CPython,但对三方库的支持略差)来运行上面的代码,你会发现所有的输出都是True。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值