当面试官要求现场手敲代码,该如何体现你对Python的编程能力?
文章來(lái)源于Python數(shù)據(jù)科學(xué),作者wLsq
如果你已經(jīng)通過(guò)了招聘人員的電話(huà)面試,那么下面正是該展現(xiàn)你代碼能力的時(shí)候了。無(wú)論是練習(xí),作業(yè),還是現(xiàn)場(chǎng)白板面試,這都是你證明自己的代碼技巧的時(shí)刻。
我們知道面試官常常會(huì)出一些題讓你來(lái)解決,作為一名程序員,除了需要具備解決問(wèn)題的思路以外,代碼的質(zhì)量和簡(jiǎn)潔性也很關(guān)鍵。因?yàn)閺囊粋€(gè)人的代碼可以直接看出你的基本功。對(duì)于Python而言,這就意味著你需要對(duì)Python的內(nèi)置功能和庫(kù)有很深入的了解。
本篇給大家介紹一些很強(qiáng)大的功能,它們能讓面試官眼前一亮,覺(jué)得你很高級(jí),這可以很大程度上給你加分。對(duì)于這些功能,我們從Python內(nèi)置函數(shù)開(kāi)始,然后是Python對(duì)數(shù)據(jù)結(jié)構(gòu)的天然支持,最后是Python強(qiáng)大的標(biāo)準(zhǔn)庫(kù)。
選擇正確的內(nèi)置功能
Python有一個(gè)大型標(biāo)準(zhǔn)庫(kù),但只有一個(gè)內(nèi)置函數(shù)的小型庫(kù),這些函數(shù)總是可用的,不需要導(dǎo)入。它們每一個(gè)都值得我們仔細(xì)研究,但是在研究前,我還是給大家一些小的提示,尤其是在其中一些函數(shù)的情況下,可以用什么替代更好。
1. 使用enumerate()而不是range()進(jìn)行迭代
在面試中,這種情況可能比任何其他情況都要多:您有一個(gè)元素列表,您需要遍歷列表,同時(shí)訪(fǎng)問(wèn)索引和值。
有一個(gè)名為FizzBuzz的經(jīng)典編碼面試問(wèn)題可以通過(guò)迭代索引和值來(lái)解決。在FizzBuzz中,你將獲得一個(gè)整數(shù)列表,任務(wù)是執(zhí)行以下操作:
用“fizz”替換所有可被3整除的整數(shù)
用“buzz”替換所有可被5整除的整數(shù)
將所有可被3和5整除的整數(shù)替換為“fizzbuzz”
通常,開(kāi)發(fā)人員將使用range()解決此問(wèn)題:
>>> numbers = [45, 22, 14, 65, 97, 72] >>> for i in range(len(numbers)): ... if numbers[i] % 3 == 0 and numbers[i] % 5 == 0: ... numbers[i] = 'fizzbuzz' ... elif numbers[i] % 3 == 0: ... numbers[i] = 'fizz' ... elif numbers[i] % 5 == 0: ... numbers[i] = 'buzz' ... >>> numbers ['fizzbuzz', 22, 14, 'buzz', 97, 'fizz']Range允許你通過(guò)索引訪(fǎng)問(wèn)數(shù)字元素,并且對(duì)于某些特殊情況也是一個(gè)很有用的工具。但在這種情況下,我們希望同時(shí)獲取每個(gè)元素的索引和值,更優(yōu)雅的解決方案使用enumerate():
>>> numbers = [45, 22, 14, 65, 97, 72] >>> for i, num in enumerate(numbers): ... if num % 3 == 0 and num % 5 == 0: ... numbers[i] = 'fizzbuzz' ... elif num % 3 == 0: ... numbers[i] = 'fizz' ... elif num % 5 == 0: ... numbers[i] = 'buzz' ... >>> numbers ['fizzbuzz', 22, 14, 'buzz', 97, 'fizz']對(duì)于每個(gè)元素,enumerate()返回一個(gè)計(jì)數(shù)器和元素值。計(jì)數(shù)器默認(rèn)為0,也是元素的索引。不想在0開(kāi)始你的計(jì)數(shù)?只需使用可選的start參數(shù)來(lái)設(shè)置偏移量:
>>> numbers = [45, 22, 14, 65, 97, 72] >>> for i, num in enumerate(numbers, start=52): ... print(i, num) ... 52 45 53 22 54 14 55 65 56 97 57 72通過(guò)使用start參數(shù),我們?cè)L問(wèn)所有相同的元素,從第一個(gè)索引開(kāi)始,但現(xiàn)在我們的計(jì)數(shù)從指定的整數(shù)值開(kāi)始。
2. 使用遞推式構(gòu)造列表而不是map()和filter()?
“我認(rèn)為刪除filter()和map()是非常有爭(zhēng)議的。”?
- Guido van Rossum,Python的創(chuàng)造者?
一般使用者可能錯(cuò)誤地認(rèn)為它沒(méi)有爭(zhēng)議,但Guido有充分的理由想要從Python中刪除map()和filter()。一個(gè)原因是Python支持遞推式構(gòu)造列表,它通常更容易閱讀并支持與map()和filter()相同的功能。?
讓我們首先看看我們?nèi)绾螛?gòu)造對(duì)map()的調(diào)用以及等效的遞推構(gòu)造列表:
>>> numbers = [4, 2, 1, 6, 9, 7] >>> def square(x): ... return x*x ... >>> list(map(square, numbers)) [16, 4, 1, 36, 81, 49]>>> [square(x) for x in numbers] [16, 4, 1, 36, 81, 49]使用map()和列表推導(dǎo)的兩種方法都返回相同的值,但列表推導(dǎo)更容易閱讀和理解。下面我們可以對(duì)filter()及其等效的列表推導(dǎo)做同樣的事情:
>>> def is_odd(x): ... return bool(x % 2) ... >>> list(filter(is_odd, numbers)) [1, 9, 7]>>> [x for x in numbers if is_odd(x)] [1, 9, 7]就像我們?cè)趍ap中看到的那樣,filter和列表推導(dǎo)方法返回相同的值,但列表推導(dǎo)更容易理解。?
來(lái)自其他語(yǔ)言的開(kāi)發(fā)人員可能不同意構(gòu)造列表比map和filter更容易閱讀,但根據(jù)我的經(jīng)驗(yàn),初學(xué)者能夠更直觀地寫(xiě)出列表推導(dǎo)。但無(wú)論哪種方式,在編碼面試中使用列表推導(dǎo)很少會(huì)出錯(cuò),因?yàn)樗鼤?huì)讓你知道Python中最常見(jiàn)的是什么。
3. 使用斷點(diǎn)breakpoint()調(diào)試而不是print()
你可能通過(guò)在代碼中添加print并查看打印出的內(nèi)容來(lái)調(diào)試一個(gè)小問(wèn)題。這種方法起初效果很好,但很快變得很麻煩。另外,在編碼面試設(shè)置中,你幾乎不希望在整個(gè)代碼中調(diào)用print()。?
相反,你應(yīng)該使用調(diào)試器。對(duì)于不是很瑣碎的錯(cuò)誤,它幾乎總是比使用print()更快,并且鑒于調(diào)試是編寫(xiě)軟件的重要部分,它表明你知道如何使用可以在工作中快速開(kāi)發(fā)的工具。?
如果你使用的是Python 3.7,則無(wú)需導(dǎo)入任何內(nèi)容,只需在代碼中要放入調(diào)試器的位置調(diào)用breakpoint():
# Some complicated code with bugsbreakpoint()調(diào)用breakpoint()會(huì)將你帶入pdb,這是默認(rèn)的Python調(diào)試器。在Python 3.6及更早版本中,你可以通過(guò)顯式導(dǎo)入pdb來(lái)執(zhí)行相同的操作:
import pdb; pdb.set_trace()像breakpoint()一樣,pdb.set_trace()會(huì)將你帶入pdb調(diào)試器。它不是那么簡(jiǎn)潔,而且需要記住的多一點(diǎn)。你可能想要嘗試其他調(diào)試器,但pdb是標(biāo)準(zhǔn)庫(kù)的一部分,因此它始終可用。無(wú)論你喜歡哪種調(diào)試器,在進(jìn)行編碼面試設(shè)置之前,都值得嘗試使用它們來(lái)適應(yīng)工作流程。
4. 使用f-Strings格式化字符串?
Python有很多不同的方法來(lái)處理字符串格式化,有時(shí)候不知道使用哪個(gè)。在coding的面試中,如果使用Python 3.6+,建議的格式化方法是Python的f-strings。?
f-strings支持使用字符串格式化迷你語(yǔ)言,以及強(qiáng)大的字符串插值。這些功能允許你添加變量甚至有效的Python表達(dá)式,并在添加到字符串之前在運(yùn)行時(shí)對(duì)它們進(jìn)行評(píng)估:
>>> def get_name_and_decades(name, age): ... return f"My name is {name} and I'm {age / 10:.5f} decades old." ... >>> get_name_and_decades("Maria", 31) My name is Maria and I'm 3.10000 decades old.f-string允許你將Maria放入字符串中,并在一個(gè)簡(jiǎn)潔的操作中添加具有所需格式的年齡。需要注意的一個(gè)風(fēng)險(xiǎn)是,如果你輸出用戶(hù)生成的值,那么可能會(huì)帶來(lái)安全風(fēng)險(xiǎn),在這種情況下,模板字符串可能是更安全的選擇。
5. 使用sorted()對(duì)復(fù)雜列表進(jìn)行排序
大量的編碼面試問(wèn)題需要進(jìn)行某種排序,并且有多種有效的方法可以進(jìn)行排序。除非面試官希望你實(shí)現(xiàn)自己的排序算法,否則通常最好使用sorted()。你可能已經(jīng)看到了排序的最簡(jiǎn)單用法,例如按升序或降序排序數(shù)字或字符串列表:
>>> sorted([6,5,3,7,2,4,1]) [1, 2, 3, 4, 5, 6, 7]>>> sorted(['cat', 'dog', 'cheetah', 'rhino', 'bear'], reverse=True) ['rhino', 'dog', 'cheetah', 'cat', 'bear]默認(rèn)情況下,sorted()已按升序?qū)斎脒M(jìn)行排序,而reverse關(guān)鍵字參數(shù)則按降序排序。
值得了解的是可選關(guān)鍵字key,它允許你在排序之前指定將在每個(gè)元素上調(diào)用的函數(shù)。添加函數(shù)允許自定義排序規(guī)則,如果要對(duì)更復(fù)雜的數(shù)據(jù)類(lèi)型進(jìn)行排序,這些規(guī)則特別有用:
通過(guò)傳入一個(gè)返回每個(gè)元素年齡的lambda函數(shù),可以輕松地按每個(gè)字典的單個(gè)值對(duì)字典列表進(jìn)行排序。在這種情況下,字典現(xiàn)在按年齡按升序排序。
有效利用數(shù)據(jù)結(jié)構(gòu)
算法在面試中得到了很多關(guān)注,但數(shù)據(jù)結(jié)構(gòu)可能更為重要。在coding面試環(huán)境中,選擇正確的數(shù)據(jù)結(jié)構(gòu)會(huì)對(duì)性能產(chǎn)生重大影響。除了理論數(shù)據(jù)結(jié)構(gòu)之外,Python還在其標(biāo)準(zhǔn)數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)中內(nèi)置了強(qiáng)大而方便的功能。這些數(shù)據(jù)結(jié)構(gòu)在面試中非常有用,因?yàn)樗鼈兡J(rèn)為你提供了許多功能,讓你可以將時(shí)間集中在問(wèn)題的其他部分。
1. 使用set存儲(chǔ)唯一值
我們通常需要從現(xiàn)有數(shù)據(jù)集中刪除重復(fù)元素。新的開(kāi)發(fā)人員有時(shí)會(huì)在列表應(yīng)該使用集合時(shí)執(zhí)行此操作,這會(huì)強(qiáng)制執(zhí)行所有元素的唯一性。
假裝你有一個(gè)名為get_random_word()的函數(shù)。它將始終從一小組單詞中返回一個(gè)隨機(jī)選擇:
>>> import random >>> all_words = "all the words in the world".split() >>> def get_random_word(): ... return random.choice(all_words)你應(yīng)該重復(fù)調(diào)用get_random_word()以獲取1000個(gè)隨機(jī)單詞,然后返回包含每個(gè)唯一單詞的數(shù)據(jù)結(jié)構(gòu)。以下是兩種常見(jiàn)的次優(yōu)方法和一種好的方法。
糟糕的方法
get_unique_words()將值存儲(chǔ)在列表中,然后將列表轉(zhuǎn)換為集合:
>>> def get_unique_words(): ... words = [] ... for _ in range(1000): ... words.append(get_random_word()) ... return set(words) >>> get_unique_words() {'world', 'all', 'the', 'words'}這種方法并不可怕,但它不必要地創(chuàng)建了一個(gè)列表,然后將其轉(zhuǎn)換為集合。面試官幾乎總是注意到(并詢(xún)問(wèn))這種類(lèi)型的設(shè)計(jì)選擇。
更糟糕的做法
為避免從列表轉(zhuǎn)換為集合,你現(xiàn)在可以在不使用任何其他數(shù)據(jù)結(jié)構(gòu)的情況下將值存儲(chǔ)在列表中。然后,通過(guò)將新值與列表中當(dāng)前的所有元素進(jìn)行比較來(lái)測(cè)試唯一性:
>>> def get_unique_words(): ... words = [] ... for _ in range(1000): ... word = get_random_word() ... if word not in words: ... words.append(word) ... return words >>> get_unique_words() ['world', 'all', 'the', 'words']這比第一種方法更糟糕,因?yàn)槟惚仨殞⒚總€(gè)新單詞與列表中已有的每個(gè)單詞進(jìn)行比較。這意味著隨著單詞數(shù)量的增加,查找次數(shù)呈二次方式增長(zhǎng)。換句話(huà)說(shuō),時(shí)間復(fù)雜度在O(N^2)的量級(jí)上增長(zhǎng)。?
優(yōu)秀的方法?
現(xiàn)在,你完全跳過(guò)使用列表,而是從頭開(kāi)始使用一組:
>>> def get_unique_words(): ... words = set() ... for _ in range(1000): ... words.add(get_random_word()) ... return words >>> get_unique_words() {'world', 'all', 'the', 'words'}除了從頭開(kāi)始使用集合之外,這可能與其他方法沒(méi)有太大的不同。如果你考慮.add()中發(fā)生了什么,它甚至聽(tīng)起來(lái)像第二種方法:得到單詞,檢查它是否已經(jīng)在集合中,如果沒(méi)有,則將其添加到數(shù)據(jù)結(jié)構(gòu)中。?
那么為什么使用與第二種方法不同的集合呢??
它們是不同的,因?yàn)榧洗鎯?chǔ)元素的方式允許接近恒定時(shí)間檢查值是否在集合中,而不像需要線(xiàn)性時(shí)間查找的列表。查找時(shí)間的差異意味著添加到集合的時(shí)間復(fù)雜度以O(shè)(N)的速率增長(zhǎng),這在大多數(shù)情況下比第二種方法的O(N^2)好得多。
2. 使用生成器節(jié)省內(nèi)存
前面提到,列表推導(dǎo)是方便的工具,但有時(shí)會(huì)導(dǎo)致不必要的內(nèi)存使用。想象一下,你被要求找到前1000個(gè)完美正方形的總和,從1開(kāi)始。你知道列表推導(dǎo),所以你快速編寫(xiě)一個(gè)有效的解決方案:
>>> sum([i * i for i in range(1, 1001)]) 333833500解決方案會(huì)列出1到1,000,000之間的每個(gè)完美平方,并對(duì)值進(jìn)行求和。你的代碼會(huì)返回正確的答案,但隨后您的面試官會(huì)開(kāi)始增加您需要總和的完美正方形的數(shù)量。?
起初,你的功能不斷彈出正確的答案,但很快就開(kāi)始放慢速度,直到最后這個(gè)過(guò)程似乎永遠(yuǎn)持續(xù)下去。這不是你想要在面試中發(fā)生的一件事。?
這里發(fā)生了什么??
它正在列出你要求的每個(gè)完美的方塊,并將它們?nèi)考悠饋?lái)。具有1000個(gè)完美正方形的列表在計(jì)算機(jī)術(shù)語(yǔ)中可能不會(huì)很大,但是1億或10億是相當(dāng)多的信息,并且很容易占用計(jì)算機(jī)的可用內(nèi)存資源。這就是這里發(fā)生的事情。
值得慶幸的是,有一種解決內(nèi)存問(wèn)題的快捷方法。你只需用括號(hào)替換方括號(hào):
>>> sum((i * i for i in range(1, 1001))) 333833500換出括號(hào)會(huì)將列表推導(dǎo)更改為生成器表達(dá)式。當(dāng)你知道要從序列中檢索數(shù)據(jù),但不需要同時(shí)訪(fǎng)問(wèn)所有數(shù)據(jù)的時(shí)候,生成器表達(dá)式非常適合。?
生成器表達(dá)式返回生成器對(duì)象,而不是創(chuàng)建列表。該對(duì)象知道它在當(dāng)前狀態(tài)中的位置(例如,i = 49)并且僅在被要求時(shí)計(jì)算下一個(gè)值。?
因此,當(dāng)sum通過(guò)重復(fù)調(diào)用.__ next __()來(lái)迭代生成器對(duì)象時(shí),生成器檢查i
等于多少,計(jì)算i * i,在內(nèi)部遞增i,并將正確的值返回到sum。該設(shè)計(jì)允許生成器用于大量數(shù)據(jù)序列,因?yàn)橐淮沃挥幸粋€(gè)元素存在于內(nèi)存中。
3. 使用.get()和.setdefault()在字典中定義默認(rèn)值?
最常見(jiàn)的編程任務(wù)之一涉及添加,修改或檢索可能在字典中或可能不在字典中的項(xiàng)。Python字典具有優(yōu)雅的功能,可以使這些任務(wù)簡(jiǎn)潔明了,但開(kāi)發(fā)人員通常會(huì)在不需要時(shí)檢查值。?
想象一下,你有一個(gè)名為cowboy的字典,你想得到那個(gè)cowboy的名字。一種方法是使用條件顯式檢查key:
>>> cowboy = {'age': 32, 'horse': 'mustang', 'hat_size': 'large'} >>> if 'name' in cowboy: ... name = cowboy['name'] ... else: ... name = 'The Man with No Name' ... >>> name 'The Man with No Name'此方法首先檢查字典中是否存在name鍵,如果存在,則返回相應(yīng)的值。否則,它返回默認(rèn)值。?
雖然清楚地檢查key確實(shí)有效,但如果使用.get(),它可以很容易地用一行代替:
>>> name = cowboy.get('name', 'The Man with No Name')get()執(zhí)行與第一種方法相同的操作,但現(xiàn)在它們會(huì)自動(dòng)處理。如果key存在,則返回適當(dāng)?shù)闹?。否則,將返回默認(rèn)值。?
但是,如果你想在仍然訪(fǎng)問(wèn)name的key時(shí)使用默認(rèn)值更新字典呢?.get()在這里沒(méi)有真正幫助你,所以你只需要再次顯式檢查這個(gè)值:
>>> if 'name' not in cowboy: ... cowboy['name'] = 'The Man with No Name' ... >>> name = cowboy['name']檢查values并設(shè)置默認(rèn)值是一種有效的方法,并且易于閱讀,但Python再次使用.setdefault()提供了更優(yōu)雅的方法:
>>> name = cowboy.setdefault('name', 'The Man with No Name').setdefault()完成與上面代碼片段完全相同的操作。它檢查cowboy中是否存在名稱(chēng),如果是,則返回該值。否則,它將cowboy ['name']設(shè)置為T(mén)he Man with No Name并返回新值。
利用Python的標(biāo)準(zhǔn)庫(kù)
默認(rèn)情況下,Python提供了許多功能,這些功能只是一個(gè)導(dǎo)入語(yǔ)句。它本身就很強(qiáng)大,但知道如何利用標(biāo)準(zhǔn)庫(kù)可以增強(qiáng)你的編碼面試技巧。
從所有可用模塊中挑選最有用的部分很困難,因此本節(jié)將僅關(guān)注其實(shí)用功能的一小部分。希望這些對(duì)您在編碼訪(fǎng)談中有用,并且您希望了解更多有關(guān)這些和其他模塊的高級(jí)功能的信息。
1. 使用collections.defaultdict()處理缺少的字典鍵?
當(dāng)你為單個(gè)鍵設(shè)置默認(rèn)值時(shí),.get()和.setdefault()可以正常工作,但通常需要為所有可能的未設(shè)置鍵設(shè)置默認(rèn)值,尤其是在面試環(huán)境中進(jìn)行編程時(shí)。?
假裝你有一群學(xué)生,你需要記錄他們?cè)诩彝プ鳂I(yè)上的成績(jī)。輸入值是具有格式(student_name,grade)的元組列表,但是你希望輕松查找單個(gè)學(xué)生的所有成績(jī)而無(wú)需迭代列表。?
存儲(chǔ)成績(jī)數(shù)據(jù)的一種方法是使用將學(xué)生姓名映射到成績(jī)列表的字典:
>>> student_grades = {} >>> grades = [ ... ('elliot', 91), ... ('neelam', 98), ... ('bianca', 81), ... ('elliot', 88), ... ] >>> for name, grade in grades: ... if name not in student_grades: ... student_grades[name] = [] ... student_grades[name].append(grade) ... >>> student_grades {'elliot': [91, 88], 'neelam': [98], 'bianca': [81]}在這種方法中,你迭代學(xué)生并檢查他們的名字是否已經(jīng)是字典中的屬性。如果沒(méi)有,則將它們添加到字典中,并將空列表作為默認(rèn)值。然后將實(shí)際成績(jī)附加到該學(xué)生的成績(jī)列表中。
但是有一個(gè)更簡(jiǎn)潔的方法,可以使用defaultdict,它擴(kuò)展了標(biāo)準(zhǔn)的dict功能,允許你設(shè)置一個(gè)默認(rèn)值,如果key不存在,它將按默認(rèn)值操作:
>>> from collections import defaultdict >>> student_grades = defaultdict(list) >>> for name, grade in grades: ... student_grades[name].append(grade)在這種情況下,你將創(chuàng)建一個(gè)defaultdict,它使用不帶參數(shù)的list構(gòu)造函數(shù)作為默認(rèn)方法。沒(méi)有參數(shù)的list返回一個(gè)空列表,因此如果名稱(chēng)不存在則defaultdict調(diào)用list(),然后再把學(xué)生成績(jī)添加上。如果你想更炫一點(diǎn),你也可以使用lambda函數(shù)作為值來(lái)返回任意常量。
利用defaultdict可以使代碼更簡(jiǎn)潔,因?yàn)槟悴槐負(fù)?dān)心key的默認(rèn)值。相反,你可以在defaultdict里處理它們一次,然后key就終存在了。
2. 使用collections.Counter計(jì)算Hashable對(duì)象?
假如你有一長(zhǎng)串沒(méi)有標(biāo)點(diǎn)符號(hào)或大寫(xiě)字母的單詞,你想要計(jì)算每個(gè)單詞出現(xiàn)的次數(shù)。?
你可以使用字典或defaultdict增加計(jì)數(shù),但collections.Counter提供了一種更清晰,更方便的方法。Counter是dict的子類(lèi),它使用0作為任何缺失元素的默認(rèn)值,并且更容易計(jì)算對(duì)象的出現(xiàn)次數(shù):
>>> from collections import Counter >>> words = "if there was there was but if \ ... there was not there was not".split() >>> counts = Counter(words) >>> counts Counter({'if': 2, 'there': 4, 'was': 4, 'not': 2, 'but': 1})當(dāng)你將單詞列表傳遞給Counter時(shí),它會(huì)存儲(chǔ)每個(gè)單詞以及該單詞在列表中出現(xiàn)的次數(shù)。
如果你好奇兩個(gè)最常見(jiàn)的詞是什么?只需使用.most_common():
>>> counts.most_common(2) [('there', 4), ('was', 4)].most-common()是一個(gè)方便的方法,只需按計(jì)數(shù)返回n個(gè)最頻繁的輸入。
3. 使用字符串常量訪(fǎng)問(wèn)公共字符串組
現(xiàn)在有一個(gè)瑣事需要判斷!‘A’>‘a(chǎn)’是真是假?
這是假的,因?yàn)锳的ASCII代碼是65,但a是97,65不大于97。為什么答案很重要?因?yàn)槿绻阆霗z查一個(gè)字符是否是英語(yǔ)字母表的一部分,一種流行的方法是看它是否在A和Z之間(在ASCII圖表上是65和122)。
檢查ascii代碼是可行的,但是在面試時(shí)卻很笨拙,很容易弄亂,特別是當(dāng)你記不清是小寫(xiě)還是大寫(xiě)的ascii字符排在第一位的時(shí)候。這時(shí)候,使用定義在字符串模塊中的常量要容易得多。
你可以使用is_upper(),它返回字符串中的所有字符是否都是大寫(xiě)字母:
>>> import string >>> def is_upper(word): ... for letter in word: ... if letter not in string.ascii_uppercase: ... return False ... return True ... >>> is_upper('Thanks Geir') False >>> is_upper('LOL') Trueis_upper()迭代word中的字母,并檢查字母是否為string.ascii_大寫(xiě)字母的一部分。如果你打印出string.ascii_大寫(xiě),你會(huì)發(fā)現(xiàn)它只是一個(gè)字符串,該值設(shè)置為文本“ABCDEFGHIJKLMNOPQRSTUVWXYZ”。
所有字符串常量都只是經(jīng)常引用的字符串值的字符串。其中包括以下內(nèi)容:
string.ascii_letters
string.ascii_uppercase
string.ascii_lowercase
string.digits
string.hexdigits
string.octdigits
string.punctuation
string.printable
string.whitespace
這些更容易使用,更重要的是,更容易閱讀。
4. 使用Itertools生成排列和組合
面試官喜歡給出真實(shí)生活的場(chǎng)景,讓面試看起來(lái)不那么嚇人,所以這里有一個(gè)人為的例子:你去游樂(lè)園,決定找出每一對(duì)可能坐在過(guò)山車(chē)上的朋友。
除非生成這些配對(duì)是面試問(wèn)題的主要目的,否則很可能生成所有可能的配對(duì)只是朝著工作算法前進(jìn)的一個(gè)乏味的步驟。你可以自己用嵌套for循環(huán)計(jì)算它們,也可以使用強(qiáng)大的itertools庫(kù)。
itertools有多個(gè)工具來(lái)生成可重復(fù)輸入數(shù)據(jù)序列,但現(xiàn)在我們只關(guān)注兩個(gè)常見(jiàn)函數(shù):itertools.permutations()和itertools.combinations()。
itertools.permutations()構(gòu)建所有排列的列表,這意味著它是輸入值的每個(gè)可能分組的列表,其長(zhǎng)度與count參數(shù)匹配。r關(guān)鍵字參數(shù)允許我們指定每個(gè)分組中有多少值:
>>> import itertools >>> friends = ['Monique', 'Ashish', 'Devon', 'Bernie'] >>> list(itertools.permutations(friends, r=2)) [('Monique', 'Ashish'), ('Monique', 'Devon'), ('Monique', 'Bernie'), ('Ashish', 'Monique'), ('Ashish', 'Devon'), ('Ashish', 'Bernie'), ('Devon', 'Monique'), ('Devon', 'Ashish'), ('Devon', 'Bernie'), ('Bernie', 'Monique'), ('Bernie', 'Ashish'), ('Bernie', 'Devon')]對(duì)于排列,元素的順序很重要,因此(“sam”、“devon”)表示與(“devon”、“sam”)不同的配對(duì),這意味著它們都將包含在列表中。
itertools.combinations()生成組合。這些也是輸入值的可能分組,但現(xiàn)在值的順序無(wú)關(guān)緊要。因?yàn)?‘sam’、‘devon’)和(‘devon’、‘sam’)代表同一對(duì),所以輸出列表中只會(huì)包含它們中的一個(gè):
>>> list(itertools.combinations(friends, r=2)) [('Monique', 'Ashish'), ('Monique', 'Devon'), ('Monique', 'Bernie'), ('Ashish', 'Devon'), ('Ashish', 'Bernie'), ('Devon', 'Bernie')]由于值的順序與組合有關(guān),因此同一輸入列表的組合比排列少。同樣,因?yàn)槲覀儗設(shè)置為2,所以每個(gè)分組中都有兩個(gè)名稱(chēng)。
.combinations和.permutations只是強(qiáng)大庫(kù)的一個(gè)小例子,但是當(dāng)你試圖快速解決算法問(wèn)題時(shí),即使這兩個(gè)函數(shù)也非常有用。
在下一次面試中,你可以放心地使用一些不太常見(jiàn)但功能更強(qiáng)大的標(biāo)準(zhǔn)特性。從整體上來(lái)說(shuō),要了解該語(yǔ)言有很多東西,但本文應(yīng)該為大家提供一個(gè)起點(diǎn),讓大家能夠更深入地了解該語(yǔ)言,同時(shí)在面試時(shí)更有效地使用Python。
備注:公眾號(hào)菜單包含了整理了一本AI小抄,非常適合在通勤路上用學(xué)習(xí)。
往期精彩回顧適合初學(xué)者入門(mén)人工智能的路線(xiàn)及資料下載機(jī)器學(xué)習(xí)在線(xiàn)手冊(cè)深度學(xué)習(xí)在線(xiàn)手冊(cè)AI基礎(chǔ)下載(pdf更新到25集)備注:加入本站微信群或者qq群,請(qǐng)回復(fù)“加群”獲取一折本站知識(shí)星球優(yōu)惠券,請(qǐng)回復(fù)“知識(shí)星球”喜歡文章,點(diǎn)個(gè)在看
總結(jié)
以上是生活随笔為你收集整理的当面试官要求现场手敲代码,该如何体现你对Python的编程能力?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 重磅 | GitHub 2019 数字年
- 下一篇: Github标星66.6k+:常见数据结