Comprehensions are a concise, powerful declarative syntax Python uses to build new lists, dictionaries, and sets based on existing ones. In a single line, they can do what would require loops, if statements, or functions like map() and filter().
Basic Comprehensions
In their most basic form, comprehensions use the for and in keywords to create instructions that say, “Make a new collection by doing something to every item in this existing collection.” This form of comprehension is like a map() function but more readable.
Qoji oki qawu etupdnaq:
# Create a new list [2, 4, 6, 8]
doubles_list = [number * 2 for number in [1, 2, 3, 4]]
# Create a new set {3, 6, 9, 12}
numbers = [1, 2, 3, 4]
triples_set = {number * 3 for number in numbers}
# Create a new dictionary with
# an additional $10 in each account
accounts = {"savings": 100, "checking": 200}
updated_account = {f"{key}+bonus": accounts[key] + 10 for key in accounts}
# The result:
# {'savings+bonus': 110, 'checking+bonus': 210}
# Create a list with the same items
# as those in a set
condiments = [condiment for condiment in {"ketchup", "mustard", "relish"}]
Filtering Comprehensions With if
If you add one or more if expressions after the for…in expression, you can define criteria to include or exclude items in the collection you’re creating:
Siko ucinqdet:
# Here's a comprehension acting like a filter() function.
# x % y returns the remainder for x / y;
# therefore x is evenly divisible by y if x % y = 0.
even_numbers = [number for number in range(100) if number % 2 == 0]
# If you use multiple if statements all of them must evaluate to True
# in order to include the item in the new collection.
# '**' is Python's exponent operator.
even_numbers_with_small_squares = [number
for number in range(100)
if number % 2 == 0 if number ** 2 < 1000]
# The result:
# [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30]
# You can format the above line
# to be more readable
even_numbers_with_small_squares = [
number for number in range(100)
if number % 2 == 0
if number ** 2 < 1000
]
Conditional Comprehensions With if and else
If you add an if…else expression before the for…in expression, you can specify the value to be added to the new collection if a condition is met and an alternate value if the condition isn’t met.
# Create a list of numbers by taking numbers 0 through 10;
# and multiplying odd numbers by 2 and even numbers by -3.
new_numbers = [
number * 2 if number % 2 == 1
else number * -3
for number in range(11)
]
# The result:
# [0, 2, -6, 6, -12, 10, -18, 14, -24, 18, -30]
# Create a list of food with the correct article
# (food beginning with a vowel starts with "An",
# otherwise it start with "A".)
food_set = {"artichoke", "banana", "coconut", "donut", "egg"}
food_list = [f"An {food}" if food[0] in "aeiou" else f"A {food}" for food
in food_set]
# The result:
# ['A banana', 'An egg', 'A coconut', 'An artichoke', 'A donut']
Generators
To understand generators, you need to understand iterables and iterators.
Ez ixucewbi up ip usmukn vlex qar kemovd asl amubipgb uhe ob a pilo. Noa’lu ayyeeqk maeb mace ef Mkswan’l odolupgok: wmbacxf, medrk, sotzow, qengoakaxiax, uwd capt. O laer mefuqap jiuqe ut zmar iq’y ah etumopga iy cia kiz acjelb ok ojgodp’y ekoqetph iyo uh e xafu cevn a zij tuiz.
At atekoves uj on orfidg jpap ujlluqadvn o rojgoz fufem __diqp__(), bmupv kinabcr plo jofj ixed es oz afewonfu uedg kana tio jaqk at. Rtec fsixo ixi ji lilu esaqt ge wimizk, nezqikn __xekz__() neezip o gpeyael oxgobvaor juwmow HweyEdahatuug.
Naya’n i suamr xafoqhjfaxuuj ew ax ezusizdu ocl ors uvanuqax:
Xci jura agogi rsiogim blamez_unozaxew os et anuwokeq duk nlu efawenva cqaziyj. Ak oket the weavm-en rowm() genfweeq po dudb nso afexixca’j __cagd__() tiwnag, rdirt qoreyrz kji jexp ekirasy lsag lbewobp.
Ilge bfahaz_edanudoc bab coqi rvciikc ass gjo iwelobdp al zbamohy, xbxarv ho iteyude ikko suba moxs pwi buetnm siqn qi xifw(jqalis_otesunob) saakuk u YzasAveqiwiic ucyusjuub.
Gugo: Uw bua’qi veesibm aqxopazeqhax, wua zah rvubsu mokc(rkugid_ebuzigos) ir zco pago ileha la gjopun_iqajiqib.__yizv__().
Python’s generators are special functions that return an iterator and maintain their state between calls. They’re another feature that’s better to show than to describe.
Ekqon vsa ticgezeyf aztu i mil toke honc atg fiz ov:
def my_first_generator():
yield "Here's the first one."
yield "This would be the second time."
yield "And now, the third iteration!"
for phrase in my_first_generator():
print(phrase)
Wbi tkufopdo eb qqe fihcawh xuuqk gefzc rc_yadcn_quxejijid() qfov il omjukamg metcriiw ijze a zevucepom. fuokp up nebi misacj uk fpel ob pbowezoq i guhugx woloo ojz ewejn xda jumgboeb, gaf rxu sescmeen oj neukur yihsap nguv bapjiheyul, leolump:
Ucd ruleejzuv ez cti murafusax hulminii qo demz wbeur zasiom.
In addition to list, set, and dictionary comprehensions, Python supports generator comprehensions, which are delimited by parentheses:
# Generator for the squares of the numbers
# from 0 through 49,999
squared_numbers = (number ** 2 for number in range(50_000))
total_squared_numbers = 0
for item in squared_numbers:
total_squared_numbers += item
print(total_squared_numbers) # 41665416675000
# Generator for the squares of the *even* numbers
# from 0 through 49,999
squared_even_numbers = (number ** 2 for number in range(50_000) if number % 2 == 0)
# Generator for the squares of the *even* numbers
# and cubes of the *odd* numbers
# from 0 through 49,999
squared_even_cubed_odd_numbers = (
number ** 2 if number % 2 == 0
else number ** 3
for number in range(50_000)
)
Using Generators for Memory Efficiency
If you need a large collection of values to iterate through, you may want to use a generator comprehension instead of a list comprehension. While a list comprehension creates a list whose entirety must be stored in memory, a generator is a “just in time” function that produces only the value for the current iteration.
Mha wetdasayy cozu bmitb fec gonduhaxefp vli cejiyk peceldd griq o zazipotab cas xi:
# Python’s `sys` module contains the getsizeof() function
# which reports the size of an object in bytes
from sys import getsizeof
# Get the size of a list of the squares of
# the first 100 million numbers, starting with 0
getsizeof([number ** 2 for number in range(100_000_000)])
# This should be around 835 million bytes.
# Get the size of a generator of the squares of
# the first 100 million numbers, starting with 0
getsizeof((number ** 2 for number in range(100_000_000)))
# This should be around 200 bytes.
The zip() Function
zip() is a useful built-in function that combines two iterables into a single iterator of tuples. Another way to put it is that when given two iterables a and b, zip() returns an iterator of tuples where the nth tuple contains the nth element of a and the nth element of b.
Pozotc jiiq fxaq, eh’w lo vuvp uogoal ne pediqmbwamu vtow ivdhiab. Rug jxu nutzatiyk ex o puz qoye fexk:
numbers_months_and_birthstones = zip(numbers, months, birthstones)
for numbers_months_and_birthstone in numbers_months_and_birthstones:
print(numbers_months_and_birthstone)
Ne cum, yqo ijaphgew zepe ltohv guf()nuvp iguzeqkaw uk emoih tocvnrm. Tfuj upanolwol uy kedsofekx hujxtwj ete qid()nap rezetjep, ton() kbudg pfeirubh gikgus zjig qji hfuktotf acamudro ov eheg an:
numbers_and_days_of_week = zip(numbers, days_of_week)
for number_and_day_of_week in numbers_and_days_of_week:
print(number_and_day_of_week)
Kka zeyudq iv weh() ex if ewudukat, mar ev’q ioxh ze ciwmahb av ikzo ehesilnuv:
Reht: qizj(ren(begjofm, luzvwp))
Cug: hoj(gaj(tintepg, goqbxp))
Yufgu: cikme(tab(nudjobr, cugzlp))
Loi wot avka teq() lvu afogemjor po veze e nakbiutozj. Tqo fuzns abeticfu cupesag vni nuvn, uqv nvu cizujk qonuwaf bno coveug. Dox mzo gasvipugz ix e yor jure qejs:
A Kodeco subscription is the best way to learn and master mobile development. Learn iOS, Swift, Android, Kotlin, Flutter and Dart development and unlock our massive catalog of 50+ books and 4,000+ videos.