map()Aşırı liste kavrayışı kullanmayı tercih etmek için bir neden var mı ? Bunlardan herhangi biri genel olarak daha verimli midir yoksa genel olarak diğerinden daha fazla pitonik kabul edilir mi?
map()Aşırı liste kavrayışı kullanmayı tercih etmek için bir neden var mı ? Bunlardan herhangi biri genel olarak daha verimli midir yoksa genel olarak diğerinden daha fazla pitonik kabul edilir mi?
Yanıtlar:
mapbazı durumlarda mikroskobik olarak daha hızlı olabilir (amaç için bir lambda yapmadığınızda, ancak aynı işlevi harita ve listcomp'da kullandığınızda). Liste kavrayışları diğer durumlarda daha hızlı olabilir ve çoğu (hepsi değil) pythonista onları daha doğrudan ve daha net olarak görür.
Tam olarak aynı işlevi kullanırken haritanın küçük hız avantajına bir örnek:
$ python -mtimeit -s'xs=range(10)' 'map(hex, xs)'
100000 loops, best of 3: 4.86 usec per loop
$ python -mtimeit -s'xs=range(10)' '[hex(x) for x in xs]'
100000 loops, best of 3: 5.58 usec per loop
Harita lambdaya ihtiyaç duyduğunda performans karşılaştırmasının nasıl tamamen tersine döndüğüne bir örnek:
$ python -mtimeit -s'xs=range(10)' 'map(lambda x: x+2, xs)'
100000 loops, best of 3: 4.24 usec per loop
$ python -mtimeit -s'xs=range(10)' '[x+2 for x in xs]'
100000 loops, best of 3: 2.32 usec per loop
map(operator.attrgetter('foo'), objs)okumak daha kolay [o.foo for o in objs]?!
oBurada olduğu gibi gereksiz isimler vermemeyi tercih ediyorum ve örnekleriniz bunun nedenini gösteriyor.
str()örneği var.
Kılıflar
map varsa, 'unpythonic' olarak kabul edilmesine rağmen , genellikle kullanımı makul olur . Örneğin map(sum, myLists), daha zarif / kısa [sum(x) for x in myLists]. Sadece yinelemek için iki kez yazmanız gereken bir kukla değişken (örneğin sum(x) for x...veya sum(_) for _...veya sum(readableName) for readableName...) oluşturmamanın zarafetini kazanırsınız . Aynı argüman modül için filterve reduceherhangi bir şey için geçerlidir itertools: zaten kullanışlı bir fonksiyonunuz varsa, devam edip bazı fonksiyonel programlama yapabilirsiniz. Bu, bazı durumlarda okunabilirlik kazanır ve diğerlerinde (örneğin acemi programcılar, çoklu argümanlar) kaybeder ... ancak kodunuzun okunabilirliği büyük ölçüde yorumlarınıza bağlıdır.mapFonksiyonel programlama yaparken, haritaladığınız mapveya köreldiğiniz map, veya mapfonksiyon olarak konuşmaktan başka şekilde faydalandığınız zaman, fonksiyonu saf bir soyut fonksiyon olarak kullanmak isteyebilirsiniz . Örneğin Haskell'de, adı verilen bir functor arabirimi fmap, herhangi bir veri yapısı üzerinde eşlemeyi genelleştirir. Bu python'da çok nadirdir, çünkü python dilbilgisi sizi yineleme hakkında konuşmak için jeneratör tarzı kullanmaya zorlar; kolayca genelleme yapamazsınız. (Bu bazen iyi ve bazen kötüdür.) Muhtemelen map(f, *lists)yapılacak makul bir şey olan nadir piton örnekleriyle karşılaşabilirsiniz . Gelebileceğim en yakın örnek sumEach = partial(map,sum), çok kabaca eşdeğer olan bir astar olan:def sumEach(myLists):
return [sum(_) for _ in myLists]
for-loop kullanarak : Tabii ki sadece for-loop kullanabilirsiniz. İşlevsel programlama bakış açısından zarif olmasa da, bazen yerel olmayan değişkenler python gibi zorunlu programlama dillerinde kodu daha net hale getirir, çünkü insanlar kodu bu şekilde okumaya çok alışkındır. For-loop'lar, genellikle, sadece liste kavrama ve harita gibi bir liste oluşturmayan herhangi bir karmaşık işlemi yaparken en etkilidir (örneğin, toplama veya ağaç yapma, vb.) - en azından bellek açısından verimli (bazı nadir patolojik çöp toplama hıçkırıklarını yasaklayan en kötü sabit bir faktörden beklediğim zaman açısından değil)."Pythonism"
"Pitonik" kelimesinden hoşlanmıyorum çünkü pitoniklerin gözlerimde her zaman zarif olduğunu bulamıyorum. Bununla birlikte, mapve filterbenzer işlevler (çok faydalı itertoolsmodül gibi) muhtemelen stil açısından ses kayıtsız olarak kabul edilir.
Tembellik
Verimlilik açısından, çoğu fonksiyonel programlama yapısı gibi, MAP LAZY OLABİLİR ve aslında python'da tembeldir. Bu, bunu yapabileceğiniz anlamına gelir ( python3'te ) ve bilgisayarınızın belleği tükenmez ve kaydedilmemiş tüm verilerinizi kaybetmez:
>>> map(str, range(10**100))
<map object at 0x2201d50>
Bunu bir liste kavrayışı ile yapmayı deneyin:
>>> [str(n) for n in range(10**100)]
# DO NOT TRY THIS AT HOME OR YOU WILL BE SAD #
Liste kavrayışlarının da doğal olarak tembel olduğunu, ancak python'un tembel olmayan olarak uygulamayı seçtiğini unutmayın . Bununla birlikte, python, aşağıdaki gibi jeneratör ifadeleri biçimindeki tembel liste anlamalarını destekler:
>>> (str(n) for n in range(10**100))
<generator object <genexpr> at 0xacbdef>
Temel [...]olarak sözdizimini, bir oluşturucu ifadesinde liste yapıcısına iletmek gibi düşünebilirsiniz list(x for x in range(5)).
Kısa örnek
from operator import neg
print({x:x**2 for x in map(neg,range(5))})
print({x:x**2 for x in [-y for y in range(5)]})
print({x:x**2 for x in (-y for y in range(5))})
Liste anlamaları tembel değildir, bu nedenle daha fazla bellek gerekebilir (jeneratör anlamalarını kullanmadığınız sürece). Köşeli parantezler [...], özellikle parantez karmaşasında olduğunda, işleri genellikle belirginleştirir. Öte yandan, bazen yazmak gibi ayrıntılı olursunuz [x for x in.... Yineleyici değişkenlerinizi kısa tuttuğunuz sürece, kodunuzu girintilendirmezseniz liste anlaşmaları genellikle daha açıktır. Ancak kodunuzu her zaman girintili yapabilirsiniz.
print(
{x:x**2 for x in (-y for y in range(5))}
)
veya bir şeyleri parçalayın:
rangeNeg5 = (-y for y in range(5))
print(
{x:x**2 for x in rangeNeg5}
)
Python3 için verimlilik karşılaştırması
map şimdi tembel:
% python3 -mtimeit -s 'xs=range(1000)' 'f=lambda x:x' 'z=map(f,xs)'
1000000 loops, best of 3: 0.336 usec per loop ^^^^^^^^^
Bu nedenle, tüm verilerinizi kullanmayacaksanız veya önceden ne kadar veriye ihtiyacınız olduğunu bilmiyorsanız, mappython3'te (ve python2 veya python3'teki jeneratör ifadeleri) son ana kadar değerlerini hesaplamaktan kaçınır. Genellikle bu genellikle herhangi bir ek yükü kullanımdan daha ağır basacaktır map. Dezavantajı, bunun çoğu işlevsel dilin aksine python'da çok sınırlı olmasıdır: bu avantajı yalnızca verilerinize soldan sağa "sırayla" eriştiğinizde elde edersiniz, çünkü python oluşturucu ifadeleri yalnızca sipariş değerlendirilebilir x[0], x[1], x[2], ....
Ancak diyelim ki fistediğimiz önceden yapılmış bir fonksiyonumuz var mapve mapderhal değerlendirmeyi zorlayarak tembelliklerini görmezden geliyoruz list(...). Çok ilginç sonuçlar elde ediyoruz:
% python3 -mtimeit -s 'xs=range(1000)' 'f=lambda x:x' 'z=list(map(f,xs))'
10000 loops, best of 3: 165/124/135 usec per loop ^^^^^^^^^^^^^^^
for list(<map object>)
% python3 -mtimeit -s 'xs=range(1000)' 'f=lambda x:x' 'z=[f(x) for x in xs]'
10000 loops, best of 3: 181/118/123 usec per loop ^^^^^^^^^^^^^^^^^^
for list(<generator>), probably optimized
% python3 -mtimeit -s 'xs=range(1000)' 'f=lambda x:x' 'z=list(f(x) for x in xs)'
1000 loops, best of 3: 215/150/150 usec per loop ^^^^^^^^^^^^^^^^^^^^^^
for list(<generator>)
Sonuçlarda A / python 3.?.? İle Intel iş istasyonunda A ile gerçekleştirilen AAA / BBB / CCC biçimindedir ve B ve C python 3.2.1 ile 2013 dolaylarında AMD iş istasyonu ile gerçekleştirilmiştir son derece farklı bir donanıma sahip. Sonuç, harita ve liste kavrayışlarının, diğer rastgele faktörlerden en güçlü şekilde etkilenen performansla karşılaştırılabilir olduğu görülmektedir. Anlayabileceğimiz tek şey, garip bir şekilde, liste kavrayışlarının [...]jeneratör ifadelerinden daha iyi performans göstermesini beklerken (...), jeneratör ifadelerinden de mapdaha etkilidir (yine tüm değerlerin değerlendirildiğini / kullanıldığını varsayarak).
Bu testlerin çok basit bir fonksiyon (kimlik fonksiyonu) aldığını fark etmek önemlidir; ancak bu iyi bir durumdur, çünkü fonksiyon karmaşık olsaydı, performans yükü programdaki diğer faktörlere kıyasla önemsiz olacaktır. (Gibi diğer basit şeylerle test etmek hala ilginç olabilir f=lambda x:x+x)
Python montajını okuma becerisine sahipseniz, bu dismodülleri kullanarak perde arkasında neler olup bittiğini görebilirsiniz:
>>> listComp = compile('[f(x) for x in xs]', 'listComp', 'eval')
>>> dis.dis(listComp)
1 0 LOAD_CONST 0 (<code object <listcomp> at 0x2511a48, file "listComp", line 1>)
3 MAKE_FUNCTION 0
6 LOAD_NAME 0 (xs)
9 GET_ITER
10 CALL_FUNCTION 1
13 RETURN_VALUE
>>> listComp.co_consts
(<code object <listcomp> at 0x2511a48, file "listComp", line 1>,)
>>> dis.dis(listComp.co_consts[0])
1 0 BUILD_LIST 0
3 LOAD_FAST 0 (.0)
>> 6 FOR_ITER 18 (to 27)
9 STORE_FAST 1 (x)
12 LOAD_GLOBAL 0 (f)
15 LOAD_FAST 1 (x)
18 CALL_FUNCTION 1
21 LIST_APPEND 2
24 JUMP_ABSOLUTE 6
>> 27 RETURN_VALUE
>>> listComp2 = compile('list(f(x) for x in xs)', 'listComp2', 'eval')
>>> dis.dis(listComp2)
1 0 LOAD_NAME 0 (list)
3 LOAD_CONST 0 (<code object <genexpr> at 0x255bc68, file "listComp2", line 1>)
6 MAKE_FUNCTION 0
9 LOAD_NAME 1 (xs)
12 GET_ITER
13 CALL_FUNCTION 1
16 CALL_FUNCTION 1
19 RETURN_VALUE
>>> listComp2.co_consts
(<code object <genexpr> at 0x255bc68, file "listComp2", line 1>,)
>>> dis.dis(listComp2.co_consts[0])
1 0 LOAD_FAST 0 (.0)
>> 3 FOR_ITER 17 (to 23)
6 STORE_FAST 1 (x)
9 LOAD_GLOBAL 0 (f)
12 LOAD_FAST 1 (x)
15 CALL_FUNCTION 1
18 YIELD_VALUE
19 POP_TOP
20 JUMP_ABSOLUTE 3
>> 23 LOAD_CONST 0 (None)
26 RETURN_VALUE
>>> evalledMap = compile('list(map(f,xs))', 'evalledMap', 'eval')
>>> dis.dis(evalledMap)
1 0 LOAD_NAME 0 (list)
3 LOAD_NAME 1 (map)
6 LOAD_NAME 2 (f)
9 LOAD_NAME 3 (xs)
12 CALL_FUNCTION 2
15 CALL_FUNCTION 1
18 RETURN_VALUE
[...]Sözdizimini kullanmaktan daha iyi görünüyor list(...). Ne yazık ki mapsınıf demontaj için biraz opak, ancak hız testimizle yapabiliriz.
mapve filterstandart kütüphane ile birlikte itertoolsdoğal olarak kötü tarzı vardır. GvR aslında ya korkunç bir hata ya da sadece performans için söylemedikçe, "Pythonicness" in söylediği tek doğal sonuç, bunu aptal gibi unutmaktır ;-)
mapfilter düşmeyi / Python 3 için harika bir fikir olarak düşündü ve sadece diğer Pythonistaların isyanı onları yerleşik ad alanında tuttu ( reducetaşındı functools). Şahsen katılmıyorum ( mapve filterönceden tanımlanmış, özellikle yerleşik işlevler konusunda iyiyim, sadece lambdagerektiğinde bunları kullanmayın ), ancak GvR temel olarak onları yıllarca Pythonic olarak adlandırmadı.
itertoolsmuydu? Bu cevaptan alıntı yaptığım kısım, beni rahatsız eden ana iddiadır. İdeal dünyasında olup olmadığını bilmiyorum mapve filtertamamen hareket edip etmeyeceğini itertoolsya functoolsda tamamen gideceğini bilmiyorum , ama hangisi olursa olsun, bir kere itertoolsbunun tamamen Pythonic olduğunu söylediği zaman, o zaman “Pythonic” in ne olduğunu gerçekten bilmiyorum ama "GvR'nin insanların kullanmasını önerdiklerine" benzer bir şey olabileceğini düşünmüyorum.
map/ filterdeğil itertools. Fonksiyonel programlama mükemmel Pythonic olan ( itertools, functoolsve operatortüm akılda fonksiyonel programlama ile özel olarak tasarlanmış ve ben Python her zaman fonksiyonel deyimleri kullanın) ve itertoolsO, özellikle oluyor bir ağrı kendinizi uygulamak olacaktır özellikler sağlar mapve filterjeneratör ifadeleriyle olmanın gereksiz Guido onlardan nefret ediyordu. itertoolsher zaman iyiydi.
mapve filterkullanmalısınız.Bir objektif onlar değiliz rağmen onları tercih etmelidir nedeni "Pythonic" şudur:
Onlar argümanlar gibi işlevleri / lambdas gerektiren yeni bir kapsam tanıtmak .
Bunu bir kereden fazla ısırdım:
for x, y in somePoints:
# (several lines of code here)
squared = [x ** 2 for x in numbers]
# Oops, x was silently overwritten!
ama onun yerine şöyle demiştim:
for x, y in somePoints:
# (several lines of code here)
squared = map(lambda x: x ** 2, numbers)
o zaman her şey iyi olurdu.
Aynı değişken adını aynı kapsamda kullandığım için aptal olduğumu söyleyebilirsin.
Ben değildim. Kod başlangıçta iyiydi - ikisi xaynı kapsamda değildi.
Sadece iç bloğu kodun farklı bir bölümüne taşıdıktan sonra sorun ortaya çıktı (okuma: bakım sırasında sorun, geliştirme değil) ve beklemiyordum.
Evet, bu hatayı asla yapmazsanız , liste kavrayışları daha zariftir.
Ama kişisel deneyimlerden (ve başkalarının da aynı hatayı yaptığını görünce), bu hatalar kodunuza girdiğinde geçmeniz gereken acıya değmeyeceğini düşünüyorum.
Kullanım mapve filter. Kapsamla ilgili zor teşhis edilen küçük hataları önlerler.
Durumunuza uygun olup olmadığını imapve ifilter(in itertools) kullanmayı düşünmeyi unutmayın !
mapve / veya geçişinin mantıklı bir nedeni değildir filter. Eğer bir şey varsa, probleminizi önlemek için en doğrudan ve mantıklı çeviri değil, JeromeJ'un işaret ettiği gibi, sızıntı yapmayan map(lambda x: x ** 2, numbers)bir jeneratör ifadesidir list(x ** 2 for x in numbers). Bak Mehrdad, şahsen bu kadar kişisel oy kullanmayın, buradaki akıl yürütmenize kesinlikle katılmıyorum.
Aslında, mapliste kavrayışları Python 3 dilinde oldukça farklı davranıyor. Aşağıdaki Python 3 programına bir göz atın:
def square(x):
return x*x
squares = map(square, [1, 2, 3])
print(list(squares))
print(list(squares))
"[1, 4, 9]" satırını iki kez yazdırmasını bekleyebilirsiniz, bunun yerine "[1, 4, 9]" ve ardından "[]" yazdırabilir. İlk bakışta squaresüç elementten oluşan bir dizi gibi görünüyor, ama ikinci kez boş olan gibi.
Python 2'de map, liste kavrayışlarının her iki dilde yaptığı gibi düz eski bir liste döndürür. En önemli nokta mapPython 3'teki (ve imapPython 2'deki) dönüş değerinin bir liste olmamasıdır - bu bir yineleyici!
Öğeler, bir liste üzerinde yinelemenin aksine bir yineleyici üzerinden yinelendiğinde tüketilir. Bu yüzden squaresson print(list(squares))satırda boş görünüyor .
Özetlemek:
mapbir yineleyici değil, bir veri yapısı üretmek. Ancak tembel yineleyiciler tembel veri yapılarından daha kolaydır. Düşünce için yiyecek. Thanks @MnZrK
Liste kavrayışlarını genel olarak yapmaya çalıştığım şeyden daha etkileyici buluyorum map- her ikisi de bunu başardı, ancak birincisi karmaşık bir lambdaifade ne olabileceğini anlamaya çalışmanın zihinsel yükünü kurtarıyor .
Ayrıca orada Guido'nun lambdas ve fonksiyonel işlevleri Python'a kabul etmekten en çok pişman olduğu şey olarak listelediği bir yerde bir röportaj var (bunu hazırlıksız bulamıyorum) , böylece erdem yoluyla Pythonic olmadıklarını iddia edebilirsiniz. bunun.
constC ++ anahtar kelimesi bu satırlar boyunca büyük bir zaferdir.
lambdao kadar topal hale getirildi (ifade yok ..), kullanımı zor ve yine de sınırlı.
İşte olası bir durum:
map(lambda op1,op2: op1*op2, list1, list2)
karşı:
[op1*op2 for op1,op2 in zip(list1,list2)]
Zip (), harita yerine liste anlayışlarını kullanmakta ısrar ederseniz şımartmanız gereken talihsiz ve gereksiz bir ek yük olduğunu tahmin ediyorum. Birisi bunu olumlu ya da olumsuz olarak açıklarsa harika olur.
ziptembel yapabilirsinizitertools.izip
map(operator.mul, list1, list2). Bu çok basit sol taraftaki ifadelerde kavrayışların sakıncası olur.
Herhangi bir eşzamansız, paralel veya dağıtılmış kod yazmayı planlıyorsanız, büyük olasılıkla mapliste kavramasını tercih edersiniz - çoğu eşzamansız, paralel veya dağıtılmış paket mappythonları aşırı yüklemek için bir işlev sağlar map. Daha sonra uygun mapişlevi kodunuzun geri kalanına ileterek, orijinal seri kodunuzu paralel olarak (vb.) Çalıştıracak şekilde değiştirmeniz gerekmeyebilir.
Python 3, map()bir yineleyici olduğundan, neye ihtiyacınız olduğunu aklınızda bulundurmanız gerekir: bir yineleyici veya listnesne.
@AlexMartelli'nin daha önce de belirtildiği gibi , map()yalnızca lambdaişlevi kullanmıyorsanız liste kavrayışından daha hızlıdır .
Size zaman karşılaştırmaları sunacağım.
Python 3.5.2 ve CPython
ben kullandım Jüpiter dizüstü ve özellikle %timeityerleşik sihirli komut
Ölçümler : s == 1000 ms == 1000 * 1000 us = 1000 x 1000 x 1000 ns
Kurmak:
x_list = [(i, i+1, i+2, i*2, i-9) for i in range(1000)]
i_list = list(range(1000))
Dahili fonksiyon:
%timeit map(sum, x_list) # creating iterator object
# Output: The slowest run took 9.91 times longer than the fastest.
# This could mean that an intermediate result is being cached.
# 1000000 loops, best of 3: 277 ns per loop
%timeit list(map(sum, x_list)) # creating list with map
# Output: 1000 loops, best of 3: 214 µs per loop
%timeit [sum(x) for x in x_list] # creating list with list comprehension
# Output: 1000 loops, best of 3: 290 µs per loop
lambda fonksiyon:
%timeit map(lambda i: i+1, i_list)
# Output: The slowest run took 8.64 times longer than the fastest.
# This could mean that an intermediate result is being cached.
# 1000000 loops, best of 3: 325 ns per loop
%timeit list(map(lambda i: i+1, i_list))
# Output: 1000 loops, best of 3: 183 µs per loop
%timeit [i+1 for i in i_list]
# Output: 10000 loops, best of 3: 84.2 µs per loop
Jeneratör ekspresyonu diye bir şey de vardır, bkz. PEP-0289 . Bu yüzden karşılaştırmaya eklemek yararlı olacağını düşündüm
%timeit (sum(i) for i in x_list)
# Output: The slowest run took 6.66 times longer than the fastest.
# This could mean that an intermediate result is being cached.
# 1000000 loops, best of 3: 495 ns per loop
%timeit list((sum(x) for x in x_list))
# Output: 1000 loops, best of 3: 319 µs per loop
%timeit (i+1 for i in i_list)
# Output: The slowest run took 6.83 times longer than the fastest.
# This could mean that an intermediate result is being cached.
# 1000000 loops, best of 3: 506 ns per loop
%timeit list((i+1 for i in i_list))
# Output: 10000 loops, best of 3: 125 µs per loop
listNesneye ihtiyacınız var :Özel işlevse liste kavrama özelliğini kullanın list(map()), yerleşik işlev varsa kullanın
listNesneye ihtiyacınız yok , sadece tekrarlanabilir olana ihtiyacınız var:Her zaman kullanın map()!
Bir nesnenin yöntemini çağırmak için üç yöntemi karşılaştırarak hızlı bir test çalıştırdı. Bu durumda zaman farkı ihmal edilebilir ve söz konusu fonksiyonun konusudur (@Alex Martelli'nin cevabına bakınız ). Burada, aşağıdaki yöntemlere baktım:
# map_lambda
list(map(lambda x: x.add(), vals))
# map_operator
from operator import methodcaller
list(map(methodcaller("add"), vals))
# map_comprehension
[x.add() for x in vals]
Liste boyutlarını artırmak için valshem tamsayıların (Python int) hem de kayan nokta numaralarının (Python float) listelerine (değişkente saklanır) baktım . Aşağıdaki kukla sınıf DummyNumdikkate alınır:
class DummyNum(object):
"""Dummy class"""
__slots__ = 'n',
def __init__(self, n):
self.n = n
def add(self):
self.n += 5
Özellikle, addyöntem. __slots__Özelliği, bellek boyutu azaltılması, sınıf (nitelikler) tarafından ihtiyaç duyulan toplam bellek tanımlamak için Python basit bir iyileştirmedir. Ortaya çıkan araziler.
Daha önce belirtildiği gibi, kullanılan teknik minimum bir fark yaratır ve sizin için veya belirli durumlarda en okunabilir şekilde kodlamanız gerekir. Bu durumda, liste kavrama ( map_comprehensionteknik), özellikle daha kısa listelerle, bir nesnedeki her iki ekleme türü için en hızlıdır.
Çizim ve verileri oluşturmak için kullanılan kaynak için bu macunu ziyaret edin .
mapdaha önce açıklandığı gibi, sadece fonksiyon aynı şekilde çağrıldığında (yani [*map(f, vals)]vs. [f(x) for x in vals]) daha hızlıdır . Yani list(map(methodcaller("add"), vals))daha hızlı [methodcaller("add")(x) for x in vals]. mapDöngü muadili, bazı ek yükleri önleyebilecek farklı bir çağrı yöntemi kullandığında daha hızlı olmayabilir (örneğin x.add(), methodcallerveya lambda ifadesi ek yükünü önler ). Bu özel test için [*map(DummyNum.add, vals)]hızlı (çünkü olacağını DummyNum.add(x)ve x.add()temelde aynı performansa sahip).
list()çağrılar liste kavrayışlarından biraz daha yavaştır. Adil bir karşılaştırma için yazmanız gerekir [*map(...)].
list()çağrıların genel olarak arttığını bilmiyordum . Cevapları okumak için daha fazla zaman harcamalıydım. Bu testleri adil bir karşılaştırma için tekrar çalıştıracağım, ancak farklar ihmal edilebilir.
En Pitonik yolun mapve yerine bir liste kavrayışı kullanmak olduğunu düşünüyorum filter. Nedeni listesi comprehensions daha net olmasıdır mapve filter.
In [1]: odd_cubes = [x ** 3 for x in range(10) if x % 2 == 1] # using a list comprehension
In [2]: odd_cubes_alt = list(map(lambda x: x ** 3, filter(lambda x: x % 2 == 1, range(10)))) # using map and filter
In [3]: odd_cubes == odd_cubes_alt
Out[3]: True
Gördüğünüz gibi, bir anlayış ihtiyaç olarak fazladan lambdaifade gerektirmez map. İken Ayrıca, bir anlama da kolayca filtreleme sağlar mapgerektirir filterolanak tanımak için.
@ Alex-martelli tarafından kodu denedim ama bazı tutarsızlıklar buldum
python -mtimeit -s "xs=range(123456)" "map(hex, xs)"
1000000 loops, best of 5: 218 nsec per loop
python -mtimeit -s "xs=range(123456)" "[hex(x) for x in xs]"
10 loops, best of 5: 19.4 msec per loop
Harita çok geniş aralıklar için bile aynı süreyi alırken, liste kavrama özelliğini kullanmak benim kodumda görüldüğü gibi çok zaman alır. Bu yüzden "unpythonic" olarak değerlendirilmenin dışında, haritanın kullanımı ile ilgili herhangi bir performans sorunuyla karşılaşmadım.
mapbir liste döndüren Python 2'ye referansla yazılmıştır . Python 3'te maptembel bir şekilde değerlendirildiğinden, basitçe çağırmak mapyeni liste öğelerinin hiçbirini hesaplamaz, bu yüzden neden bu kadar kısa süreler alırsınız.