لیستها
تا اینجا هر متغیر یک مقدار داشت. برای نگه داشتن نمره سی دانشآموز، سی متغیر لازم بود. لیست این مشکل را حل میکند و در عمل پرکاربردترین ساختمان داده پایتون است.
۱. ساختن لیست
لیست مجموعهای مرتب از مقدارهاست که داخل کروشه نوشته میشوند و با ویرگول از هم جدا میشوند.
# A list holds several values in one variable, in a fixed order,
# written between square brackets and separated by commas.
animals = ['Cat', 'Lion', 'Dog', 'Wolf']
numbers = [5, 7, 15, 32, 104, 1]
empty = [] # a list with nothing in it
print(animals)
print(numbers)
print(empty)
print(animals[0]) # the first item
print(type(animals)) # <class 'list'>
print(len(animals)) # how many items -> 4
# A list may even mix different types (rarely a good idea, but it is allowed).
mixed = ['Ali', 20, 19.5, True]
print(mixed)
ساختن لیست: نمونه 01_create_list.py
['Cat', 'Lion', 'Dog', 'Wolf'] [5, 7, 15, 32, 104, 1] [] Cat <class 'list'> 4 ['Ali', 20, 19.5, True]
شرح مثال
- لیست خالی
[]نقطه شروع بسیاری از برنامههاست: لیست را خالی میسازید و بعد پرش میکنید. lenهمان تابعی است که روی رشته دیدیم و اینجا تعداد اعضا را میدهد.- لیست میتواند انواع مختلف را با هم داشته باشد، ولی این کار معمولاً نشانه طراحی بد است. لیست باید مجموعهای از چیزهای همجنس باشد.
۲. اندیس و برش
همه چیزهایی که در فصل سوم درباره اندیس و برش رشته یاد گرفتید، عیناً برای لیست هم صادق است.
# Indexes and slices work exactly like they do on strings.
cars = ['BMW', 'Benz', 'Pride', 'Paykan', 'Ford']
print(cars[0]) # 'BMW'
print(cars[-1]) # 'Ford' -> the last one
print(cars[1:3]) # ['Benz', 'Pride']
print(cars[:2]) # ['BMW', 'Benz']
print(cars[2:]) # ['Pride', 'Paykan', 'Ford']
print(cars[::-1]) # the list reversed
اندیس و برش لیست: نمونه 02_indexing_slicing.py
دقت کنید که cars[0] یک رشته میدهد ولی
cars[1:3] یک لیست. اندیس یک عضو میدهد،
برش همیشه لیست میدهد، حتی اگر فقط یک عضو داشته باشد.
۳. لیست تغییرپذیر است
این مهمترین تفاوت لیست با رشته است. رشته را نمیشد عوض کرد، لیست را میشود.
# A list is MUTABLE: an item can be replaced without creating a new list.
cars = ['BMW', 'Benz', 'Pride']
cars[2] = 'Peugeot'
print(cars) # ['BMW', 'Benz', 'Peugeot']
# A whole slice can be replaced as well.
cars[0:2] = ['Mazda', 'Kia']
print(cars)
# Remember: a string cannot be changed like this,
# name = 'kadoos'
# name[0] = 'K' -> TypeError
تغییرپذیری: نمونه 03_mutable.py
| رشته | لیست | |
|---|---|---|
| تغییر یک عضو | ممکن نیست | ممکن است |
| متدها | رشته تازه برمیگردانند | خود لیست را عوض میکنند |
| نمونه | s = s.upper() | lst.append(x) |
این تفاوت را خوب به خاطر بسپارید: متدهای لیست معمولاً چیزی
برنمیگردانند و مستقیم خود لیست را عوض میکنند. نوشتن
numbers = numbers.append(5) یک اشتباه رایج است که مقدار
None را در متغیر میریزد و لیست را از دست میدهید.
۴. اضافه کردن عضو
numbers = [10, 20, 30]
# append() adds ONE item at the end.
numbers.append(40)
print(numbers) # [10, 20, 30, 40]
# insert() adds an item at a chosen position.
numbers.insert(0, 5)
print(numbers) # [5, 10, 20, 30, 40]
# extend() adds all the items of another list.
numbers.extend([50, 60])
print(numbers) # [5, 10, 20, 30, 40, 50, 60]
# Careful: append() with a list adds the LIST itself as one single item.
numbers.append([70, 80])
print(numbers) # [..., 60, [70, 80]]
# '+' builds a new list without touching the originals.
print([1, 2] + [3, 4])
اضافه کردن: نمونه 04_add_items.py
| متد | وظیفه آن |
|---|---|
append(x) | یک عضو به انتها اضافه میکند |
insert(i, x) | یک عضو در جای مشخص جا میدهد |
extend(lst) | همه اعضای یک لیست دیگر را اضافه میکند |
+ | لیست تازه میسازد، اصلیها دستنخورده میمانند |
append([70, 80]) کل لیست را به عنوان یک
عضو اضافه میکند، پس لیستی تودرتو میسازید.
extend([70, 80]) اعضایش را یکییکی
اضافه میکند. هر دو مجازند و هر کدام کاربرد خودش را دارد، ولی قاطی
کردنشان باگهای عجیب میسازد.
۵. حذف کردن عضو
numbers = [5, 20, -7, 8, 14]
# pop() removes an item BY POSITION and returns it.
last = numbers.pop() # no argument -> the last item
print('Removed:', last, '->', numbers)
first = numbers.pop(0) # by index
print('Removed:', first, '->', numbers)
# remove() removes the first item equal to the given VALUE.
numbers.remove(8)
print(numbers)
# del removes by index (or by slice) without returning anything.
del numbers[0]
print(numbers)
# clear() empties the list.
numbers.clear()
print(numbers) # []
حذف کردن: نمونه 05_remove_items.py
| روش | بر اساس | مقدار برمیگرداند |
|---|---|---|
pop() | جایگاه، پیشفرض آخری | بله |
remove(x) | مقدار، اولین تطابق | خیر |
del lst[i] | جایگاه یا برش | خیر |
clear() | همه چیز | خیر |
اگر remove مقداری را پیدا نکند، خطای ValueError
میدهد. پس پیش از حذف، با in بررسی کنید که واقعاً وجود دارد.
۶. جستوجو در لیست
cars = ['BMW', 'Benz', 'Pride', 'Paykan', 'Ford', 'Benz']
car = input('Enter the car name: ')
# 'in' tells us whether a value exists in the list.
if car in cars:
print(car, 'found.')
else:
print(car, 'not found!')
# index() gives the position of the FIRST occurrence.
print(cars.index('Pride'))
# count() says how many times a value appears.
print(cars.count('Benz')) # 2
جستوجو: نمونه 06_search_in_list.py
سه ابزار جستوجو: in برای «هست یا نیست»، index برای «کجاست» و count برای «چند تا». مثل remove، اگر index چیزی پیدا نکند خطا ایجاد میکند، پس معمولاً اول با in بررسی میکنند.
۷. پیمایش لیست
numbers = [200, 350, 40, 1000, 270]
# Way 1 (the usual one): loop directly over the items.
for number in numbers:
print(number, end=' ')
print()
# Way 2: loop over the indexes. Useful when we also need the position,
# or when we want to CHANGE the items.
for i in range(len(numbers)):
print(f'index {i} -> {numbers[i]}')
# Changing every item needs the index version.
for i in range(len(numbers)):
numbers[i] = numbers[i] * 2
print(numbers)
دو روش پیمایش: نمونه 07_loop_over_list.py
شرح مثال
- روش اول تمیزتر و پایتونیتر است. هر وقت فقط به مقدار نیاز دارید، همین را به کار ببرید.
- روش دوم وقتی لازم است که به جایگاه هم نیاز دارید، یا میخواهید اعضا را عوض کنید.
- چرا برای تغییر باید اندیس داشته باشیم؟ چون در روش اول،
numberفقط یک کپی از مقدار است. اگر بنویسیدnumber = number * 2، لیست اصلی هیچ تغییری نمیکند. - در فصل بیست و پنجم ابزار
enumerateرا میبینید که هم مقدار و هم اندیس را با هم میدهد و از هر دوی این موارد بهتر است.
۸. ساختن لیست از ورودی کاربر
# Starting from an empty list and filling it with append().
numbers = []
while True:
user_input = input('Enter a number (or "exit"): ')
if user_input == 'exit':
break
numbers.append(float(user_input))
print('You entered:', numbers)
print('How many:', len(numbers))
if len(numbers) > 0:
total = 0
for number in numbers:
total += number
print('Average:', total / len(numbers))
پر کردن لیست: نمونه 08_build_from_input.py
اینجا سه چیزی که تا حالا یاد گرفتهاید کنار هم آمدهاند: حلقه نگهبان از فصل هشتم، الگوی انباره از فصل ششم و لیست از این فصل. تقریباً همه برنامههای واقعی همین شکل را دارند: جمع کن، بعد پردازش کن.
۹. برنامه: میانگین طول نامها
# Reading names into a list and computing the average length of the names.
names = []
while True:
user_input = input('Enter a name (or "exit"): ')
if user_input == 'exit':
break
names.append(user_input)
if len(names) == 0:
print('No name was entered.')
else:
total = 0
for name in names:
total += len(name)
print('Average length of the names:', total / len(names))
میانگین طول نامها: نمونه 09_names_length.py
باز هم بررسی لیست خالی پیش از تقسیم. این را به عادت تبدیل کنید: هر جا
len(...) در مخرج یک تقسیم است، حالت صفر را جدا بررسی کنید.
۱۰. لیست به عنوان پشته و صف
پشته ساختاری است که «آخرین ورودی، اولین خروجی» است. درست مثل دسته بشقاب: بشقابی که آخر گذاشتهاید، اول برداشته میشود.
# A stack is a "last in, first out" container.
# A Python list is already a perfect stack: append() to push, pop() to pop.
my_stack = []
my_stack.append(5)
my_stack.append(20)
my_stack.append(-7)
print(my_stack) # [5, 20, -7]
item = my_stack.pop() # takes the LAST item
print('Popped:', item) # -7
print(my_stack) # [5, 20]
my_stack.pop()
print(my_stack) # [5]
# By popping index 0 instead, the list behaves as a queue (first in, first out).
queue = [5, 20, -7, 8, 14]
queue.pop(0)
queue.pop(0)
print(queue) # [-7, 8, 14]
پشته و صف: نمونه 10_stack.py
شرح مثال
- پشته با
appendوpop()ساخته میشود. دکمه بازگشت در مرورگر و دکمه undo در ویرایشگر، همگی پشتهاند. - صف برعکس است: «اولین ورودی، اولین خروجی»، مثل صف نانوایی. با
pop(0)ساخته میشود. - نکته فنی:
pop(0)کند است، چون همه اعضا باید یک خانه جابهجا شوند. برای صفهای بزرگ، پایتون ابزار بهتری به نامdequeدر ماژولcollectionsدارد که در فصل پانزدهم میبینید.
۱۱. دام کپی کردن لیست
این بخش را با دقت بخوانید. یکی از گیجکنندهترین رفتارهای پایتون برای تازهکارها همین است.
# IMPORTANT TRAP: '=' does not copy a list, it only gives it a second name.
list1 = [1, 2, 3]
list2 = list1
list2.append(4)
print(list1) # [1, 2, 3, 4] -> list1 changed too!
# To get a real copy use copy(), list() or a full slice.
list3 = list1.copy()
list3.append(5)
print(list1) # [1, 2, 3, 4] -> unchanged
print(list3) # [1, 2, 3, 4, 5]
list4 = list1[:] # the same idea with a slice
print(list4)
دام کپی: نمونه 11_copy_list.py
شرح مثال
- خط
list2 = list1لیست تازهای نمیسازد. فقط یک نام دوم برای همان لیست میگذارد. مثل اینکه یک نفر دو اسم داشته باشد؛ همان یک نفر است. - پس هر تغییری از راه یکی از نامها، از راه دیگری هم دیده میشود.
- برای کپی واقعی سه راه هست:
list1.copy()،list(list1)وlist1[:]. هر سه یکیاند. - چرا با عدد و رشته چنین مشکلی نداریم؟ چون آنها تغییرناپذیرند و اصلاً نمیشود عوضشان کرد. این دام فقط برای انواع تغییرپذیر مثل لیست پیش میآید.
وقتی لیستی را به یک تابع بدهید، تابع همان لیست را میگیرد، نه کپیاش را. اگر تابع تغییرش دهد، لیست اصلی شما هم عوض میشود. در فصل دوازدهم دقیقاً روی همین موضوع مکث میکنیم.
پوشه S09-lists شامل نمونههای
01_create_list.py تا 11_copy_list.py.
خلاصه فصل
| ابزار | وظیفه آن |
|---|---|
[a, b, c] | ساختن لیست. [] یعنی لیست خالی |
lst[i] و lst[a:b] | اندیس و برش، دقیقاً مثل رشته |
lst[i] = x | تغییر یک عضو. رشته این را ندارد |
append insert extend | اضافه کردن |
pop remove del clear | حذف کردن |
in index count len | جستوجو و شمارش |
for x in lst | پیمایش مقدارها |
for i in range(len(lst)) | پیمایش اندیسها، برای تغییر دادن |
| پشته و صف | append با pop() یا با pop(0) |
lst2 = lst1 | کپی نیست. برای کپی: copy() یا [:] |
تمرینهای فصل نه
- لیستی از پنج شهر بسازید و هر کدام را در یک خط چاپ کنید.
- پنج عدد در یک لیست بگیرید و لیست را برعکس چاپ کنید.
- لیستی از نامها بگیرید و فقط آنهایی که با
Aشروع میشوند را چاپ کنید. - عدد بگیرید تا
exit، و بگویید چند تایشان زوج بودند. - عضوهای تکراری یک لیست را حذف کنید، بدون استفاده از
setکه هنوز نخواندهایم. - لیستی از اعداد بگیرید و لیست دومی بسازید که فقط اعداد مثبت را دارد.
- یک جمله بگیرید، با
split()به کلمات بشکنیدش و بلندترین کلمه را چاپ کنید. - یک برنامه «فهرست خرید» با منو بنویسید: افزودن کالا، حذف کالا، نمایش فهرست و خروج.