PythonPython · Chapterبەش 9 · Lectureوانە 9.4
Lists, References, Copies and Functionsلیستەکان، ئاماژەکان، کۆپی و کردارەکان
Why list2 = list1 does not copy a list, how names refer to one object, is, == and id(), four ways to make a real copy, shallow and deep copies of nested lists, and what happens to lists passed to and returned from functions — with the shared-default trap and Lab 3 Tasks 3 and 4.
بۆچی list2 = list1 کۆپی ناکات، چۆن ناوەکان ئاماژە بە یەک دەکەن، is، == و id()، چوار ڕێگە بۆ کۆپییەکی ڕاستەقینە، و ناو و چی بەسەر ئەو دێت کە دەنێردرێن بۆ و لێیانەوە دەگەڕێنەوە — لەگەڵ داوی هاوبەش و ئەرکەکانی 3 و 4ـی تاقیگەی 3.
What you will learnچی فێر دەبیت
- Explain, with the name-tag picture, why
list2 = list1gives two names for one list. - Tell
==fromis, and useid()to check whether two names are one object. - Make real copies with
copy(),list(),[:]and[] + list, and choosecopy.deepcopy()for nested lists. - Predict what a function can and cannot change in the caller's lists and numbers.
- Return new lists from functions and avoid the shared mutable default.
- بە وێنەی کارتی ناو ڕوون بکەیتەوە بۆچی
list2 = list1دوو ناو بۆ یەک دەدات. ==لەisجیا بکەیتەوە و بەid()بپشکنیت ئایا دوو ناو یەک .- بە
copy()،list()،[:]و[] + listکۆپیی ڕاستەقینە دروست بکەیت و بۆ ناوcopy.deepcopy()هەڵبژێریت. - پێشبینی بکەیت چی دەتوانێت و چی ناتوانێت لە و ژمارەکانی بگۆڕێت.
- نوێ لە بگەڕێنیتەوە و خۆت لە گۆڕانهەڵگری هاوبەش بپارێزیت.
Two names, one listدوو ناو، یەک لیست
In Python a variable does not keep a list inside itself. The list is an object that lives in the computer's memory, and the variable is only a name that refers to it — the name-tag picture from Variables and data types. This lesson is about what that means in practice: why a change made through one name can appear under another name, how to make a real copy, and what happens when a list goes into a function or comes out of one.
لە لەناو خۆیدا هەڵناگرێت. کە لە کۆمپیوتەردا دەژی و تەنها ناوێکە کە ئاماژەی پێ دەکات — هەمان وێنەی کارتی ناو کە لە گۆڕاوەکان و جۆرەکانی دراوە بینیت. ئەم وانەیە باسی ئەوە دەکات کە ئەمە لە ڕاستیدا چی دەگەیەنێت: بۆچی گۆڕانێک کە بە ناوێک دەکرێت لەژێر ناوێکی تریشدا دەردەکەوێت، چۆن کۆپییەکی ڕاستەقینە دروست دەکەیت و چی ڕوو دەدات کاتێک دەچێتە ناو یان لێی دێتە دەرەوە.
Start with the course's own example. mylist = thislist looks like "make mylist a copy of thislist". Then one item is added through thislist only. Read the output: mylist has the new item too.
بە نموونەکەی خودی کۆرسەکە دەست پێ بکە. mylist = thislist وەک ئەوە دەردەکەوێت کە «mylist بکە بە کۆپییەکی thislist». پاشان تەنها بە thislist زیاد دەکرێت. سەیری بکە: mylistـیش تێدایە.
thislist = ["apple", "banana", "cherry"]
mylist = thislist
thislist.append("kiwi")
print(mylist)
print(thislist)['apple', 'banana', 'cherry', 'kiwi'] ['apple', 'banana', 'cherry', 'kiwi']
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 2
No new list is made here.
mylistbecomes a second name for the list thatthislistalready names.لێرەدا هیچ نوێ دروست ناکرێت.
mylistدەبێتە ناوی دووەمی ئەو کەthislistپێشتر ناوی بوو.- Lineدێڕی 3
appendchanges the one list. Both names see the change.appendهەمان یەک دەگۆڕێت. هەردوو ناوەکە گۆڕانەکە دەبینن.
Two names, one listدوو ناو، یەک لیست
A box with two name tagsسندووقێک بە دوو کارتی ناوەوە
Aram and his brother Karwan keep their books in one box. The box has two name tags tied to it: "Aram" and "Karwan". If Aram puts a new book in, Karwan opens "his" box and finds the book, because there is only one box. A Python list is the box, and every variable that refers to it is a tag.
ئارام و براکەی کاروان کتێبەکانیان لە یەک سندووقدا دادەنێن. دوو کارتی ناو بە سندووقەکەوە بەستراون: «ئارام» و «کاروان». ئەگەر ئارام کتێبێکی نوێ تێی بخات، کاروان سندووقەکەی «خۆی» دەکاتەوە و کتێبەکە دەبینێت، چونکە تەنها یەک سندووق هەیە. Python سندووقەکەیە و هەر کە ئاماژەی پێ بکات کارتێکە.
Where the analogy stops workingسنووری ئەم نموونەیە
A real tag is tied on for good, but a Python name can be moved to another box at any moment (mylist = [1, 2]), and that does not touch the old box. A box that no tag points to any more is cleared away by Python automatically.
کارتی ڕاستەقینە بۆ هەمیشە دەبەسترێت، بەڵام ناوێکی Python هەر کاتێک بێت دەتوانرێت بۆ سندووقێکی تر بگوازرێتەوە (mylist = [1, 2]) و ئەمە دەست لە سندووقە کۆنەکە نادات. ئەو سندووقەی هیچ کارتێک ئاماژەی پێ نەکات، Python خۆکارانە لای دەبات.
= makes a second name, not a copy= ناوی دووەم دروست دەکات، نەک کۆپی
The course slides say that to copy a list you write list2 = list1. Look at what really happens. Before the line, list2 names its own list [7, 8]. After the line, list2 names the same list as list1, and the old list [7, 8] has no name left.
سلایدەکانی کۆرس دەڵێن بۆ کۆپیکردنی دەنووسیت list2 = list1. سەیر بکە بە ڕاستی چی ڕوو دەدات. پێش ئەو دێڕە، list2 ناوی تایبەت بە خۆیەتی: [7, 8]. دوای دێڕەکە، list2 ناوی هەمان ئەو کە list1 ناویەتی و [7, 8] هیچ ناوێکی بۆ نامێنێتەوە.
A second name that points to the same value or object. In PHP $b = &$a; makes one; in Python every name is a reference, so after list2 = list1 both names show the same list and a change through one is seen through the other.
ناوێکی دووەمە کە ئاماژە بە هەمان نرخ یان ئۆبجێکت دەکات. لە PHPـدا $b = &$a; دروستی دەکات؛ لە Pythonـدا هەموو ناوێک ئاماژەیە، بۆیە دوای list2 = list1 هەردوو ناو هەمان لیست پیشان دەدەن و گۆڕانکاری لە ڕێگەی یەکێکیانەوە لە ئەویتریشدا دەبینرێت.
In Python every variable is a reference: list2 = list1 copies the reference, not the list.
لە هەموو : list2 = list1 کۆپی دەکات، نەک .
list2 = list1 moves the name list2; the list is not copied.list2 = list1 ناوی list2 دەگوازێتەوە؛ کۆپی ناکرێت.CêITlist1 = [1, 2, 3]
list2 = [7, 8]
list2 = list1
list1.append(4)
print(list1, list2, list2 is list1)[1, 2, 3, 4] [1, 2, 3, 4] True
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 3
From here on,
list1andlist2are two names for one list.لێرەوە بەدواوە
list1وlist2دوو ناون بۆ یەک .- Lineدێڕی 5
list2 is list1asks "is this the very same object?" — the answer isTrue.list2 is list1دەپرسێت «ئایا ئەمە ڕێک هەمان ؟» — وەڵامەکەTrueـە.
= makes a second name, not a copy= ناوی دووەم دروست دەکات، نەک کۆپی
Moving a name is not changing the listگواستنەوەی ناو گۆڕینی لیست نییە
Two different things can happen to a name. Changing the object — list2[0] = 111, append, remove, sort — changes the one list, and every name that refers to it sees the change. Re-binding the name — list2 = [7, 8] — ties that one name to another object; the other names stay where they were.
دوو شتی جیاواز دەکرێت بە ناوێک بکرێت. گۆڕینی — list2[0] = 111، append، remove، sort — هەمان یەک دەگۆڕێت و هەموو ئەو ناوانەی ئاماژەی پێ دەکەن گۆڕانەکە دەبینن. بەستنەوەی ناوەکە بە شتێکی تر — list2 = [7, 8] — تەنها ئەو ناوە بە ترەوە دەبەستێت؛ ناوەکانی تر لە شوێنی خۆیان دەمێننەوە.
list1 = [1, 2, 3]
list2 = list1
list2 = [7, 8] # list2 now names a new list
print(list1, list2)
a = 5
b = a
a = a + 1 # a new number; b still names 5
print(a, b)[1, 2, 3] [7, 8] 6 5
Numbers, strings and tuples are immutable: they can never be changed, only replaced by a new value. So sharing them between names is always safe — a = a + 1 makes a new number and moves a to it. Lists are mutable: they can be changed in place. Sharing is only a surprise for mutable objects.
ژمارەکان، و : هەرگیز ناگۆڕدرێن، تەنها نوێ جێگەیان دەگرێتەوە. بۆیە هاوبەشکردنیان لە نێوان چەند ناوێکدا هەمیشە بێ مەترسییە — a = a + 1 ژمارەیەکی نوێ دروست دەکات و a دەگوازێتەوە بۆ لای. : دەکرێت لە شوێنی خۆیاندا بگۆڕدرێن. هاوبەشکردن تەنها بۆ سەرسوڕهێنەرە.
is, == and id()is، == و id()
Python gives you two different questions. == asks "do these two lists hold the same items in the same order?" is asks "are these two names the very same object?" The built-in function id() shows an object's identity number — every value has one, as Every value is an object with an id showed. Two names are the same object exactly when their id() numbers are equal.
دوو پرسیاری جیاوازت پێ دەدات. == دەپرسێت «ئایا ئەم دوو هەمان بە هەمان ڕیزبەندییان تێدایە؟» is دەپرسێت «ئایا ئەم دوو ناوە ڕێک هەمان ؟» id() ژمارەی ناسنامەی پیشان دەدات — هەموو ناسنامەی هەیە، وەک لە هەموو نرخێک ئۆبجێکتێکە و ناسنامەی هەیە بینیت. دوو ناو تەنها کاتێک هەمان کە ژمارەی id()ـیان یەکسان بێت.
list1 = [1, 2, 3]
list2 = list1
list3 = [1, 2, 3]
print(list1 == list2, list1 is list2)
print(list1 == list3, list1 is list3)
print(id(list1) == id(list2), id(list1) == id(list3))
print(id(list1))True True True False True False 4327755968
Your last line will show a different number.
دوایین دێڕی تۆ ژمارەیەکی جیاواز پیشان دەدات.
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 3
list3is a separate list that happens to hold the same numbers.list3جیایە کە بە ڕێکەوت هەمان ژمارەکانی تێدایە.- Lineدێڕی 8
The number itself means nothing to you. In CPython it is the object's memory address, so it changes from run to run.
خودی ژمارەکە بۆ تۆ هیچ مانایەکی نییە. لە CPythonـدا ئەم ژمارەیە ناونیشانی لە ، بۆیە لە هەر جێبەجێکردنێکدا دەگۆڕێت.
== asks whether two values are equal; is asks whether two names are the very same object, checked with id(), shown with lists.
== دەپرسێت ئایا دوو یەکسانن؛ is دەپرسێت ئایا دوو ناو ڕێک هەمان ، کە بە id() دەپشکنرێت و بە پیشان دەدرێت.
Whole video (8:51): analogy (0:39), code (3:33), two names for one list (5:37), id() (6:37).
هەموو ڤیدیۆکە (8:51): نموونەیەکی ڕۆژانە (0:39)، کۆد (3:33)، دوو ناو بۆ یەک (5:37) و id() (6:37).
Four ways to make a real copyچوار ڕێگە بۆ کۆپییەکی ڕاستەقینە
To get a second, independent list you must ask Python to build a new list with the same items. Each of these four lines does that. The course slides show the first two; the slice [:] and [] + list are the same idea in other forms.
بۆ ئەوەی دووەمی سەربەخۆت هەبێت، دەبێت داوا لە بکەیت نوێ دروست بکات کە هەمان تێدابێت. هەریەک لەم چوار دێڕە ئەوە دەکات. سلایدەکانی کۆرس دووانی یەکەمیان پیشان دەدەن؛ بە [:] و [] + list هەمان بیرۆکەن بە شێوەیەکی تر.
thislist = ["apple", "banana", "cherry"]
copy1 = thislist.copy() # 1. the copy() method
copy2 = list(thislist) # 2. the list() constructor
copy3 = thislist[:] # 3. a slice of the whole list
copy4 = [] + thislist # 4. join it to an empty list
thislist.append("kiwi")
print(thislist)
print(copy1)
print(copy2)
print(copy3)
print(copy4)['apple', 'banana', 'cherry', 'kiwi'] ['apple', 'banana', 'cherry'] ['apple', 'banana', 'cherry'] ['apple', 'banana', 'cherry'] ['apple', 'banana', 'cherry']
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 2-5
Each line creates a new list object and fills it with the items of
thislist.هەر دێڕێک نوێی دروست دەکات و بە
thislistپڕی دەکاتەوە.- Lineدێڕی 7
Only
thislistgets"kiwi". The four copies are separate lists, so they keep three items.تەنها
thislist"kiwi"وەردەگرێت. چوار کۆپییەکە جیان، بۆیە سێ دەمێنێت.
![Animation in six steps. list1 = [1, 2, 3]: the tag list1 points to a list box. list2 = list1: a second tag, list2, points to the same box. list2[0] = 111: the one box changes to [111, 2, 3] and both tags show it. list3 = list1.copy(): a new box [111, 2, 3] splits off with the tag list3. list3.append(4): only the new box grows to [111, 2, 3, 4]. At the end: list2 is list1 is True, list3 is list1 is False.](/_astro/py-list-references-and-copies-two-names.en.CCx5yJvW.gif)
![Animation in six steps. list1 = [1, 2, 3]: the tag list1 points to a list box. list2 = list1: a second tag, list2, points to the same box. list2[0] = 111: the one box changes to [111, 2, 3] and both tags show it. list3 = list1.copy(): a new box [111, 2, 3] splits off with the tag list3. list3.append(4): only the new box grows to [111, 2, 3, 4]. At the end: list2 is list1 is True, list3 is list1 is False.](/_astro/py-list-references-and-copies-two-names.ckb.BiquvH_w.gif)
copy() makes a second box.دوو کارت لەسەر یەک سندووق، پاشان copy() سندووقی دووەم دروست دەکات.CêITExercises: copy or not?ڕاهێنان: کۆپی یان نا؟
The two exercises from the slides differ in one line only. Predict the output before you open the answer. list(range(1, 10, 2)) is [1, 3, 5, 7, 9].
دوو ڕاهێنانەکەی سلایدەکان تەنها لە یەک دێڕدا جیاوازن. پێش کردنەوەی وەڵامەکە پێشبینی بکە. list(range(1, 10, 2)) بریتییە لە [1, 3, 5, 7, 9].
What is the output of this code?
ئەم کۆدە چییە؟
list1 = list(range(1, 10, 2))
list2 = list1
list1[0] = 111
print(list1)
print(list2)Show answerوەڵامەکە پیشان بدە
list1 = list(range(1, 10, 2))
list2 = list1
list1[0] = 111
print(list1)
print(list2)[111, 3, 5, 7, 9] [111, 3, 5, 7, 9]
Both lines show 111. list2 = list1 made a second name, so there is only one list to change.
هەردوو دێڕەکە 111 پیشان دەدەن. list2 = list1 ناوێکی دووەمی دروست کرد، بۆیە تەنها یەک هەیە کە بگۆڕدرێت.
What is the output of this code?
ئەم کۆدە چییە؟
list1 = list(range(1, 10, 2))
list2 = [] + list1
list1[0] = 111
print(list1)
print(list2)Show answerوەڵامەکە پیشان بدە
list1 = list(range(1, 10, 2))
list2 = [] + list1
list1[0] = 111
print(list1)
print(list2)[111, 3, 5, 7, 9] [1, 3, 5, 7, 9]
[] + list1 joins an empty list with list1 and so builds a new list. Changing list1[0] does not touch it.
[] + list1 بەتاڵ لەگەڵ list1 پێکەوە دەلکێنێت و بەم شێوەیە نوێ دروست دەکات. گۆڕینی list1[0] دەستی لێ نادات.
Shallow and deep copies: the nested-list trapکۆپیی ڕووکەش و کۆپیی قووڵ: داوی لیستی ناو لیست
copy(), list(), [:] and [] + list all make a shallow copy: a new outer list whose items are the same objects as in the old list. For numbers and strings that is fine. But when the items are themselves lists — a table stored as rows — the two outer lists share the rows.
copy()، list()، [:] و [] + list هەموویان دروست دەکەن: نوێی دەرەوە کە هەمان وەک لە . بۆ ژمارە و ئەمە کێشە نییە. بەڵام کاتێک خۆیان — خشتەیەک کە وەک هەڵگیراوە — هەردوو هەمان بەیەکەوە بەکار دەهێنن.
import copy
marks = [[80, 90], [70, 60]] # two students, two subjects each
shallow = marks.copy() # new outer list, the SAME rows
deep = copy.deepcopy(marks) # new outer list AND new rows
marks[0][0] = 100 # change one mark in row 0
print("marks: ", marks)
print("shallow:", shallow)
print("deep: ", deep)
shallow.append([50, 55]) # add a whole row to the shallow copy
print(len(marks), len(shallow))marks: [[100, 90], [70, 60]] shallow: [[100, 90], [70, 60]] deep: [[80, 90], [70, 60]] 2 3
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 4
A new outer list, but its two items are the very same row lists as in
marks.دەرەوەی نوێ، بەڵام هەردوو ڕێک هەمان
marksـن.- Lineدێڕی 5
copy.deepcopy()from thecopymodule copies the rows too, at every level.copy.deepcopy()لەcopyکۆپی دەکات، لە هەموو ئاستێکدا.- Lineدێڕی 12
Adding a whole row changes only the outer list of
shallow, somarksstill has 2 rows.زیادکردنی تەواو تەنها
shallowدەگۆڕێت، بۆیەmarksهێشتا 2 هەیە.
Passing a list to a functionناردنی لیستێک بۆ کردارێک
A list can be an argument like any other value. When you call print_list([3, 1, 2, 6, 4, 2]), Python does something like lst = [3, 1, 2, 6, 4, 2] behind the scenes: the parameter lst becomes one more name for the caller's list. Nothing is copied.
دەتوانێت وەک هەر تر بێت. کاتێک print_list([3, 1, 2, 6, 4, 2]) بانگ دەکەیت، لە پشتەوە شتێکی وەک lst = [3, 1, 2, 6, 4, 2] دەکات: lst دەبێتە ناوێکی تر بۆ . هیچ شتێک کۆپی ناکرێت.
def print_list(lst):
for element in lst:
print(element)
print_list([3, 1, 2, 6, 4, 2])3 1 2 6 4 2
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 1
On the slide the function is called
printListand its body is indented by one space. Both work, but Python's style guide (PEP 8) asks forsnake_casenames and 4 spaces.لە سلایدەکەدا ناوی
printListـە و جەستەکەی بە یەک بۆشایی چووەتە ناوەوە. هەردووکیان کار دەکەن، بەڵام ڕێنمایی شێوازی (PEP 8) ناویsnake_caseو 4 بۆشایی دەخوازێت.
This function only reads the list. But because the parameter and the caller's variable are two names for one mutable list, a function can also change it — and the change is still there after the call. The next screen shows exactly that.
ئەم تەنها دەخوێنێتەوە. بەڵام لەبەر ئەوەی و دوو ناون بۆ یەک ، دەشتوانێت بیگۆڕێت — و گۆڕانەکە دوای دەمێنێتەوە. پەڕەی داهاتوو ڕێک ئەوە پیشان دەدات.
The list changes, the number does notلیستەکە دەگۆڕێت، ژمارەکە ناگۆڕێت
This classic example passes a number x and a list y to a function m. Inside, m gives its parameter number a new value and changes the first item of numbers. After the call, main prints both. Here is the program as the slide has it:
ئەم نموونە ناودارە ژمارەیەک x و y دەنێرێت بۆ m. لە ناوەوە، m نوێ دەدات بە number و یەکەم numbers دەگۆڕێت. دوای ، main هەردووکیان چاپ دەکات. ئەمە وەک لە سلایدەکەدایە:
def main():
x=1
y=[1,2,3]
m(x,y)
print("x is ", x)
print("y[0] is ",y)
def m(number,numbers):
x=1001
numbers[0]=5555
main()x is 1 y[0] is [5555, 2, 3]
def main():
x = 1
y = [1, 2, 3]
m(x, y)
print("x is", x)
print("y[0] is", y[0])
def m(number, numbers):
number = 1001 # moves the local name only
numbers[0] = 5555 # changes the caller's list
main()x is 1 y[0] is 5555
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 9
numberwas a second name for1. Now it names1001— butmain'sxstill names1.numberناوی دووەمی1بوو. ئێستا ناوی1001ـە — بەڵامxـیmainهێشتا ناوی1ـە.- Lineدێڕی 10
numbersandmain'syare one list. Changing an item changes it for both.numbersوyـیmainیەک . گۆڕینی بۆ هەردووکیان دەیگۆڕێت.
m: number is moved, numbers is changed.لە ناو mـدا: number دەگوازرێتەوە، numbers دەگۆڕدرێت.CêITThe list changes, the number does notلیستەکە دەگۆڕێت، ژمارەکە ناگۆڕێت
Which types can change in place?کام جۆرانە لە شوێنی خۆیاندا دەگۆڕدرێن؟
The example worked this way because a list is mutable and a number is immutable. Every built-in type of Python is one or the other. You know lists, numbers and strings already; tuples, sets and dictionaries come later in Tuples, sets and dictionaries.
نموونەکە بەم شێوەیە کاری کرد چونکە و ژمارە . هەر جۆرێکی ئامادەی یان یان . ، ژمارەکان و دەناسیت؛ ، و دواتر لە تاپڵەکان، کۆمەڵەکان و فەرهەنگەکان دێن.
| Typeجۆر | Exampleنموونە | Can it change in place?لە شوێنی خۆیدا دەگۆڕدرێت؟ |
|---|---|---|
list | [80, 90] | Yes: mutableبەڵێ: |
dict | {"Aram": 87} | Yes: mutableبەڵێ: |
set | {1, 2} | Yes: mutableبەڵێ: |
int | 5 | No: immutableنەخێر: |
float | 2.5 | No: immutableنەخێر: |
bool | True | No: immutableنەخێر: |
complex | 3+4j | No: immutableنەخێر: |
str | "Hana" | No: immutableنەخێر: |
tuple | (1, 2) | No: immutableنەخێر: |
+= on a string and on a list+= لەسەر زنجیرەنووسەیەک و لەسەر لیستێکwhich_types.pyPYTHONType in a terminalلە تێرمیناڵدا بینووسەname = "Hana"
other = name
name += "!" # a new string; other keeps the old one
print(name, other, name is other)
marks = [80]
same = marks
marks += [90] # the same list grows in place
print(marks, same, marks is same)Hana! Hana False [80, 90] [80, 90] True
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 3
A string cannot change, so
+=builds a new string and moves onlyname.ناگۆڕدرێت، بۆیە
+=نوێ دروست دەکات و تەنهاnameدەگوازێتەوە.- Lineدێڕی 8
A list can change, so
+=grows the one list andsamesees it.دەگۆڕدرێت، بۆیە
+=هەمان یەک گەورە دەکات وsameدەیبینێت.
Which Python types can change in place (lists) and which cannot (numbers, strings, tuples), tested in the interpreter.
لە کام جۆر لە شوێنی خۆیدا دەگۆڕێت () و کامیان ناگۆڕێت (ژمارە، ، )؛ هەمووی لە تاقی دەکرێتەوە.
Watch 0:35–5:31, immutable vs mutable; the 'quirks' part after it (a list inside a tuple) is extra.
لە 0:35 تا 5:31 سەیر بکە: بەرامبەر ؛ بەشی quirks کە دوای ئەوە دێت ( لەناو ) زیادەیە.
Returning a list from a functionگەڕاندنەوەی لیستێک لە کردارێک
A function can also return a list. What comes back is a reference to the list the function built. This reverse function makes an empty list result, puts every element of lst at the front of it with insert(0, …), and returns it. The list you passed in is not touched.
دەتوانێت بگەڕێنێتەوە. ئەوەی دەگەڕێتەوە بۆ ئەو کە دروستی کرد. ئەم reverseـە بەتاڵی result دروست دەکات، هەموو lst بە insert(0, …) دەخاتە سەرەتای result و دەیگەڕێنێتەوە. ئەو ناردت دەستی لێ نادرێت.
def reverse(lst):
result = []
for element in lst:
result.insert(0, element)
return result
print("reverse is : ", reverse([12, 6, 7]))
print("default is :", [12, 6, 7])reverse is : [7, 6, 12] default is : [12, 6, 7]
The slide's picture of this output has the typo "defualt"; the code says "default".
وێنەی ئەم لە سلایدەکەدا هەڵەی نووسینی «defualt»ـی تێدایە؛ کۆدەکە «default» دەڵێت.
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 4
Each new element goes to position 0, pushing the earlier ones right:
[12], then[6, 12], then[7, 6, 12].هەر نوێ دەچێتە شوێنی 0 و ئەوانەی پێشوو بەرەو ڕاست پاڵ دەنێت:
[12]، پاشان[6, 12]، پاشان[7, 6, 12].- Lineدێڕی 5
The function returns a reference to
result, the new list.بۆ
resultدەگەڕێنێتەوە، واتە .
Writing reverse yourself is good practice with loops. In real programs Python already has three tools — two give a new list, one changes the list in place:
نووسینی reverse بە دەستی خۆت ڕاهێنانێکی باشە لەسەر . لە ڕاستەقینەدا پێشتر سێ ئامرازی هەیە — دووانیان نوێ دەدەن و یەکێکیان لە شوێنی خۆیدا دەگۆڕێت:
numbers = [12, 6, 7]
print(numbers[::-1]) # a new list, reversed
print(list(reversed(numbers))) # a new list, reversed
print(numbers) # unchanged so far
numbers.reverse() # reverses numbers itself, returns None
print(numbers)[7, 6, 12] [7, 6, 12] [12, 6, 7] [7, 6, 12]
The shared default listلیستە بنەڕەتییە هاوبەشەکە
What is the output of the following code? Think about where the list [1, 1, 2, 3] is made.
ئەم کۆدەی خوارەوە چییە؟ بیر لەوە بکەرەوە کە [1, 1, 2, 3] لە کوێ دروست دەکرێت.
def main():
list1 = m(1)
print(list1)
list2 = m(1)
print(list2)
def m(x, lst = [1, 1, 2, 3]):
if x in lst:
lst.remove(x)
return lst
main()Show answerوەڵامەکە پیشان بدە
def main():
list1 = m(1)
print(list1)
list2 = m(1)
print(list2)
def m(x, lst = [1, 1, 2, 3]):
if x in lst:
lst.remove(x)
return lst
main()[1, 2, 3] [2, 3]
The first call removes one 1 and prints [1, 2, 3]. The second call does not start again from [1, 1, 2, 3]: it gets the same list, already changed, removes the other 1 and prints [2, 3].
یەکەم یەک 1 لا دەبات و [1, 2, 3] چاپ دەکات. دووەم لە [1, 1, 2, 3]ـەوە دەست پێ ناکاتەوە: هەمان وەردەگرێت کە پێشتر گۆڕاوە، 1ـەکەی تر لا دەبات و [2, 3] چاپ دەکات.
Why? A default value is worked out once, when Python runs the def line — not every time the function is called. So every call that uses the default shares one list. For numbers and strings that never matters, because they cannot change. For a list it does.
بۆچی؟ تەنها یەکجار هەژمار دەکرێت، کاتێک دێڕی def جێبەجێ دەکات — نەک هەر جارێک بانگ بکرێت. بۆیە هەموو ئەو بانگکردنانەی بەکار دەهێنن یەک هاوبەش دەکەن. بۆ ژمارە و ئەمە هەرگیز گرنگ نییە، چونکە ناگۆڕدرێن. بۆ گرنگە.
Noneچارەسەر: None بکە بە نرخی بنەڕەتیdefault_none.pyPYTHONType in a terminalلە تێرمیناڵدا بینووسەdef m(x, lst=None):
if lst is None:
lst = [1, 1, 2, 3] # a fresh list on every call
if x in lst:
lst.remove(x)
return lst
print(m(1))
print(m(1))
print(m(7))[1, 2, 3] [1, 2, 3] [1, 1, 2, 3]
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 1
Noneis immutable, so it is a safe default.None، بۆیە وەک بێ مەترسییە.- Lineدێڕی 2-3
A new list is built inside the function, on every call that did not pass one.
نوێ لە ناو دروست دەکرێت، لە هەموو ئەو بانگکردنانەدا کە نەناردووە.
- Lineدێڕی 6
returnis now outside theif, so the function always returns the list. In the slide's versionm(7)would returnNone.ئێستا
returnلە دەرەوەیifـە، بۆیە هەمیشە دەگەڕێنێتەوە. لە وەشانی سلایدەکەداm(7)Noneدەگەڕێنێتەوە.
Why a mutable default value such as a list is created only once and shared by every call, and how None fixes it.
بۆچی کە دەکرێت بگۆڕدرێت (وەک ) تەنها یەک جار دروست دەکرێت و هەموو تێیدا هاوبەشن، هەروەها چۆن None چاکی دەکاتەوە.
Watch 0:00–10:56: the shared default list and the None fix. The datetime example after it shows again that a default is made only once.
لە 0:00 تا 10:56 سەیر بکە: وەک کە لە نێوان بانگکردنەکاندا هاوبەشە و چارەسەرکردنی بە None. نموونەی datetime کە دوای ئەوە دێت دووبارە پیشان دەداتەوە کە تەنها یەک جار دروست دەکرێت.
Lab: an average function with a list parameterتاقیگە: کردارێکی تێکڕا بە پارامیتەرێکی لیست
Write a program that prints the average of the numbers of Task 1-1 (2.7, 32, 768, 89.1, 21, 90.3, 135, 77, 43, 38.2). Requirements: (1) a function that returns the average; (2) when you call it, pass the number of elements and the list, for example average(10, [2.7, 32, …]). Expected output: Average is 129.63.
بنووسە کە تێکڕای ژمارەکانی ئەرکی 1-1 چاپ بکات (2.7، 32، 768، 89.1، 21، 90.3، 135، 77، 43، 38.2). مەرجەکان: (1) کە تێکڕاکە بگەڕێنێتەوە؛ (2) کاتێک بانگی دەکەیت، ژمارەی و بنێرە، بۆ نموونە average(10, [2.7, 32, …]). چاوەڕوانکراو: Average is 129.63.
Hintئاماژە
sum(numbers) adds up the whole list (see the next lesson).
sum(numbers) هەموو کۆ دەکاتەوە (وانەی داهاتوو ببینە).
Show answerوەڵامەکە پیشان بدە
def average(count, numbers):
return sum(numbers) / count
values = [2.7, 32, 768, 89.1, 21, 90.3, 135, 77, 43, 38.2]
print("Average is ", average(10, values))Average is 129.63
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 1
Two parameters: the count and the list. The list parameter is a reference to
values; the function only reads it.دوو : ژمارەکە و . بۆ
values؛ تەنها دەیخوێنێتەوە.
A better design does not ask for the count at all, because the list knows its own length: len(numbers). Then the function can never be called with a wrong count.
داڕشتنێکی باشتر هەرگیز داوای ژمارەکە ناکات، چونکە درێژیی خۆی دەزانێت: len(numbers). ئیتر هەرگیز ناکرێت بە ژمارەیەکی هەڵە بانگ بکرێت.
def average(numbers):
return sum(numbers) / len(numbers)
values = [2.7, 32, 768, 89.1, 21, 90.3, 135, 77, 43, 38.2]
print("Average is", round(average(values), 2))Average is 129.63
Lab: reverse a list inside a functionتاقیگە: پێچەوانەکردنەوەی لیستێک لە ناو کردارێکدا
Write a Python program that "swaps" the list [Python, Java, C#, PHP, Visual basic], that is, reverses its order: (1) write a function that swaps the elements of the list; (2) pass the list to the function when you call it, for example swapping(["Python", "Java", …]).
Python بنووسە کە [Python, Java, C#, PHP, Visual basic] «ئاڵوگۆڕ» بکات، واتە ڕیزبەندییەکەی پێچەوانە بکاتەوە: (1) بنووسە کە ئاڵوگۆڕ بکات؛ (2) کاتێک بانگی دەکەیت بنێرە بۆ ، بۆ نموونە swapping(["Python", "Java", …]).
Before Swap ['Python', 'Java', 'C#', 'PHP', 'Visual basic'] After Swap ['Visual basic', 'PHP', 'C#', 'Java', 'Python']
Hintئاماژە
Swap the first and the last element, then the second and the second-last, and so on until you reach the middle.
یەکەم و دوایین ئاڵوگۆڕ بکە، پاشان دووەم و پێش دوایین و بەم شێوەیە تا دەگەیتە ناوەڕاست.
Show answerوەڵامەکە پیشان بدە
def swapping(lst):
left = 0
right = len(lst) - 1
while left < right:
lst[left], lst[right] = lst[right], lst[left]
left += 1
right -= 1
return lst
languages = ["Python", "Java", "C#", "PHP", "Visual basic"]
print("Before Swap", languages)
print("After Swap", swapping(languages))Before Swap ['Python', 'Java', 'C#', 'PHP', 'Visual basic'] After Swap ['Visual basic', 'PHP', 'C#', 'Java', 'Python']
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 2-3
Two positions:
leftstarts at the first element,rightat the last.دوو شوێن:
leftلە یەکەم دەست پێ دەکات وrightلە دوایین.- Lineدێڕی 5
Swap the two elements in one line: Python builds the pair on the right first, then assigns it.
دوو لە یەک دێڕدا ئاڵوگۆڕ دەکرێن: سەرەتا جووتەکەی لای ڕاست دروست دەکات و پاشان دایدەنێت.
- Lineدێڕی 6-7
Move both positions one step towards the middle. Stop when they meet.
هەردوو شوێنەکە یەک هەنگاو بەرەو ناوەڕاست ببە. کاتێک بە یەک گەیشتن بوەستە.
| Roundجار | left | right | List after the swap دوای ئاڵوگۆڕ |
|---|---|---|---|
| 1 | 0 | 4 | ['Visual basic', 'Java', 'C#', 'PHP', 'Python'] |
| 2 | 1 | 3 | ['Visual basic', 'PHP', 'C#', 'Java', 'Python'] |
| — | 2 | 2 | left < right is False: stop. C# stays in the middle.left < right دەبێتە False: وەستان. C# لە ناوەڕاست دەمێنێتەوە. |
"Swap" in this task means reverse the order. The function changes the caller's list in place and returns it. That has a trap: if you saved the list with before = languages and print before afterwards, you see the reversed list, because before is only another name.
«ئاڵوگۆڕ» لەم ئەرکەدا واتە پێچەوانەکردنەوەی ڕیزبەندی. لە شوێنی خۆیدا دەگۆڕێت و دەیگەڕێنێتەوە. ئەمە داوێکی هەیە: ئەگەر بە before = languages هەڵگرتبێت و دواتر before چاپ بکەیت، پێچەوانەکراوەکە دەبینیت، چونکە before تەنها ناوێکی ترە.
def swapping(lst):
lst.reverse() # in place, like the loop version
return lst
languages = ["Python", "Java", "C#", "PHP", "Visual basic"]
before = languages # NOT a copy
swapped = swapping(languages)
print("Before Swap", before)
print(swapped is languages)Before Swap ['Visual basic', 'PHP', 'C#', 'Java', 'Python'] True
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 6
Use
before = languages.copy()to keep the old order.بۆ هێشتنەوەی ڕیزبەندییە کۆنەکە
before = languages.copy()بەکار بهێنە.
Common mistakesهەڵە باوەکان
| Mistakeهەڵە | What happensچی ڕوو دەدات | Fixچارەسەر |
|---|---|---|
backup = scores | backup is the same list; changes show in bothbackup هەمان ؛ گۆڕانەکان لە هەردووکیاندا دەردەکەون | backup = scores.copy() |
t2 = table.copy() (2-D)t2 = table.copy() (دووڕەهەند) | the rows are still shared هێشتا هاوبەشن | copy.deepcopy(table) |
def f(items=[]) | one default list shared by every callیەک کە هەموو بانگکردنەکان هاوبەشی دەکەن | items=None, then if items is None: items = []items=None، پاشان if items is None: items = [] |
number = 1001 inside a functionnumber = 1001 لە ناو | the caller's variable does not change ناگۆڕێت | return the new value بە return بگەڕێنەوە |
a is b to compare itemsa is b بۆ بەراوردکردنی | can be False for equal listsبۆ دوو یەکسان دەکرێت False بێت | a == b |
| a function changes its list parameter by accident بە هەڵە دەگۆڕێت | the caller's list is changed too هەروەها دەگۆڕێت | pass a copy: f(lst.copy()), or build a new list insideکۆپییەک بنێرە: f(lst.copy())، یان لە ناوەوە نوێ دروست بکە |
Exercisesڕاهێنانەکان
Predict the output, then run it.
پێشبینی بکە، پاشان جێبەجێی بکە.
a = [1, 2]
b = a
c = a[:]
b.append(3)
c.append(4)
print(a, b, c)Show answerوەڵامەکە پیشان بدە
a = [1, 2]
b = a
c = a[:]
b.append(3)
c.append(4)
print(a, b, c)[1, 2, 3] [1, 2, 3] [1, 2, 4]
b is the same list as a, so both get 3. c is a copy, so only c gets 4.
b هەمان aـیە، بۆیە هەردووکیان 3 وەردەگرن. c کۆپییەکە، بۆیە تەنها c 4 وەردەگرێت.
Write with_bonus(marks, bonus), which returns a new list with bonus added to every mark and leaves marks unchanged, and add_bonus(marks, bonus), which changes the caller's list instead. Test both on [60, 75, 82] with a bonus of 5.
with_bonus(marks, bonus) بنووسە کە نوێ دەگەڕێنێتەوە و bonus بۆ هەموو نمرەیەک زیاد دەکات و marks وەک خۆی دەهێڵێتەوە، هەروەها add_bonus(marks, bonus) کە لەبری ئەوە دەگۆڕێت. هەردووکیان لەسەر [60, 75, 82] بە نمرەی زیادەی 5 تاقی بکەرەوە.
Hintئاماژە
For the in-place version, loop over the indexes with range(len(marks)), not over the values.
بۆ ئەو وەشانەی لە شوێنی خۆیدا دەیگۆڕێت، بە range(len(marks)) بەسەر بخولێوە، نەک بەسەر .
Show answerوەڵامەکە پیشان بدە
def with_bonus(marks, bonus):
"""Return a NEW list; marks stays as it was."""
result = []
for m in marks:
result.append(m + bonus)
return result
def add_bonus(marks, bonus):
"""Change the caller's list in place."""
for i in range(len(marks)):
marks[i] += bonus
class_marks = [60, 75, 82]
print(with_bonus(class_marks, 5), class_marks)
add_bonus(class_marks, 5)
print(class_marks)[65, 80, 87] [60, 75, 82] [65, 80, 87]
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 11
marks[i] += bonuschanges an item of the shared list, so the caller sees it.marks[i] += bonusدەگۆڕێت، بۆیە دەیبینێت.
The programmer wanted backup to keep the old table. What does this print, and how do you fix it?
بەرنامەسازەکە دەیویست backup خشتە کۆنەکە بپارێزێت. ئەمە چی چاپ دەکات و چۆن چاکی دەکەیتەوە؟
table = [[1, 2], [3, 4]]
backup = table.copy()
table[1][1] = 0
print(backup)Show answerوەڵامەکە پیشان بدە
table = [[1, 2], [3, 4]]
backup = table.copy()
table[1][1] = 0
print(backup)[[1, 2], [3, 0]]
copy() is shallow: the rows are shared, so the 0 shows up in backup. A deep copy fixes it:
copy() ڕووکەشە: هاوبەشن، بۆیە 0ـەکە لە backupـدا دەردەکەوێت. چاکی دەکاتەوە:
import copy
table = [[1, 2], [3, 4]]
backup = copy.deepcopy(table)
table[1][1] = 0
print(backup)[[1, 2], [3, 4]]
Predict both outputs. In part (a), b is a second name for a: compare a *= 2 with a = a * 2. In part (b), c and d name one list: compare append() with extend().
هەردوو پێشبینی بکە. لە بەشی (أ)دا، b ناوی دووەمی aـیە: a *= 2 لەگەڵ a = a * 2 بەراورد بکە. لە بەشی (ب)دا، c و d ناوی یەک : append() لەگەڵ extend() بەراورد بکە.
a = [1, 2]
b = a
a *= 2
print(a, b, a is b)
a = a * 2
print(a, b, a is b)c = [1, 2]
d = c
c.append([3, 4])
d.extend([5, 6])
print(c)
print(len(c), c is d)Hintئاماژە
Ask each time: does this line change the list itself, or build a new one?
هەر جارێک بپرسە: ئایا ئەم دێڕە خودی دەگۆڕێت، یان نوێ دروست دەکات؟
Show answerوەڵامەکە پیشان بدە
a = [1, 2]
b = a
a *= 2
print(a, b, a is b)
a = a * 2
print(a, b, a is b)[1, 2, 1, 2] [1, 2, 1, 2] True [1, 2, 1, 2, 1, 2, 1, 2] [1, 2, 1, 2] False
a *= 2 changes the list in place, like += on a list (Moving a name is not changing the list), so b sees [1, 2, 1, 2] too and a is b is True. a = a * 2 builds a new list (Repeating a list with *) and moves only the name a: b keeps the old list, and now a is b is False.
a *= 2 لە شوێنی خۆیدا دەگۆڕێت، وەک += لەسەر (گواستنەوەی ناو گۆڕینی لیست نییە)، بۆیە bـیش [1, 2, 1, 2] دەبینێت و a is b دەبێتە True. a = a * 2 نوێ دروست دەکات (دووبارەکردنەوەی لیستێک بە *) و تەنها ناوی a دەگوازێتەوە: b دەهێڵێتەوە و ئێستا a is b دەبێتە False.
c = [1, 2]
d = c
c.append([3, 4])
d.extend([5, 6])
print(c)
print(len(c), c is d)[1, 2, [3, 4], 5, 6] 5 True
append([3, 4]) adds one element: the whole list [3, 4]. extend([5, 6]) adds its two items one by one (append() or extend()?). Both methods change the list in place, and c and d are one list, so both changes land in it: 5 elements.
append([3, 4]) یەک زیاد دەکات: هەموو [3, 4]. extend([5, 6]) دوو یەک بە یەک زیاد دەکات (append() یان extend()؟). هەردوو لە شوێنی خۆیدا دەگۆڕن و c و d یەک ، بۆیە هەردوو گۆڕانەکە دەچنە ناوی: 5 .
Summaryپوختە
- A variable is a name that refers to an object.
list2 = list1adds a second name to the same list; it copies nothing. - Changing a list (
append,lst[0] = …) is seen through every name. Re-binding a name (lst = …) moves only that name. ==compares items,iscompares identity;id()shows the identity number.- Real copies:
copy(),list(),[:],[] + list. They are shallow;copy.deepcopy()also copies inner lists. - A list passed to a function is shared with the caller: the function can change its items. Assigning to a number parameter does not change the caller's variable.
- A function can return a new list. Never use a list as a default value; use
None.
- ناوێکە کە ئاماژە بە دەکات.
list2 = list1ناوێکی دووەم بۆ هەمان زیاد دەکات؛ هیچ کۆپی ناکات. - گۆڕینی (
append،lst[0] = …) لە ڕێگەی هەموو ناوەکانەوە دەبینرێت. بەستنەوەی ناوێک بە شتێکی تر (lst = …) تەنها ئەو ناوە دەگوازێتەوە. ==بەراورد دەکات،isناسنامە بەراورد دەکات؛id()ژمارەی ناسنامە پیشان دەدات.- کۆپیی ڕاستەقینە:
copy()،list()،[:]،[] + list. ئەمانە ڕووکەشن؛copy.deepcopy()ناوەوەش کۆپی دەکات. - کە بۆ دەنێردرێت لەگەڵ هاوبەشە: دەتوانێت بگۆڕێت. دانانی بۆ ژمارە ناگۆڕێت.
- دەتوانێت نوێ بگەڕێنێتەوە. هەرگیز وەک بەکار مەهێنە؛
Noneبەکار بهێنە.
Why does mylist = thislist not protect mylist from changes?بۆچی mylist = thislist mylist لە گۆڕان ناپارێزێت؟
Because both names refer to one list object. Any change to that object is visible through both names.
چونکە هەردوو ناوەکە ئاماژە بە یەک دەکەن. هەر گۆڕانێک لەو لە ڕێگەی هەردوو ناوەکەوە دەبینرێت.
When do you need copy.deepcopy() instead of copy()?کەی لەبری copy() پێویستت بە copy.deepcopy() دەبێت؟
When the list contains other lists (or other mutable objects) and the copy must not share them, for example a table of rows.
کاتێک تری تێدایە (یان تر) و کۆپییەکە نابێت هاوبەشیان بکات، بۆ نموونە خشتەیەک لە .
How can a function give back a changed number?کردارێک چۆن دەتوانێت ژمارەیەکی گۆڕاو بگەڕێنێتەوە؟
By returning it: x = change(x). Assigning to the parameter inside the function is not enough.
بە گەڕاندنەوەی: x = change(x). دانانی بۆ لە ناو بەس نییە.
Next: the built-in tools for lists of numbers — sum, max, min — and sorting, in sum, max, min and Sorting.
داهاتوو: ئامرازە ئامادەکان بۆ ژمارە — sum، max، min — و ، لە sum، max، min و ڕیزکردن.
Videoڤیدیۆ
Watch a videoسەیری ڤیدیۆیەک بکە
A video that viewers liked a lot and praised in their comments, chosen for this lesson.ڤیدیۆیەک کە بینەران زۆریان پێ خۆش بووە و لە کۆمێنتەکانیاندا ستایشیان کردووە، بۆ ئەم وانەیە هەڵبژێردراوە.
Why b = a gives one list two names, why copy() still shares the inner lists, and how copy.deepcopy() fixes it.
بۆچی b = a دوو ناو دەداتە یەک ، بۆچی copy() هێشتا ناوەوە هاوبەش دەکات و چۆن copy.deepcopy() چاکی دەکاتەوە.
Whole video (6:44): the reference trap (0:00), shallow-copy limits with nested lists (1:31), deep copies (4:25).
هەموو ڤیدیۆکە (6:44): تەڵەی (0:00)، سنووری لەگەڵ ناو (1:31) و (4:25).
Lesson complete!وانەکە تەواو بوو!
Well done. Review the key terms, then go on to the next lesson.دەستخۆش. سەیرێکی زاراوە سەرەکییەکان بکەرەوە، پاشان بڕۆ بۆ وانەی داهاتوو.
Key termsزاراوە سەرەکییەکان
sum, max, min and Sortingsum، max، min و ڕیزکردن
Related lecturesوانە پەیوەندیدارەکان
References and further readingسەرچاوەکان و خوێندنەوەی زیاتر
- Python FAQ: Why did changing list 'y' also change list 'x'? / How do I copy an object? / Why are default values shared between objects? / is vs ==
- Python Standard Library: copy — shallow and deep copy operations
- Python tutorial 5.1: More on lists (list.copy, list.reverse)
- Python built-in functions: id(), list()
- Ned Batchelder: Facts and myths about Python names and values
- PEP 8 — Style Guide for Python Code (names, indentation)
This lecture is a first edition. The Kurdish text and terminology are waiting for review by Kurdish IT teachers.ئەم وانەیە چاپی یەکەمە. دەقە کوردییەکە و زاراوەکانی چاوەڕێی پێداچوونەوەی مامۆستایانی کوردی بواری IT ن.