2017年度python面試題超綱20道(二)

2018你還是沒有貓

相關鏈接:

??我知道有人覺得問題就在stackoverflow上有什么好寫的,但是我答案是自己寫的,我將我解決的思路分享記錄,自己思考一遍總比寡看一遍stackoverflow上的問題好的多你說對吧~

Speed up millions of regex replacements in Python 3

為Python3中百萬次級的正則替換提速

compiled_words = [re.compile(r'\b' + word + r'\b') for word in my20000words]

import re
for sentence in sentences:
  for word in compiled_words:
    sentence = re.sub(word, "", sentence)
  # put sentence into a growing list
# This nested loop is processing about 50 sentences per second

??正經(jīng)回答:寫成這種形式能提速"\b(word1|word2|word3)\b",題目的寫法會重復百萬次的編譯c代碼過程。
??不正經(jīng)回答:換庫,用FlashText,官方說法是Regex速度與量成正比,而FlashText幾乎保持常數(shù)不動,看下面對比圖。

執(zhí)行replace操作的速度對比圖

Union of 2 sets does not contain all items

兩個集合做并集,為什么會丟失集合中的元素?

set1 = {1, 2, 3}
set2 = {True, False}

print(set1 | set2)
# {False, 1, 2, 3}

print(set2 | set1)
#{False, True, 2, 3}

??對啊,為什么并集還丟數(shù)據(jù),摔。等等,先開你的終端試試。

>>> 1 == True
True
>>> 0 == False
True
>>> {0, False}
{0}
>>> {False, 0}
{False}

??繼續(xù)摔,雖然知道了原因,但要同時用1True怎么辦?
??你可以試試這樣

>>> set1 = {(1, int), (2, int), (3, int)}
>>> set2 = {(True, bool), (False, bool)}
>>> set1 | set2
{(3, <class 'int'>), (1, <class 'int'>), (2, <class 'int'>),
 (True, <class 'bool'>), (False, <class 'bool'>)}
>>> set1 & set2
set()

&emsp;&emsp;# 或者
>>> set1 = {'1', '2', '3'}
>>> set2 = {'True', 'False'}
>>> set1 | set2
{'2', '3', 'False', 'True', '1'}
>>> set1 & set2
set()

??雖然是麻煩了點,但好歹能用了。

What is the difference between i = i + 1 and i += 1 in a 'for' loop?

在for循環(huán)中,i = i + 1 和 i += 1的區(qū)別?

??這個確實比較...嗯...難查。翻了很多資料,最后再python的官方文檔找到差別,++=調(diào)用的方法不一樣,其中,+=調(diào)用object.__iadd__(self, other),+調(diào)用object.__add__(self, other)。
??我把原文及網(wǎng)址貼出來,我怕我自己翻譯過來變了味道,基本都能看懂

These methods are called to implement the augmented arithmetic assignments (+=, -=, *=, @=, /=, //=, %=, **=, <<=, >>=, &=, ^=, |=). These methods should attempt to do the operation in-place (modifying self) and return the result (which could be, but does not have to be, self). If a specific method is not defined, the augmented assignment falls back to the normal methods. For instance, if x is an instance of a class with an iadd() method, x += y is equivalent to x = x.iadd(y) . Otherwise, x.add(y) and y.radd(x) are considered, as with the evaluation of x + y. In certain situations, augmented assignment can result in unexpected errors (see Why does a_tuple[i] += [‘item’] raise an exception when the addition works?), but this behavior is in fact part of the data model.
https://docs.python.org/3/reference/datamodel.html#emulating-numeric-types

Why is copying a shuffled list much slower?

為什么拷貝一個隨機排序的列表慢?

??這題問起來就比較難懂我先完善一下題目,大家看一下如下兩種程序運行速度:

from timeit import timeit
import random

#case1 run: 5.84262761547 s
print timeit(lambda: random.shuffle(range(10**6)), number=10)

#case2 run: 1.07579151663 s
print timeit(lambda: range(10**6), number=10)

??題目問的就是這兩種方式速度為什么會相差那么大?摔,這題真的很難,講道理面試官就是不想讓你進這家公司吧。
??查了很多資料(真的很多),我大概是知道是什么意思的,但是可能自己寫的不太到位,如果大家有更準確的表達方式請寫在評論區(qū)。

  • 影響列表復制速度的因素是什么?
    • 列表復制的速度是取決于列表元素在堆中的順序。
  • 列表的復制又是一個什么操作?
    • Python所有對象都在heap上,因此每個對象都是指針。
    • 這里的列表復制是淺操作
    • Pytohn的數(shù)字也是對象,你定義的整形1實際上是對對象1的引用。而且Python使用引用計數(shù),所以當一個對象放在一個新的容器,它的引用計數(shù)必須遞增,所以pytohn不能僅僅是復制引用,而是真的需要去物理地址那里一趟(意會一下)。
  • shuffle操作后在物理層面對原列表進行了哪些更改?
    • 看一段代碼
      import random
      a = list(range(10**6, 100+10**6))
      random.shuffle(a)
      last = None
      for item in a:
          if last is not None:
              print('diff', id(item) - id(last))
          last = item
      # diff 736
      # diff -64
      # diff -17291008
      # diff -128
      # diff 288
      # diff -224
      # diff 17292032
      # diff -1312
      # diff 1088
      # .
      # .
      # .
      

??綜上其實已經(jīng)可以得出速度變慢的原因:進行shuffle操作后,它們的引用位置更差,導致緩存性能更差。而復制列表不僅是復制引用,復制操作仍然需要為了修改訪問每個對象的引用計數(shù)。
??你就當我在寫數(shù)學證明題吧...

Why do tuples take less space in memory than lists?

為什么元組比列表消耗更少的內(nèi)存?

>>> a = (1,2,3)
>>> a.__sizeof__()
48

>>> b = [1,2,3]
>>> b.__sizeof__()
64

??看完上面的題就覺得這種實在是簡單...顯而易見的因為兩種的數(shù)據(jù)結(jié)構不同,看下圖來找茬。


list與tuple數(shù)據(jù)結(jié)構示意圖
  • tuple中的元素不可修改,list可以。
  • list.ob_item 是指向列表對象的指針數(shù)組。
  • list.allocated 是申請內(nèi)存的槽的個數(shù)。
    ??因為存的多所以占用內(nèi)存大嘛,了以理解。
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容