Wiki 4: Functions, Scope, Modules na Mradi wa "Daftari la Wanafunzi"
Mwezi 1 | Lengo kuu: Mwanafunzi aweze kugawa programu kuwa functions zinazotumika tena, kutumia modules (za Python na zake mwenyewe), na kukamilisha mradi wa kwanza kamili wa CLI.
Maandalizi ya Mwalimu (soma kabla ya wiki kuanza)
- Tengeneza folder
python_darasa\wiki04, na ndani yake folderdaftarikwa ajili ya mradi. - Soma: https://docs.python.org/3/tutorial/controlflow.html#defining-functions (hadi 4.9) na https://docs.python.org/3/tutorial/modules.html (sehemu 6.1 tu).
- Andika mradi wa "Daftari la Wanafunzi" mwenyewe kabla ya Kipindi 3 (code kamili iko kwenye Kipindi 3). Iendeshe, ijaribu kwa input mbaya. Ukiielewa kila mstari, utaweza kumsaidia mwanafunzi akikwama.
- Dhana ngumu za wiki hii:
returndhidi yaprintna scope (local vs global). Jaribu mifano ya Kipindi 1 Hatua 3 na Kipindi 2 Hatua 1 kwenye REPL mpaka uweze kuzieleza kwa maneno yako. - Kipindi 3 ni pia marudio ya Mwezi 1 — andaa maswali ya haraka (yako kwenye Kipindi 3).
Malengo ya Wiki (mwisho wa wiki mwanafunzi ataweza...)
- Kuandika function kwa
def, kuiita, na kuelewa kwa nini functions ni muhimu (DRY — Don't Repeat Yourself). - Kutumia parameters na arguments; kutofautisha
returnnaprint; kurudisha thamani nyingi (tuple). - Kutumia default arguments, keyword arguments,
*argsna**kwargs. - Kuelewa scope (local na global) na kwa nini kuepuka
global. - Kuandika docstrings na kutumia
help(). - Kutumia
importna modules:math,random,datetime, na kutengeneza module yake mwenyewe. - Kujenga programu ya CLI "Daftari la Wanafunzi" kwa kutumia lists, dicts na functions.
Kipindi 1 — Functions: def, parameters, return
Mtiririko wa kipindi
- Marudio ya kazi ya nyumbani (kamusi.py)
- Kwa nini functions? Tayari tunatumia:
print,len,input defbila parameters, kisha na parametersreturndhidi yaprint- Mapumziko
- Kurudisha thamani nyingi;
returnmapema; function inaita function - Kubadilisha programu ya zamani (madaraja ya alama) kuwa functions
- Zoezi darasani
- Q&A + kazi ya nyumbani
Elezo kwa mwalimu (soma kwanza wewe)
- Function ni kipande cha code chenye jina, ambacho unakiandika mara moja na kukitumia (kukiita) mara nyingi.
- Tayari tumetumia functions za Python (built-in):
print(),len(),input(),int(). Sasa tunatengeneza zetu. -
Muundo:
def jina_la_function(parameter1, parameter2): # mwili (body) — indented return matokeo
-
Kufafanua (define) si kuendesha.
definamwambia Python "kumbuka maagizo haya". Hayafanyiki mpaka uite:jina_la_function(3, 4). - Parameter ni jina la variable kwenye
def(a,b). Argument ni thamani halisi unayotuma wakati wa kuita (3,4). returninarudisha thamani kwa aliyeita na inamaliza function papo hapo. Unaweza kuihifadhi:x = jumlisha(3, 4).printinaonyesha tu kwenye skrini — haimpi aliyeita chochote. Function isiyo nareturninarudishaNone.- Kanuni rahisi: function ifanye kazi moja; ikihesabu kitu, irudishe (return); acha code inayoiita iamue kama ita-print.
- Kurudisha thamani nyingi:
return ndogo, kubwa→ inarudisha tuple →a, b = function(). - Function lazima ifafanuliwe kabla ya kuitwa (juu kwenye file).
Sema hivi kwa mwanafunzi
- "Function ni kama mashine ya juisi: unaweka matunda (arguments), inafanya kazi ndani (body), inakupa juisi (return). Hujali ndani inafanyaje — unaitumia tu."
- "Au kama recipe ya chapati iliyoandikwa kwenye daftari. Kuandika recipe (def) si kupika. Kupika ni kuiita:
pika_chapati(5)." - "
returnni kama mhudumu anayekuletea chakula mezani — unaweza kukila, kukihifadhi, kukipa mtu.printni kama mhudumu anayekuonyesha chakula kupitia dirishani kisha anaondoka nacho!" - "DRY — Don't Repeat Yourself. Ukijikuta unanakili code ile ile mara tatu, ni wakati wa kutengeneza function."
Andika code hii live (share screen)
Hatua 1 — functions.py: function ya kwanza
def salimu(): print("Habari!") print("Karibu darasani.") salimu() salimu()
Habari! Karibu darasani. Habari! Karibu darasani.
Futa salimu() mbili za mwisho na endesha — hakuna kinachotokea. "Kufafanua si kuendesha."
Hatua 2 — Parameters
def salimu(jina): print(f"Habari {jina}!") salimu("Amina") salimu("Juma")
def eneo_mstatili(urefu, upana): print("Eneo ni", urefu * upana) eneo_mstatili(5, 3) # Eneo ni 15
Hatua 3 — return dhidi ya print (muhimu sana!)
def jumlisha_print(a, b): print(a + b) def jumlisha_return(a, b): return a + b x = jumlisha_print(3, 4) # inaonyesha 7 print("x ni:", x) # x ni: None ← !! y = jumlisha_return(3, 4) # haionyeshi kitu print("y ni:", y) # y ni: 7 print(jumlisha_return(10, 5) * 2) # 30 — tunaweza kuitumia kwenye hesabu
Uliza: "Kwa nini x ni None?" → function haikurudisha kitu.
Hatua 4 — return inamaliza function
def ni_mtu_mzima(umri): if umri >= 18: return True return False # inafikiwa tu kama juu haikurudisha print(ni_mtu_mzima(20)) # True print(ni_mtu_mzima(12)) # False def gawa(a, b): if b == 0: return "Huwezi kugawa kwa sifuri" return a / b print("Mstari huu haufikiwi kamwe") print(gawa(10, 2)) # 5.0 print(gawa(10, 0)) # Huwezi kugawa kwa sifuri
Hatua 5 — Thamani nyingi
def takwimu(namba): return min(namba), max(namba), sum(namba) / len(namba) ndogo, kubwa, wastani = takwimu([45, 82, 67, 90]) print(ndogo, kubwa, wastani) # 45 90 71.0
Hatua 6 — Kubadilisha programu ya zamani kuwa functions
def daraja(alama): if alama >= 75: return "A" elif alama >= 65: return "B" elif alama >= 45: return "C" elif alama >= 30: return "D" else: return "F" def wastani(alama_list): if len(alama_list) == 0: return 0 return sum(alama_list) / len(alama_list) alama = [78, 64, 50, 29] for a in alama: print(a, "->", daraja(a)) w = wastani(alama) print(f"Wastani: {w:.1f}, daraja: {daraja(w)}")
78 -> A 64 -> C 50 -> C 29 -> F Wastani: 55.2, daraja: C
Sisitiza: function daraja inatumika mara 5 bila kuandika if/elif tena.
Hatua 7 — Function inaita function
def eneo_duara(r): return 3.14159 * r ** 2 def gharama_rangi(r, bei_kwa_m2): return eneo_duara(r) * bei_kwa_m2 print(f"{gharama_rangi(2, 5000):,.0f} TZS") # 62,832 TZS
Maswali ya kumuuliza mwanafunzi
- Tofauti ya kufafanua (define) na kuita (call) function? — Jibu:
definahifadhi maagizo; kuitaf()ndiko kunayaendesha. - Function isiyo na
returninarudisha nini? — Jibu:None. - Parameter na argument? — Jibu: Parameter ni jina kwenye
def; argument ni thamani inayotumwa. - Code baada ya
returninafanyika? — Jibu: Hapana,returninamaliza function. - Kwa nini ni bora
returnkulikoprintndani ya function ya hesabu? — Jibu: Ili matokeo yatumike tena (kuhifadhi, kuhesabu, kulinganisha).
Makosa ya kawaida
| Kosa | Ujumbe wa error | Suluhisho |
|---|---|---|
| Kuita kabla ya kufafanua | NameError: name 'salimu' is not defined |
Weka def juu ya mahali unapoiita. |
| Idadi ya arguments isiyolingana | TypeError: eneo_mstatili() missing 1 required positional argument: 'upana' |
Tuma arguments zote. |
| Arguments zaidi | TypeError: salimu() takes 1 positional argument but 2 were given |
Linganisha na parameters. |
| Kusahau mabano wakati wa kuita | salimu → hakuna kinachotokea; print(salimu) → <function salimu at 0x...> |
salimu() |
Kutumia print badala ya return |
Matokeo ni None; TypeError: unsupported operand type(s) for *: 'NoneType' and 'int' |
return thamani. |
Kusahau : au indentation |
SyntaxError: expected ':' / IndentationError: expected an indented block after function definition |
def f(): + nafasi 4. |
Zoezi darasani
- Andika
celsius_to_fahrenheit(c)inayorudishac * 9/5 + 32. Ijaribu kwa 0, 37, 100. - Andika
ni_shufwa(n)inayorudishaTrue/False. Itumie kuchapisha namba shufwa 1–20. - Andika
hesabu_vokali(neno)inayorudisha idadi ya vokali. - Andika
bei_baada_ya_punguzo(bei, asilimia)inayorudisha bei mpya. Mf.(10000, 15)→8500.0.
Jibu
def celsius_to_fahrenheit(c): return c * 9 / 5 + 32 for c in [0, 37, 100]: print(c, "C =", celsius_to_fahrenheit(c), "F") # 0 C = 32.0 F, 37 C = 98.6 F, 100 C = 212.0 F def ni_shufwa(n): return n % 2 == 0 for i in range(1, 21): if ni_shufwa(i): print(i, end=" ") print() def hesabu_vokali(neno): idadi = 0 for h in neno.lower(): if h in "aeiou": idadi += 1 return idadi print(hesabu_vokali("Tanzania")) # 4 def bei_baada_ya_punguzo(bei, asilimia): return bei - bei * asilimia / 100 print(bei_baada_ya_punguzo(10000, 15)) # 8500.0
Kipindi 2 — Default/Keyword Arguments, *args/**kwargs, Scope, Docstrings, Modules
Mtiririko wa kipindi
- Marudio ya kazi ya nyumbani
- Default arguments na keyword arguments
*argsna**kwargs- Scope: local na global
- Mapumziko
- Docstrings na
help() - Modules:
import math,random,datetime,from ... import - Module yetu wenyewe:
zana.py+main.py - Q&A + kazi ya nyumbani
Elezo kwa mwalimu (soma kwanza wewe)
- Default argument:
def salimu(jina, salamu="Habari"):— kama mtumiaji hatatumasalamu, inatumia"Habari". Parameters zenye default lazima ziwe baada ya zisizo na default. - Keyword argument: wakati wa kuita, taja jina:
salimu(salamu="Shikamoo", jina="Bibi")— mpangilio haujalishi. Tayari mmetumia:print(..., sep="-", end=""). *args: inakusanya arguments zozote za ziada (positional) kuwa tuple.def jumla(*namba):→jumla(1, 2, 3)→namba = (1, 2, 3).**kwargs: inakusanya keyword arguments za ziada kuwa dict.def wasifu(**taarifa):→wasifu(jina="Ali", mji="Moshi")→taarifa = {"jina": "Ali", "mji": "Moshi"}.- Majina
args/kwargsni mazoea tu; muhimu ni*na**. - Scope: variable iliyotengenezwa ndani ya function ni local — inaishi ndani tu na inapotea function ikiisha. Variable iliyotengenezwa nje (juu ya file) ni global — inaweza kusomwa ndani ya function. Lakini ukiipa thamani ndani ya function (
x = ...), Python inatengeneza local mpya yenye jina hilo; global haibadiliki. - Keyword
global xinaruhusu kubadilisha global ndani ya function — epuka; ni bora kupitisha kama parameter na kutumiareturn. - Tahadhari (mutable): kama global ni list/dict, ukiibadilisha kwa method (
.append) ndani ya function, inabadilika kweli (hakuna assignment mpya). Hii tutaitumia kwenye mradi Kipindi 3 (tunapitisha list kama parameter). - Docstring: string ya
"""..."""mstari wa kwanza ndani ya function, inaeleza function inafanya nini.help(jina_la_function)inaionyesha. VS Code inaionyesha ukipeleka mouse juu ya jina. - Module ni file la
.pylenye functions/variables.import math→math.sqrt(16).from math import sqrt→sqrt(16).import datetime as dt→ jina fupi.math:sqrt,pi,ceil,floor,powrandom:randint,choice,shuffle,randomdatetime:date.today(),datetime.now(),.strftime("%d/%m/%Y"), kutoa tarehe mbili →timedelta
- Module yako: file
zana.pykwenye folder ile ile →import zanakwenyemain.py. Usiite file lakomath.py,random.py,datetime.py! if __name__ == "__main__":— code chini yake inaendeshwa tu ukiendesha file hilo moja kwa moja, si likiwa imported. Ifundishe kwa ufupi; tutaitumia kwenye mradi.
Sema hivi kwa mwanafunzi
- "Default argument ni kama kuagiza chai: usiposema chochote, unapata chai ya maziwa (default). Ukisema 'chai ya rangi', unapata hiyo."
- "Keyword argument ni kama kujaza fomu kwa kutaja kila sehemu: 'Jina: ..., Mji: ...' — haijalishi unaanza na ipi."
- "
*argsni kama kikapu — weka matunda mangapi unayotaka.**kwargsni kama kikapu chenye lebo kwenye kila tunda." - "Scope ni kama chumba cha mtihani: kilichoandikwa kwenye karatasi ya rasimu ndani ya chumba (local) kinabaki humo. Ubao wa matangazo nje (global) kila mtu anaweza kuusoma, lakini si kuubadilisha bila ruhusa maalum."
- "Module ni kama sanduku la zana (toolbox).
import mathni kufungua sanduku la zana za hisabati. Huhitaji kutengeneza nyundo mwenyewe."
Andika code hii live (share screen)
Hatua 1 — Default na keyword (arguments.py)
def salimu(jina, salamu="Habari"): print(f"{salamu}, {jina}!") salimu("Amina") # Habari, Amina! salimu("Bibi", "Shikamoo") # Shikamoo, Bibi! salimu(salamu="Mambo", jina="Juma") # Mambo, Juma! def bei_jumla(bei, idadi=1, kodi=0.18): return bei * idadi * (1 + kodi) print(bei_jumla(1000)) # 1180.0 print(bei_jumla(1000, 3)) # 3540.0 print(bei_jumla(1000, kodi=0)) # 1000.0
Hatua 2 — *args na **kwargs
def jumla(*namba): print("namba ni:", namba) total = 0 for n in namba: total += n return total print(jumla(1, 2)) # namba ni: (1, 2) -> 3 print(jumla(5, 10, 15, 20)) # namba ni: (5, 10, 15, 20) -> 50 print(jumla()) # namba ni: () -> 0 def wasifu(jina, **taarifa): print(f"--- {jina} ---") for key, value in taarifa.items(): print(f"{key}: {value}") wasifu("Amina", umri=20, mji="Dodoma", kozi="Python")
--- Amina --- umri: 20 mji: Dodoma kozi: Python
Hatua 3 — Scope
x = 10 # global def onyesha(): print("Ndani, x =", x) # inaweza kusoma global onyesha() # Ndani, x = 10 def badilisha(): x = 99 # hii ni LOCAL mpya, si global print("Ndani, x =", x) badilisha() # Ndani, x = 99 print("Nje, x =", x) # Nje, x = 10 ← haijabadilika! def tengeneza(): siri = "local" return siri tengeneza() # print(siri) # NameError: name 'siri' is not defined
Onyesha kosa la kawaida:
hesabu = 0 def ongeza(): hesabu += 1 # UnboundLocalError ongeza()
UnboundLocalError: cannot access local variable 'hesabu' where it is not associated with a value
Njia bora (bila global):
def ongeza(hesabu): return hesabu + 1 hesabu = 0 hesabu = ongeza(hesabu) hesabu = ongeza(hesabu) print(hesabu) # 2
Na list ikipitishwa (mutable):
def ongeza_jina(orodha, jina): orodha.append(jina) # inabadilisha list ya asili majina = [] ongeza_jina(majina, "Amina") ongeza_jina(majina, "Juma") print(majina) # ['Amina', 'Juma']
Hatua 4 — Docstrings
def bmi(uzito, urefu): """Hesabu Body Mass Index. uzito: kilo (float) urefu: mita (float) Inarudisha BMI kama float. """ return uzito / urefu ** 2 help(bmi) print(bmi(65, 1.7))
Pia onyesha: peleka mouse juu ya bmi kwenye VS Code — docstring inaonekana.
Hatua 5 — math na random (modules_demo.py)
import math import random print(math.sqrt(81)) # 9.0 print(math.pi) # 3.141592653589793 print(math.ceil(4.1)) # 5 print(math.floor(4.9)) # 4 print(round(math.pi, 2)) # 3.14 print(random.randint(1, 6)) # mf. 4 print(random.choice(["Simba", "Yanga", "Azam"])) # mf. Yanga kadi = [1, 2, 3, 4, 5] random.shuffle(kadi) print(kadi) # mf. [3, 1, 5, 2, 4] print(random.random()) # mf. 0.5372... (0 hadi chini ya 1)
from math import sqrt, pi print(sqrt(16), pi) # 4.0 3.141592653589793
Hatua 6 — datetime
from datetime import date, datetime leo = date.today() print(leo) # mf. 2026-11-25 print(leo.year, leo.month, leo.day) print(leo.strftime("%d/%m/%Y")) # mf. 25/11/2026 sasa = datetime.now() print(sasa.strftime("%H:%M")) # mf. 18:30 mwaka_mpya = date(2027, 1, 1) siku_zilizobaki = (mwaka_mpya - leo).days print(f"Siku {siku_zilizobaki} hadi mwaka mpya") def umri_kutoka_tarehe(mwaka, mwezi, siku): """Rudisha umri (miaka kamili) kutoka tarehe ya kuzaliwa.""" leo = date.today() umri = leo.year - mwaka if (leo.month, leo.day) < (mwezi, siku): # bado hajafikisha siku ya kuzaliwa umri -= 1 return umri print(umri_kutoka_tarehe(2005, 12, 15))
Angalia: (leo.month, leo.day) < (mwezi, siku) inalinganisha tuples — inaanza na kipengele cha kwanza, kikilingana inaenda cha pili. Mfano mzuri wa kurudia tuples za Wiki 3.
Hatua 7 — Module yetu: tengeneza zana.py
# zana.py — functions zetu za msaada """Zana ndogo za kusaidia programu zetu.""" KIWANGO_USD = 2600 def tzs_to_usd(tzs): """Badilisha shilingi kuwa dola.""" return round(tzs / KIWANGO_USD, 2) def mstari(urefu=30, alama="="): """Rudisha mstari wa alama kwa ajili ya kupamba.""" return alama * urefu if __name__ == "__main__": # inaendeshwa tu ukiendesha zana.py moja kwa moja print("Kujaribu zana:", tzs_to_usd(26000))
Kisha main.py kwenye folder ile ile:
import zana print(zana.mstari()) print("Dola:", zana.tzs_to_usd(52000)) print("Kiwango:", zana.KIWANGO_USD) print(zana.mstari(20, "-"))
Endesha main.py:
============================== Dola: 20.0 Kiwango: 2600 --------------------
Kisha endesha zana.py moja kwa moja → Kujaribu zana: 10.0. Eleza: "Ukiendesha main.py, sehemu ya if __name__ == "__main__": ya zana.py haifanyiki."
Maswali ya kumuuliza mwanafunzi
def f(a, b=2)—f(5)inapatab= ? — Jibu: 2.def f(a=1, b):inafanya kazi? — Jibu: Hapana:SyntaxError: parameter without a default follows parameter with a default.*argsinakuwa aina gani ndani ya function?**kwargs? — Jibu: tuple; dict.- Variable iliyoundwa ndani ya function inapatikana nje? — Jibu: Hapana (local).
- Tofauti ya
import mathnafrom math import sqrt? — Jibu: Ya kwanza unaandikamath.sqrt(); ya pilisqrt()moja kwa moja. - Kwa nini usiite file lako
random.py? — Jibu: Python itaimport file lako badala ya module ya Python.
Makosa ya kawaida
| Kosa | Ujumbe wa error | Suluhisho |
|---|---|---|
| Default kabla ya isiyo default | SyntaxError: parameter without a default follows parameter with a default |
Weka zenye default mwishoni. |
Kubadilisha global bila global |
UnboundLocalError: cannot access local variable 'hesabu' where it is not associated with a value |
Pitisha kama parameter + return. |
| Kutumia local nje | NameError: name 'siri' is not defined |
return thamani. |
| Kusahau jina la module | sqrt(9) baada ya import math → NameError: name 'sqrt' is not defined |
math.sqrt(9) au from math import sqrt. |
| Module haipo / spelling | ModuleNotFoundError: No module named 'zana' |
File liwe kwenye folder ile ile; VS Code ifungue folder hilo; spelling sahihi. |
| File lako lina jina la module | AttributeError: module 'random' has no attribute 'randint' (mara nyingi pia (consider renaming '...\random.py' since it has the same name as the standard library module named 'random'...)) |
Badilisha jina la file, futa __pycache__. |
datetime.now() baada ya import datetime |
AttributeError: module 'datetime' has no attribute 'now' |
datetime.datetime.now() au from datetime import datetime. |
| Keyword argument isiyokuwepo | TypeError: salimu() got an unexpected keyword argument 'jna' |
Angalia spelling ya parameter. |
Zoezi darasani
- Andika
tengeneza_email(jina, mwisho, kikoa="shule.ac.tz")inayorudishajina.mwisho@kikoakwa herufi ndogo. - Andika
wastani(*alama)inayorudisha wastani wa alama zozote; irudishe 0 kama hakuna. - Kwa
random, andikatengeneza_password(urefu=8)inayorudisha password ya herufi na namba za bahati. (Kidokezo:random.choice("abc...xyz0123456789").) - Andika
siku_hadi(mwaka, mwezi, siku)inayorudisha siku zilizobaki hadi tarehe hiyo kutoka leo.
Jibu
import random from datetime import date def tengeneza_email(jina, mwisho, kikoa="shule.ac.tz"): """Rudisha email kwa mfumo jina.mwisho@kikoa.""" return f"{jina.strip().lower()}.{mwisho.strip().lower()}@{kikoa}" print(tengeneza_email("Amina", "Juma")) # amina.juma@shule.ac.tz print(tengeneza_email("Ali", "Hassan", kikoa="kazi.co.tz")) def wastani(*alama): """Rudisha wastani wa alama zozote zilizotumwa.""" if len(alama) == 0: return 0 return sum(alama) / len(alama) print(wastani(70, 80, 90)) # 80.0 print(wastani()) # 0 def tengeneza_password(urefu=8): """Rudisha password ya bahati ya herufi ndogo, kubwa na namba.""" herufi = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" password = "" for _ in range(urefu): password += random.choice(herufi) return password print(tengeneza_password()) # mf. aZ3kP9qL print(tengeneza_password(12)) def siku_hadi(mwaka, mwezi, siku): """Rudisha idadi ya siku kutoka leo hadi tarehe iliyotolewa.""" return (date(mwaka, mwezi, siku) - date.today()).days print(siku_hadi(2026, 12, 25), "siku hadi Krismasi")
Kumbuka: _ kwenye for _ in range(...) ni jina la variable tusiyoihitaji — mazoea ya kawaida. Kwa password za kweli Python ina module secrets (salama zaidi) — tutaitaja baadaye.
Kipindi 3 — Mini Project: CLI "Daftari la Wanafunzi" + Marudio ya Mwezi 1
Mtiririko wa kipindi
- Marudio ya kazi ya nyumbani
- Kueleza mradi: unafanya nini, muundo wa data, orodha ya functions (mpango kwanza!)
- Hatua 1–2: data + functions za msaada (
daraja,wastani,pata_namba) - Hatua 3: ongeza mwanafunzi, onyesha wote
- Mapumziko
- Hatua 4: tafuta, ongeza alama, futa
- Hatua 5: takwimu za darasa + menyu kuu (
main) - Marudio ya Mwezi 1: maswali ya haraka
- Q&A + kazi ya nyumbani + maoni ya mwezi
Elezo kwa mwalimu (soma kwanza wewe)
- Mradi unafanya nini: programu ya terminal (CLI = Command Line Interface) ambayo mwalimu anaweza:
- Kuongeza mwanafunzi (jina + alama za masomo)
- Kuonyesha wanafunzi wote (jedwali: jina, wastani, daraja)
- Kumtafuta mwanafunzi kwa jina
- Kuongeza/kubadilisha alama ya somo
- Kumfuta mwanafunzi
- Kuona takwimu za darasa (wastani wa darasa, bora, idadi kwa kila daraja)
- Kutoka
-
Muundo wa data: list ya dicts; kila mwanafunzi ana dict ya alama (somo → alama):
wanafunzi = [ {"jina": "Amina Juma", "alama": {"Hisabati": 78, "Kiingereza": 85}}, ]
Hii inatumia kila kitu cha mwezi huu: list, dict, nested structure, loops, if, f-strings, functions.
-
Kanuni za muundo wa code:
- Kila kazi = function moja (
ongeza_mwanafunzi,onyesha_wote, ...). - Functions zinapokea list
wanafunzikama parameter (hatutumiiglobal). Kwa kuwa list ni mutable,append/removendani ya function zinabadilisha list ya asili. - Function ndogo za msaada (
daraja,wastani) zinarudisha thamani; function za menyu zinaonyesha (print). pata_namba()inauliza tena mpaka mtumiaji aandike namba sahihi — hivyo programu haiharibiki (crash) kwaValueError. Tunatumiatry/excepthapa kwa mara ya kwanza, kwa ufupi tu: "jaribu kubadilisha; kama inashindikana (ValueError), fanya hiki." Tutaisoma kwa kina mwezi ujao.main()ina menyu; mwisho wa file:if __name__ == "__main__": main().
- Kila kazi = function moja (
- Mbinu ya kufundisha: usiandike file lote mara moja. Andika hatua moja, endesha, onyesha inafanya kazi, kisha ongeza. Mwanafunzi aandike pamoja nawe kwenye kompyuta yake (au akufuate na kuuliza). Ukikosa muda, maliza hatua 1–4 na hatua 5 iwe kazi ya nyumbani.
Sema hivi kwa mwanafunzi
- "Leo tunajenga programu halisi — kama ile ambayo mwalimu wa darasa angeitumia badala ya daftari la karatasi."
- "Mjenzi hajengi nyumba bila ramani. Kabla ya code, tunapanga: data itahifadhiwa vipi? Tunahitaji functions gani?"
- "Kila function ni kama mfanyakazi mmoja kwenye ofisi: mmoja anapokea wanafunzi wapya, mwingine anatafuta, mwingine anahesabu takwimu.
main()ni meneja anayepokea maombi na kumtuma mfanyakazi sahihi." - "Programu nzuri haiharibiki mtumiaji akikosea. Ndiyo maana
pata_nambainauliza tena kwa upole."
Andika code hii live (share screen)
Tengeneza daftari\daftari.py. Hapa chini ni toleo kamili; liandike kwa hatua kama zilivyowekwa alama kwenye comments.
"""Daftari la Wanafunzi — programu ya CLI ya kusimamia alama za wanafunzi. Mradi wa Mwezi 1: lists, dicts, loops, if, f-strings na functions. """ # ========== HATUA 1: Data ya kuanzia ========== MASOMO = ("Hisabati", "Kiingereza", "Kiswahili", "Python") # tuple: haibadiliki def data_ya_mfano(): """Rudisha list ya wanafunzi wa mfano ili tuanze na data.""" return [ {"jina": "Amina Juma", "alama": {"Hisabati": 78, "Kiingereza": 85, "Kiswahili": 90, "Python": 88}}, {"jina": "Baraka Mushi", "alama": {"Hisabati": 55, "Kiingereza": 62, "Kiswahili": 70, "Python": 48}}, {"jina": "Neema Said", "alama": {"Hisabati": 92, "Kiingereza": 74, "Kiswahili": 81, "Python": 95}}, ] # ========== HATUA 2: Functions za msaada ========== def wastani(alama): """Rudisha wastani wa dict ya alama {somo: alama}. Rudisha 0 kama ni tupu.""" if len(alama) == 0: return 0 return sum(alama.values()) / len(alama) def daraja(alama): """Rudisha daraja (A-F) la alama moja.""" if alama >= 75: return "A" elif alama >= 65: return "B" elif alama >= 45: return "C" elif alama >= 30: return "D" else: return "F" def pata_namba(ujumbe, chini=0, juu=100): """Uliza namba mpaka mtumiaji aandike namba sahihi kati ya chini na juu.""" while True: jibu = input(ujumbe).strip() try: namba = int(jibu) except ValueError: print(" ! Tafadhali andika namba kamili.") continue if chini <= namba <= juu: return namba print(f" ! Namba iwe kati ya {chini} na {juu}.") def tafuta(wanafunzi, jina): """Rudisha dict ya mwanafunzi mwenye jina hilo (bila kujali herufi kubwa), au None.""" for m in wanafunzi: if m["jina"].lower() == jina.strip().lower(): return m return None # ========== HATUA 3: Ongeza na onyesha ========== def ongeza_mwanafunzi(wanafunzi): """Uliza jina na alama za kila somo, kisha ongeza mwanafunzi kwenye list.""" jina = input("Jina kamili: ").strip().title() if jina == "": print(" ! Jina haliwezi kuwa tupu.") return if tafuta(wanafunzi, jina) is not None: print(f" ! {jina} tayari yupo.") return alama = {} for somo in MASOMO: alama[somo] = pata_namba(f" Alama ya {somo} (0-100): ") wanafunzi.append({"jina": jina, "alama": alama}) print(f" ✓ {jina} ameongezwa. Wastani: {wastani(alama):.1f}") def onyesha_wote(wanafunzi): """Onyesha jedwali la wanafunzi wote: jina, wastani, daraja.""" if not wanafunzi: print(" Hakuna wanafunzi bado.") return print(f"\n {'#':<3}{'JINA':<20}{'WASTANI':>8} DARAJA") print(" " + "-" * 39) for i, m in enumerate(wanafunzi, start=1): w = wastani(m["alama"]) print(f" {i:<3}{m['jina']:<20}{w:>8.1f} {daraja(w)}") print() def onyesha_mmoja(m): """Onyesha alama zote za mwanafunzi mmoja.""" print(f"\n == {m['jina']} ==") for somo, a in m["alama"].items(): print(f" {somo:<12}{a:>4} {daraja(a)}") w = wastani(m["alama"]) print(f" {'WASTANI':<12}{w:>4.0f} {daraja(w)}\n") # ========== HATUA 4: Tafuta, badilisha alama, futa ========== def tafuta_mwanafunzi(wanafunzi): """Uliza jina na onyesha taarifa za mwanafunzi.""" jina = input("Jina la kutafuta: ") m = tafuta(wanafunzi, jina) if m is None: print(" ! Hakupatikana.") else: onyesha_mmoja(m) def badilisha_alama(wanafunzi): """Ongeza au badilisha alama ya somo moja kwa mwanafunzi.""" m = tafuta(wanafunzi, input("Jina la mwanafunzi: ")) if m is None: print(" ! Hakupatikana.") return for i, somo in enumerate(MASOMO, start=1): print(f" {i}. {somo} (sasa: {m['alama'].get(somo, '-')})") chaguo = pata_namba(" Chagua somo: ", 1, len(MASOMO)) somo = MASOMO[chaguo - 1] m["alama"][somo] = pata_namba(f" Alama mpya ya {somo}: ") print(f" ✓ Imebadilishwa. Wastani mpya: {wastani(m['alama']):.1f}") def futa_mwanafunzi(wanafunzi): """Futa mwanafunzi baada ya kuthibitisha.""" m = tafuta(wanafunzi, input("Jina la kufuta: ")) if m is None: print(" ! Hakupatikana.") return thibitisha = input(f" Una uhakika unataka kumfuta {m['jina']}? (ndiyo/hapana): ") if thibitisha.strip().lower() == "ndiyo": wanafunzi.remove(m) print(" ✓ Amefutwa.") else: print(" Imesitishwa.") # ========== HATUA 5: Takwimu na menyu kuu ========== def takwimu_darasa(wanafunzi): """Onyesha wastani wa darasa, mwanafunzi bora, na idadi kwa kila daraja.""" if not wanafunzi: print(" Hakuna wanafunzi bado.") return wastani_list = [wastani(m["alama"]) for m in wanafunzi] wastani_darasa = sum(wastani_list) / len(wastani_list) bora = wanafunzi[0] for m in wanafunzi: if wastani(m["alama"]) > wastani(bora["alama"]): bora = m madaraja = {"A": 0, "B": 0, "C": 0, "D": 0, "F": 0} for w in wastani_list: madaraja[daraja(w)] += 1 print(f"\n Idadi ya wanafunzi: {len(wanafunzi)}") print(f" Wastani wa darasa: {wastani_darasa:.1f} ({daraja(wastani_darasa)})") print(f" Mwanafunzi bora: {bora['jina']} ({wastani(bora['alama']):.1f})") print(" Madaraja:") for d, idadi in madaraja.items(): print(f" {d}: {'#' * idadi} {idadi}") print(" Wastani kwa somo:") for somo in MASOMO: alama_somo = [m["alama"][somo] for m in wanafunzi if somo in m["alama"]] if alama_somo: print(f" {somo:<12}{sum(alama_somo) / len(alama_somo):>6.1f}") print() def main(): """Menyu kuu ya programu.""" wanafunzi = data_ya_mfano() vitendo = { "1": ongeza_mwanafunzi, "2": onyesha_wote, "3": tafuta_mwanafunzi, "4": badilisha_alama, "5": futa_mwanafunzi, "6": takwimu_darasa, } print("=" * 40) print(" DAFTARI LA WANAFUNZI v1.0") print("=" * 40) while True: print("1) Ongeza mwanafunzi 2) Onyesha wote") print("3) Tafuta 4) Badilisha alama") print("5) Futa 6) Takwimu za darasa") print("0) Toka") chaguo = input("Chagua: ").strip() if chaguo == "0": print("Kwaheri! Daftari limefungwa.") break elif chaguo in vitendo: vitendo[chaguo](wanafunzi) else: print(" ! Chaguo si sahihi, jaribu tena.") if __name__ == "__main__": main()
Maelezo ya mistari migumu (soma kabla, eleza darasani):
-
vitendo = {"1": ongeza_mwanafunzi, ...}— functions ni vitu pia; tunaweza kuziweka kwenye dict bila mabano (hatuziiti bado).vitendo[chaguo](wanafunzi)inachukua function sahihi na kuiita. Kama ni ngumu kwa mwanafunzi, onyesha toleo laif/elif(sawa kabisa):if chaguo == "1": ongeza_mwanafunzi(wanafunzi) elif chaguo == "2": onyesha_wote(wanafunzi) # ... n.k.
-
try: ... except ValueError:— "jaribuint(jibu); kama jibu si namba, badala ya programu kuanguka, fanya kilicho chini yaexcept." is not None/is None— njia sahihi ya kukaguaNone.m['alama'].get(somo, '-')— kama somo halina alama bado, onyesha-.
Mfano wa kuendesha:
========================================
DAFTARI LA WANAFUNZI v1.0
========================================
1) Ongeza mwanafunzi 2) Onyesha wote
3) Tafuta 4) Badilisha alama
5) Futa 6) Takwimu za darasa
0) Toka
Chagua: 2
# JINA WASTANI DARAJA
---------------------------------------
1 Amina Juma 85.2 A
2 Baraka Mushi 58.8 C
3 Neema Said 85.5 A
Chagua: 1
Jina kamili: zawadi ally
Alama ya Hisabati (0-100): sabini
! Tafadhali andika namba kamili.
Alama ya Hisabati (0-100): 70
Alama ya Kiingereza (0-100): 150
! Namba iwe kati ya 0 na 100.
Alama ya Kiingereza (0-100): 66
Alama ya Kiswahili (0-100): 80
Alama ya Python (0-100): 72
✓ Zawadi Ally ameongezwa. Wastani: 72.0
Chagua: 6
Idadi ya wanafunzi: 4
Wastani wa darasa: 75.4 (A)
Mwanafunzi bora: Neema Said (85.5)
Madaraja:
A: ## 2
B: # 1
C: # 1
D: 0
F: 0
Wastani kwa somo:
Hisabati 73.8
Kiingereza 71.8
Kiswahili 80.2
Python 75.8
Chagua: 0
Kwaheri! Daftari limefungwa.
(Menyu inajirudia baada ya kila chaguo — imeachwa kwenye mfano huu ili kufupisha.)
Marudio ya Mwezi 1 — maswali ya haraka:
type(input())daima ni nini? —str7 // 2na7 % 2? —3na1"Python"[::-1]? —"nohtyP"range(2, 8, 2)inatoa nini? — 2, 4, 6- Tofauti ya list na tuple? — list mutable, tuple immutable
- Kwa kutafuta bei kwa jina la bidhaa, muundo gani? — dict
- Function isiyo na
returninarudisha nini? —None - Kwa nini tunatumia functions? — kutumia code tena, kupanga programu, kurahisisha kurekebisha (DRY)
- Error gani unapata ukifanya
int("abc")? —ValueError - Kwenye mradi, kwa nini tunapitisha
wanafunzikama parameter badala yaglobal? — code wazi zaidi, function inajitegemea, rahisi kujaribu
Maswali ya kumuuliza mwanafunzi
- Kwa nini
alamaya kila mwanafunzi ni dict badala ya list? — Jibu: Ili tujue kila alama ni ya somo gani kwa jina (alama["Python"]), si kwa index. - Kwa nini
MASOMOni tuple? — Jibu: Masomo hayabadiliki wakati programu inaendeshwa; tuple inazuia kubadilishwa kwa bahati mbaya. ongeza_mwanafunzihainareturn— mwanafunzi mpya anafikaje kwenye list yamain? — Jibu: List ni mutable;appendndani ya function inabadilisha list ile ile iliyopitishwa.- Nini kingetokea bila
pata_nambamtumiaji akiandika "sabini"? — Jibu:ValueErrorna programu ingefungwa (crash). - Ungeongezaje somo jipya "Fizikia"? — Jibu: Liongeze kwenye tuple
MASOMO(na kwa data ya mfano kama unataka). - Data inapotea tukifunga programu — kwa nini? Tutatatuaje? — Jibu: Iko kwenye memory (RAM) tu. Mwezi ujao tutajifunza kuhifadhi kwenye file (JSON/CSV).
Makosa ya kawaida
| Kosa | Ujumbe wa error | Suluhisho |
|---|---|---|
| Kuweka function kwenye dict kwa mabano | vitendo = {"1": ongeza_mwanafunzi(wanafunzi)} → inaiita mara moja wakati wa kutengeneza dict |
Bila mabano: "1": ongeza_mwanafunzi |
| Nukuu ndani ya f-string (Python ≤3.11) | f"{m["jina"]}" → SyntaxError: f-string: unmatched '[' |
f"{m['jina']}" |
| Kusahau kupitisha list | TypeError: onyesha_wote() missing 1 required positional argument: 'wanafunzi' |
onyesha_wote(wanafunzi) |
Kutumia tafuta bila kukagua None |
TypeError: 'NoneType' object is not subscriptable |
if m is None: ... return |
| Wastani wa dict tupu | ZeroDivisionError: division by zero |
Kagua len(alama) == 0 kwanza. |
Kusahau kuita main() |
Programu inaendesha bila kuonyesha chochote | Ongeza if __name__ == "__main__": main() mwishoni. |
Indentation ya return ndani ya for |
tafuta inarudisha None baada ya mwanafunzi wa kwanza tu |
return None iwe nje ya for (kiwango sawa na for). |
Emoji/alama ✓ kuonekana vibaya kwenye terminal ya zamani |
Herufi za ajabu | Badilisha ✓ kuwa [OK]. |
Zoezi darasani
- Ongeza chaguo
7) Panga kwa wastanilinaloonyesha wanafunzi kuanzia wastani mkubwa hadi mdogo (bila kubadilisha list ya asili). - Badilisha
tafutaili ipate mwanafunzi hata ukiandika sehemu ya jina (mf. "ami" → "Amina Juma"). Irudishe list ya wote wanaolingana. - Ongeza kwenye
takwimu_darasaidadi ya waliofaulu (wastani ≥ 45) na walioshindwa.
Jibu
# zoezi 1 — ongeza function hii, na "7": panga_kwa_wastani kwenye dict ya vitendo, # na mstari "7) Panga kwa wastani" kwenye menyu. def panga_kwa_wastani(wanafunzi): """Onyesha wanafunzi kuanzia wastani mkubwa, bila kubadilisha list ya asili.""" jozi = [] for m in wanafunzi: jozi.append((wastani(m["alama"]), m["jina"])) jozi.sort(reverse=True) # tuples zinapangwa kwa kipengele cha kwanza (wastani) for nafasi, (w, jina) in enumerate(jozi, start=1): print(f" {nafasi}. {jina:<20}{w:>6.1f}")
Toleo la juu zaidi (kwa udadisi tu): sorted(wanafunzi, key=lambda m: wastani(m["alama"]), reverse=True) — lambda tutaijifunza baadaye.
# zoezi 2 def tafuta_sehemu(wanafunzi, kipande): """Rudisha list ya wanafunzi ambao majina yao yana kipande hicho.""" kipande = kipande.strip().lower() matokeo = [] for m in wanafunzi: if kipande in m["jina"].lower(): matokeo.append(m) return matokeo def tafuta_mwanafunzi(wanafunzi): matokeo = tafuta_sehemu(wanafunzi, input("Jina (au sehemu): ")) if not matokeo: print(" ! Hakupatikana.") for m in matokeo: onyesha_mmoja(m)
# zoezi 3 — ongeza ndani ya takwimu_darasa, baada ya wastani_list waliofaulu = len([w for w in wastani_list if w >= 45]) walioshindwa = len(wastani_list) - waliofaulu print(f" Waliofaulu: {waliofaulu}, Walioshindwa: {walioshindwa}")
Kazi ya Nyumbani
KN1 (baada ya Kipindi 1, leta Kipindi 2): maumbo.py — andika functions zinazorudisha (return): eneo_mraba(upande), eneo_mstatili(urefu, upana), eneo_pembetatu(kitako, kimo), eneo_duara(r). Kisha menyu ndogo inayomwuliza mtumiaji umbo na vipimo, na kuonyesha eneo kwa desimali 2.
KN2 (baada ya Kipindi 2, leta Kipindi 3): Tengeneza module hesabu_zangu.py yenye: wastani(*namba), kubwa_zaidi(*namba) (bila max), ni_prime(n) (inarudisha True/False), na docstring kwa kila moja. Kisha jaribu.py ina-import module hiyo na kuitumia. Bonus: ni_prime itumie math.sqrt ili iwe ya haraka.
KN3 (baada ya Kipindi 3, leta kipindi kijacho): Boresha "Daftari la Wanafunzi":
(a) chaguo la kubadilisha jina la mwanafunzi;
(b) onyesha somo ambalo darasa lilifanya vizuri zaidi;
(c) ripoti ya mwanafunzi mmoja ikiwa na tarehe ya leo juu (tumia datetime, mfumo dd/mm/yyyy).
Jibu
# maumbo.py import math def eneo_mraba(upande): return upande ** 2 def eneo_mstatili(urefu, upana): return urefu * upana def eneo_pembetatu(kitako, kimo): return 0.5 * kitako * kimo def eneo_duara(r): return math.pi * r ** 2 print("1) Mraba 2) Mstatili 3) Pembetatu 4) Duara") chaguo = input("Chagua umbo: ").strip() if chaguo == "1": eneo = eneo_mraba(float(input("Upande: "))) elif chaguo == "2": eneo = eneo_mstatili(float(input("Urefu: ")), float(input("Upana: "))) elif chaguo == "3": eneo = eneo_pembetatu(float(input("Kitako: ")), float(input("Kimo: "))) elif chaguo == "4": eneo = eneo_duara(float(input("Nusu kipenyo (r): "))) else: eneo = None if eneo is None: print("Chaguo si sahihi.") else: print(f"Eneo: {eneo:.2f}")
# hesabu_zangu.py """Functions zangu za hisabati.""" import math def wastani(*namba): """Rudisha wastani wa namba zote; 0 kama hakuna.""" if not namba: return 0 return sum(namba) / len(namba) def kubwa_zaidi(*namba): """Rudisha namba kubwa zaidi bila kutumia max(); None kama hakuna.""" if not namba: return None kubwa = namba[0] for n in namba: if n > kubwa: kubwa = n return kubwa def ni_prime(n): """Rudisha True kama n ni namba tasa (prime).""" if n < 2: return False for i in range(2, int(math.sqrt(n)) + 1): if n % i == 0: return False return True
# jaribu.py import hesabu_zangu as hz print(hz.wastani(10, 20, 30)) # 20.0 print(hz.kubwa_zaidi(4, 19, 7, 3)) # 19 primes = [n for n in range(1, 30) if hz.ni_prime(n)] print(primes) # [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] help(hz.ni_prime)
# KN3 — vipande vya kuongeza kwenye daftari.py from datetime import date # weka juu ya file # (a) def badilisha_jina(wanafunzi): """Badilisha jina la mwanafunzi.""" m = tafuta(wanafunzi, input("Jina la sasa: ")) if m is None: print(" ! Hakupatikana.") return jipya = input("Jina jipya: ").strip().title() if jipya == "": print(" ! Jina haliwezi kuwa tupu.") elif tafuta(wanafunzi, jipya) is not None: print(" ! Jina hilo tayari lipo.") else: m["jina"] = jipya print(" ✓ Jina limebadilishwa.") # (b) ongeza ndani ya takwimu_darasa, baada ya "Wastani kwa somo" somo_bora = None wastani_bora = -1 for somo in MASOMO: alama_somo = [m["alama"][somo] for m in wanafunzi if somo in m["alama"]] if alama_somo: w = sum(alama_somo) / len(alama_somo) if w > wastani_bora: somo_bora, wastani_bora = somo, w print(f" Somo bora la darasa: {somo_bora} ({wastani_bora:.1f})") # (c) badilisha onyesha_mmoja def onyesha_mmoja(m): """Onyesha ripoti ya mwanafunzi mmoja yenye tarehe ya leo.""" print(f"\n RIPOTI — {date.today().strftime('%d/%m/%Y')}") print(f" == {m['jina']} ==") for somo, a in m["alama"].items(): print(f" {somo:<12}{a:>4} {daraja(a)}") w = wastani(m["alama"]) print(f" {'WASTANI':<12}{w:>4.0f} {daraja(w)}\n") # Usisahau kuongeza "7": badilisha_jina kwenye vitendo na mstari kwenye menyu.
Ukiulizwa swali usilolijua
- Tumia
help(jina)audir(module)kwenye REPL (mf.import datetime; dir(datetime)) — inaonyesha kila kitu kilichomo. Kwa error, nakili mstari wa mwisho na uutafute. - Tafuta: "python function return vs print", "python args kwargs explained", "python datetime strftime", "python import own module same folder".
- Docs: https://docs.python.org/3/tutorial/controlflow.html#defining-functions , https://docs.python.org/3/tutorial/modules.html , https://docs.python.org/3/library/math.html , https://docs.python.org/3/library/random.html , https://docs.python.org/3/library/datetime.html
Checklist ya mwisho wa wiki
- Anaandika function kwa
def, anaiita, na anajua kufafanua si kuendesha - Anatofautisha parameter na argument
- Anaelewa
returndhidi yaprint, na kwamba bilareturn→None - Anarudisha thamani nyingi na kufanya unpacking
- Anatumia default arguments na keyword arguments
- Anaelewa
*args(tuple) na**kwargs(dict) - Anaeleza local vs global na kwa nini kuepuka
global - Anaandika docstrings na kutumia
help() - Anatumia
math,random,datetimekwaimportnafrom ... import - Ametengeneza module yake na ku-import kwenye file lingine
- Amekamilisha "Daftari la Wanafunzi" na anaweza kueleza kila function inafanya nini
- Mwezi 1: anaweza kuandika programu ndogo kamili bila kunakili (input → uchakataji → output)