ლექცია 11 · XI კვირაLecture 11 · Week XI
სიმრავლე და
ლექსიკონიSets and
dictionaries
set · dict · შესაბამის სტრუქტურებთან სამუშაო ფუნქციები
set · dict · the methods that come with them
დღეს ასევე: პრაქტიკული დავალება #3 Also today: practical assignment #3
გამეორება · ლექციები 09–10Review · lectures 09–10
შემოწმება — 9 კითხვაCheck yourself — 9 questions
1. რა განსხვავებაა "w" და "a" რეჟიმებს შორის?
1. What is the difference between modes "w" and "a"?
"w" ფაილის შიგთავსს შლის და ახლიდან წერს; "a" არსებულს ინახავს და ბოლოში ამატებს.
"w" erases the file and writes from scratch; "a" keeps what is there and appends at the end.
2. რატომ ვწერთ encoding="utf-8"?
2. Why do we write encoding="utf-8"?
Windows-ზე ნაგულისხმევი კოდირება UTF-8 არაა, ამიტომ ქართული ტექსტი ან „კუბიკებად“ გამოჩნდება, ან
UnicodeDecodeError-ს გამოიწვევს.
On Windows the default encoding is not UTF-8, so non-ASCII text either shows up as boxes or raises a UnicodeDecodeError.
3. რა უპირატესობა აქვს with open(...) as f:-ს?
3. What is the advantage of with open(...) as f:?
ფაილს ავტომატურად ხურავს ბლოკიდან გამოსვლისას — მაშინაც კი, თუ შიგნით შეცდომა მოხდა.
It closes the file automatically on leaving the block — even if an error occurred inside.
4. რას დაბეჭდავს? a = [1,2]; b = a; b.append(3); print(a)
4. What does this print? a = [1,2]; b = a; b.append(3); print(a)
[1, 2, 3]. b = a ასლს არ ქმნის — ორივე სახელი ერთსა და იმავე სიაზე მიუთითებს. ასლისთვის: a.copy() ან a[:].
[1, 2, 3]. b = a does not copy — both names point at the same list. For a copy use a.copy() or a[:].
5. რას აბრუნებს lst.sort()?
5. What does lst.sort() return?
None — ის ორიგინალს ცვლის ადგილზე. ახალი დახარისხებული სიისთვის — sorted(lst).
None — it sorts in place. For a new sorted list use sorted(lst).
6. რა განსხვავებაა append([3,4])-სა და extend([3,4])-ს შორის?
6. What is the difference between append([3,4]) and extend([3,4])?
append მთელ სიას ერთ ელემენტად დაამატებს → [1,2,[3,4]]; extend ელემენტებს ცალ-ცალკე → [1,2,3,4].
append adds the whole list as one element → [1,2,[3,4]]; extend adds the elements individually → [1,2,3,4].
7. რით განსხვავდება tuple list-ისგან?
7. How does a tuple differ from a list?
tuple უცვლელია — შექმნის შემდეგ ელემენტს ვერ შეცვლი/დაამატებ. სამაგიეროდ ოდნავ სწრაფია და ლექსიკონის გასაღებად გამოდგება.
A tuple is immutable — you cannot change or add elements after it is created. In exchange it is slightly faster and can serve as a dictionary key.
8. რას აკეთებს enumerate() და zip()?
8. What do enumerate() and zip() do?
enumerate ერთდროულად აბრუნებს ინდექსსა და მნიშვნელობას; zip ორ (ან მეტ) თანმიმდევრობას პარალელურად გადის, წყვილებად.
enumerate yields the index and the value together; zip walks two (or more) sequences in parallel, as pairs.
9. რატომ არის [[0]*3]*3 საშიში?
9. Why is [[0]*3]*3 dangerous?
ის სამ მიმართვას ერთსა და იმავე სიაზე ქმნის — ერთი ელემენტის შეცვლა სამივე „რიგს“ შეცვლის. სწორია:
[[0]*3 for _ in range(3)].
It creates three references to the same list — changing one element changes all three “rows”. The correct form is [[0]*3 for _ in range(3)].
ახალი ტიპიA new type
set — სიმრავლეset — a set
უნიკალური ელემენტების დაულაგებელი კრებული.
An unordered collection of unique elements.
s = {1, 2, 3, 3, 2, 1}
print(s) # {1, 2, 3} — duplicates gone
empty = set() # ⚠ {} — that is a dictionary!
numbers = [1, 2, 2, 3, 3, 3]
unique = set(numbers)
print(unique) # {1, 2, 3}
print(list(unique)) # [1, 2, 3] — back to a list
print(len(s)) # 3
print(2 in s) # True
# print(s[0]) # TypeError — no indexing!
#1 გამოყენებადუბლიკატების მოშორება ერთ ხაზში:
list(set(data)).
Use #1Removing duplicates in one line: list(set(data)).
#2 გამოყენება
in-შემოწმება ბევრად სწრაფია, ვიდრე სიაში — დიდ მონაცემზე ეს კრიტიკულია.
Use #2An in check is far faster than on a list — critical for large data.
set
სიმრავლეთა ოპერაციებიSet operations
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
print(a | b) # {1,2,3,4,5,6} union a.union(b)
print(a & b) # {3, 4} intersection a.intersection(b)
print(a - b) # {1, 2} difference a.difference(b)
print(a ^ b) # {1,2,5,6} symmetric difference
print({1, 2} <= a) # True — is it a subset?
print(a.isdisjoint({9})) # True — nothing in common
ცვლილებაModifying
s = {1, 2, 3}
s.add(4) # one element
s.update([5, 6]) # several
s.discard(10) # remove — no error if absent
s.remove(1) # remove — KeyError if absent
x = s.pop() # an arbitrary element
s.clear()
პრაქტიკული მაგალითიორ ჯგუფში საერთო სტუდენტები:
group_a & group_b. მხოლოდ პირველში მყოფნი: group_a - group_b.
A practical exampleStudents in both groups: group_a & group_b. Only in the first: group_a - group_b.
ახალი ტიპიA new type
dict — ლექსიკონიdict — a dictionary
წყვილები გასაღები → მნიშვნელობა. წვდომა ინდექსით კი არა, სახელით.
Key → value pairs. You look things up by name, not by index.
student = ["ნინო", 20, 92]
print(student[2]) # what is 2?
student = {
"name": "ნინო",
"age": 20,
"score": 92,
}
print(student["score"]) # 92
empty = {}
also = dict()
from_pairs = dict([("a", 1), ("b", 2)])
by_kwargs = dict(name="ნინო", age=20)
print(len(student)) # 3
print("name" in student) # True — it searches the keys
dict
წვდომა — [] თუ get()?Access — [] or get()?
student = {"name": "ნინო", "score": 92}
print(student["name"]) # ნინო
print(student["email"])
# KeyError: 'email'
print(student.get("email")) # None — no error
print(student.get("email", "არ არის")) # a default value
როდის რომელი
[] — როცა გასაღები აუცილებლად უნდა არსებობდეს (მისი არარსებობა შეცდომაა)
get() — როცა შესაძლოა არ იყოს და ნაგულისხმევი მნიშვნელობა გვაწყობს
Which one when
[] — when the key must be there (its absence is a bug)
get() — when it may be missing and a default is fine
# adding and changing
student["email"] = "nino@example.com" # a new key
student["score"] = 95 # changing an existing one
# removing
del student["email"]
value = student.pop("score") # remove and return
student.clear()
dict
გავლა ლექსიკონზეIterating a dictionary
scores = {"ნინო": 92, "გიორგი": 78, "ანა": 85}
print(scores.keys()) # dict_keys(['ნინო', 'გიორგი', 'ანა'])
print(scores.values()) # dict_values([92, 78, 85])
print(scores.items()) # dict_items([('ნინო', 92), ...])
# keys only (the default)
for name in scores:
print(name, scores[name])
# values only
for score in scores.values():
print(score)
# ✓ both at once — the most common form
for name, score in scores.items():
print(f"{name:<10}{score:>5}")
print(sum(scores.values()) / len(scores)) # the average
print(max(scores, key=scores.get)) # the top student
.items()ესაა ლექსიკონზე გავლის სტანდარტული ხერხი — თითოეულ ბიჯზე tuple-ს აბრუნებს, რომელიც პირდაპირ ორ ცვლადად იშლება.
.items()The standard way to loop a dictionary — each step yields a tuple that unpacks straight into two variables.
შაბლონიPattern
სიხშირის დათვლა — ლექსიკონის კლასიკაCounting frequencies — the classic use
text = "პროგრამირება პითონზე"
freq = {}
for ch in text:
if ch == " ":
continue
if ch in freq:
freq[ch] += 1
else:
freq[ch] = 1
# the same, more compactly:
for ch in text.replace(" ", ""):
freq[ch] = freq.get(ch, 0) + 1
# sorted by frequency
for ch, n in sorted(freq.items(), key=lambda p: p[1], reverse=True):
print(f"{ch}: {'█' * n} {n}")
მზა ინსტრუმენტი
A ready-made tool
from collections import Counter
freq = Counter(text.replace(" ", ""))
print(freq.most_common(3)) # the 3 most frequent
ეს ამოცანა თითქმის ყოველთვის ხვდება დასკვნით გამოცდაზე. სთხოვე ჯერ ხელით დაწერონ, მერე Counter-ით.
This exercise appears in nearly every final exam. Have them write it by hand first, then with
Counter.
კომბინაციაCombining
ჩადგმული სტრუქტურებიNested structures
students = {
"ნინო": {"age": 20, "scores": [92, 88, 95]},
"გიორგი": {"age": 21, "scores": [78, 82, 70]},
}
print(students["ნინო"]["age"]) # 20
print(students["ნინო"]["scores"][0]) # 92
for name, info in students.items():
scores = info["scores"]
avg = sum(scores) / len(scores)
print(f"{name:<10}{info['age']:>4}{avg:>8.1f}")
# a list of dictionaries — the most common shape of real data
group = [
{"name": "ნინო", "score": 92},
{"name": "გიორგი", "score": 78},
]
for s in group:
print(s["name"], s["score"])
best = max(group, key=lambda s: s["score"])
print("საუკეთესო:", best["name"])
ეს სტრუქტურა შემთხვევითი არაა„სია ლექსიკონებისგან“ ზუსტად ისეა აგებული, როგორც JSON — ფორმატი, რომლითაც ვებ-სერვისები მონაცემს ცვლიან.
This shape is no accidentA “list of dictionaries” is built exactly like JSON — the format web services exchange data in.
შედარებაComparison
ოთხი კრებული ერთ ცხრილშიFour collections in one table
| ტიპიType | ჩანაწერიWritten | დალაგებულიOrdered | ცვალებადიMutable | დუბლიკატიDuplicates | წვდომაAccess |
|---|---|---|---|---|---|
list | [1, 2, 3] | ✔ | ✔ | ✔ | ინდექსითBy index |
tuple | (1, 2, 3) | ✔ | ✘ | ✔ | ინდექსითBy index |
set | {1, 2, 3} | ✘ | ✔ | ✘ | მხოლოდ inin only |
dict | {"a": 1} |
✔ (ჩაწერის რიგით)(insertion order) | ✔ | გასაღები ✘Keys ✘ | გასაღებითBy key |
როგორ ავირჩიოთ
რიგი და ცვლილება →
list
უცვლელი ჩანაწერი (კოორდინატი, RGB) → tuple
უნიკალურობა ან სწრაფი in → set
სახელით მოძებნა → dict
How to choose
Order and mutation → list
A fixed record (a coordinate, an RGB triple) → tuple
Uniqueness or a fast in → set
Lookup by name → dict
შეფასებაAssessment
პრაქტიკული დავალება #3Practical assignment #3
8 ქულა · სრულდება აუდიტორიაში, დამოუკიდებლად 8 points · done in class, independently
- უნიკალური სიტყვებიტექსტიდან გამოყავი უნიკალური სიტყვები
set-ით, დაბეჭდე ანბანურად დახარისხებული - ორი ჯგუფის შედარებაორი სიმრავლიდან: საერთო სტუდენტები, მხოლოდ პირველში, მხოლოდ მეორეში მყოფნი
- სიტყვების სიხშირელექსიკონით დათვალე ტექსტში თითოეული სიტყვა; დაბეჭდე 5 ყველაზე ხშირი
- სატელეფონო წიგნაკიმენიუთი: დამატება, ძებნა (
get-ით), წაშლა, სრული სია. მონაცემები ფაილში შეინახე - უწყისისია ლექსიკონებისგან: სახელი + 3 ქულა. დაბეჭდე საშუალოთი დახარისხებული ცხრილი
- Unique wordsExtract the unique words from a text using a
setand print them sorted alphabetically - Comparing two groupsFrom two sets: the students in both, only in the first, only in the second
- Word frequencyCount every word in a text with a dictionary; print the 5 most frequent
- A phone bookWith a menu: add, look up (using
get), delete, list all. Persist the data to a file - A grade tableA list of dictionaries: a name plus 3 scores. Print a table sorted by average
რჩევადავალება 4 და 5 IX კვირის ფაილებთან მუშაობასაც იყენებს — ესაა კარგი ინტეგრაცია.
NoteTasks 4 and 5 also draw on week IX’s file handling — a good integration point.
შემაჯამებელიWrap-up
რა უნდა დაგამახსოვრდესWhat to remember
set— უნიკალური, დაულაგებელი, ინდექსის გარეშე;set()ცარიელისთვის ({}— ლექსიკონია!)- ოპერაციები:
|გაერთიანება ·&თანაკვეთა ·-სხვაობა ·^სიმეტრიული dict— გასაღები→მნიშვნელობა;[]მკაცრი,get()უსაფრთხო- გავლა:
for k, v in d.items(): - სიხშირის შაბლონი:
d[x] = d.get(x, 0) + 1 - „სია ლექსიკონებისგან“ — რეალური მონაცემების სტანდარტული ფორმა (JSON)
set— unique, unordered, no indexing; useset()for an empty one ({}is a dict!)- Operations:
|union ·&intersection ·-difference ·^symmetric difference dict— key → value;[]is strict,get()is safe- Iterating:
for k, v in d.items(): - The counting pattern:
d[x] = d.get(x, 0) + 1 - A “list of dictionaries” is the standard shape of real data (JSON)
შემდეგი — ლექცია 12შეცდომები და მათი დამუშავება:
try / except / else / finally, with ... as.
Next — lecture 12Errors and how to handle them: try / except / else / finally, with ... as.