Kazi katika Python: def, return, hoja, *args na **kwargs, lambda na type hints
Kazi katika Python ni kizuizi chenye jina kinachotangazwa kwa neno def, kinaitwa kwa jina pamoja na mabano, na kurudisha matokeo kwa return; bila return kazi hurudisha None. Hoja hupitishwa kwa mpangilio au kwa jina, *args hukusanya hoja za ziada za nafasi kuwa tuple, **kwargs hukusanya zile zilizotajwa kwa jina kuwa kamusi, na lambda huunda kazi fupi isiyo na jina kutoka kwa usemi mmoja.
Kazi katika Python ni kipande cha msimbo chenye jina ambacho kinaweza kuitwa mara nyingi upendavyo kwa data tofauti za kuingiza. Hutangazwa kwa neno def, hupokea thamani kupitia vigezo, na hutoa matokeo kwa return. Kazi ndiyo njia kuu ya kugeuza hati ndefu kuwa hatua zilizo wazi na zinazoweza kukaguliwa.
Jinsi ya kutangaza kazi: def python
Tangazo la kazi huanza kwa def, kisha jina, vigezo kwenye mabano na koloni. Mwili wa kazi huandikwa kwa ujongezaji wa nafasi nne — ujongezaji katika Python si pambo, bali ni sehemu ya sintaksia.
def greet(name):
"""Inarudisha salamu kwa mtumiaji."""
return f"Habari, {name}!"
print(greet("Amina")) # Habari, Amina!
Mfuatano wa nukuu tatu mara baada ya kichwa cha kazi ni docstring, yaani nyaraka za kazi. help(greet) na vidokezo vya mhariri huionyesha. Majina ya kazi kwa mujibu wa PEP 8 huandikwa kwa snake_case: add_expense, get_rate.
Mstari def greet(name): huitwa sahihi ya kazi (signature): jina pamoja na orodha ya vigezo (na type hints, ikiwa zipo). Kwa sahihi msomaji anaelewa jinsi ya kuitumia bila kuangalia mwili wake.
Kazi ya return katika Python
return humaliza kazi na kumpa aliyeiita thamani. Msimbo uliopo baada ya return iliyotekelezwa haufanyiki. Ikiwa return haipo, au imeandikwa bila thamani, kazi inarudisha None.
def area(w, h):
w * h # hesabu imefanyika lakini imetupwa
print(area(3, 4)) # None
def area(w, h):
return w * h
print(area(3, 4)) # 12
Kusahau return ni mojawapo ya makosa ya kawaida ya wanaoanza: kazi "inafanya kazi", lakini inarudisha None, na kosa linajitokeza mstari mmoja baadaye. Kazi inaweza kurudisha thamani kadhaa — kwa kweli ni tuple moja, ambayo ni rahisi kuifungua:
def min_max(numbers):
return min(numbers), max(numbers)
low, high = min_max([4, 1, 9])
print(low, high) # 1 9
Return ya mapema husaidia kuepuka ujongezaji usio wa lazima: kwanza kushughulikia visa maalum, kisha kuandika mantiki kuu.
def discount(price, is_member):
if price <= 0:
return 0
if not is_member:
return price
return price * 0.9
Hoja za kazi katika Python: za nafasi na za jina
Vigezo ni majina yaliyoandikwa katika tangazo la kazi; hoja ni thamani zinazopitishwa wakati wa wito. Hoja zinaweza kupitishwa kwa mpangilio (za nafasi) au kwa jina (za jina). Hoja za jina zinafanya wito ujieleze wenyewe, na mpangilio unakoma kuwa muhimu.
def add_expense(title, amount, category="nyingine"):
return {"title": title, "amount": amount, "category": category}
add_expense("Kahawa", 250) # kwa nafasi
add_expense(amount=250, title="Kahawa") # kwa jina
add_expense("Teksi", 600, category="usafiri") # mchanganyiko
Kigezo chenye thamani chaguo-msingi si lazima kukipatia thamani. Kanuni: vigezo vyenye thamani chaguo-msingi huandikwa baada ya vile vya lazima, na wakati wa wito hoja za nafasi huja kabla ya zile za jina. Vinginevyo Python itatoa SyntaxError.
Mtego: thamani chaguo-msingi inayoweza kubadilika
Thamani chaguo-msingi hukokotolewa mara moja — wakati mstari wa def unatekelezwa, si kila wito. Ikiwa ni orodha au kamusi, itakuwa ya pamoja kwa miito yote.
def add_item(item, acc=[]):
acc.append(item)
return acc
print(add_item(1)) # [1]
print(add_item(2)) # [1, 2] — orodha inakumbuka wito uliopita
Mbinu sahihi ni None kama chaguo-msingi na kuunda kitu kipya ndani ya kazi:
def add_item(item, acc=None):
if acc is None:
acc = []
acc.append(item)
return acc
*args na **kwargs: idadi yoyote ya hoja
Nyota moja mbele ya kigezo hukusanya hoja zote za ziada za nafasi kuwa tuple (tuple), na nyota mbili hukusanya zile za ziada za jina kuwa kamusi (dict). Majina args na kwargs ni makubaliano tu — muhimu ni nyota zenyewe.
def total(*args):
return sum(args)
print(total(100, 250, 40)) # 390
def make_user(name, **kwargs):
user = {"name": name}
user.update(kwargs)
return user
print(make_user("Amina", city="Arusha", age=30))
# {'name': 'Amina', 'city': 'Arusha', 'age': 30}
Nyota hizo hizo hufanya kazi kinyume pia — wakati wa wito zinafungua mkusanyiko au kamusi kuwa hoja:
values = [3, 4]
print(pow(*values)) # 81
opts = {"sep": " | ", "end": "\n"}
print("a", "b", **opts) # a | b
Vigezo vya nafasi pekee na vya jina pekee
Alama ya mkwaju / na nyota * katika orodha ya vigezo hufanya kazi kama vizuizi: kila kilicho kabla ya / kinapitishwa kwa mpangilio tu (sintaksia ilionekana Python 3.8, PEP 570), na kilicho baada ya * kinapitishwa kwa jina tu.
def convert(amount, /, *, rate, currency="USD"):
return round(amount / rate, 2), currency
convert(100, rate=90.5) # (1.1, 'USD')
convert(amount=100, rate=90.5) # TypeError: amount inapitishwa kwa nafasi pekee
convert(100, 90.5) # TypeError: rate — kwa jina pekee
Vigezo vya jina pekee vinalinda dhidi ya kuchanganyikiwa katika miito kama convert(100, 90.5, "EUR"), ambapo haieleweki kipi ni kipi.
Upeo wa vigezo: kanuni ya LEGB
Python hutafuta jina la kigezo kwa mnyororo: Local (ndani ya kazi) → Enclosing (katika kazi ya nje) → Global (kwenye kiwango cha moduli) → Built-in (majina yaliyojengwa ndani kama len). Kusoma kigezo cha kimataifa ndani ya kazi kunaruhusiwa, lakini ili kukipa thamani mpya inahitajika tamko la global.
limit = 1000
def check(amount):
return amount > limit # kusoma kigezo cha kimataifa — kunaruhusiwa
def raise_limit():
global limit
limit = 2000 # bila global, ingeundwa kigezo cha ndani
Kwa vitendo, global ni bora kuepukwa: kazi inayobadilisha hali ya nje ni ngumu kupima. Ni bora kupokea thamani kama hoja na kurudisha matokeo.
Kazi zilizoingiana na funga (closures)
Kazi inaweza kutangazwa ndani ya kazi nyingine. Kazi iliyoingizwa huona vigezo vya nje hata baada ya ile ya nje kumaliza — hiyo ndiyo closure. Ili kubadilisha kigezo kama hicho hutumika nonlocal.
def make_counter():
count = 0
def counter():
nonlocal count
count += 1
return count
return counter
c = make_counter()
print(c(), c(), c()) # 1 2 3
Closures ndizo msingi wa decorators na viwanda vya kazi (function factories).
Kazi pia ni kitu
Katika Python kazi ni kitu cha kawaida: unaweza kuiweka kwenye kigezo, kuipitisha kwa kazi nyingine, kuirudisha kutoka kazini, au kuihifadhi kwenye kamusi. Ina sifa: __name__, __doc__, __defaults__, __annotations__.
def double(x):
return x * 2
f = double
print(f(5), f.__name__) # 10 double
print(list(map(double, [1, 2, 3]))) # [2, 4, 6]
Lambda katika Python: kazi zisizo na jina
Lambda ni kazi fupi isiyo na jina ambayo mwili wake ni usemi mmoja. Matokeo ya usemi hurudishwa moja kwa moja, na return haitumiki.
square = lambda x: x ** 2
print(square(4)) # 16
expenses = [("Kahawa", 250), ("Teksi", 600), ("Chakula", 450)]
expenses.sort(key=lambda e: e[1], reverse=True)
print(expenses) # [('Teksi', 600), ('Chakula', 450), ('Kahawa', 250)]
print(list(filter(lambda n: n % 2 == 0, range(10)))) # [0, 2, 4, 6, 8]
Lambda inafaa kama hoja fupi ya sorted, max, map, filter. Kuweka lambda kwenye kigezo, kama square hapo juu, PEP 8 haipendekezi: kazi ikihitaji jina, andika def — itakuwa na __name__ sahihi kwenye traceback na mahali pa docstring.
| def | lambda | |
|---|---|---|
| Jina | lipo | halipo (<lambda>) |
| Mwili | idadi yoyote ya amri | usemi mmoja |
| return | wazi | kimyakimya |
| Docstring, type hints | ndiyo | hapana |
| Inafaa wapi | kila mahali | key fupi au callback |
Type hints: vidokezo, si ukaguzi
Type hints zinaeleza aina zinazotarajiwa za vigezo na matokeo. Python yenyewe haizikagui wakati wa kuendesha: kazi yenye x: int itapokea mfuatano bila tatizo. Ukaguzi unafanywa na zana za nje — mypy, pyright, ty — na mhariri anayeonyesha kosa kabla ya kuendesha.
def add_expense(title: str, amount: float, category: str = "nyingine") -> dict[str, object]:
return {"title": title, "amount": amount, "category": category}
def area(w: float, h: float) -> float:
w * h # mypy: Missing return statement
Ukaguzi unaweza kuendeshwa bila kusakinisha kwa uvx mypy .. Mfano hapo juu unaonyesha faida ya type hints: return iliyosahauliwa kwa -> float inanaswa mara moja na kichambuzi.
Kuanzia Python 3.12 (PEP 695) kazi za jumla huandikwa bila TypeVar: kigezo cha aina kinaandikwa kwenye mabano ya mraba, na jina bandia la aina linatangazwa kwa neno type.
def first[T](xs: list[T]) -> T:
return xs[0]
type Money = int | float
Katika Python 3.14 (PEP 649) type hints zikawa za uvivu: zinakokotolewa wakati zinapotumika kwa mara ya kwanza, kwa hiyo unaweza kurejelea darasa lililotangazwa chini bila nukuu, na from __future__ import annotations haihitajiki tena.
"Hakupitishwa" au "amepitisha None": sentinel katika 3.15
Thamani None kama chaguo-msingi haiwezi kutofautisha "hoja haikupitishwa" na "None imepitishwa kwa makusudi". Kwa miaka watu walitatua hili kwa kiashiria cha kujitengenezea:
_MISSING = object()
def get_rate(currency, default=_MISSING):
rates = {"USD": 90.5}
if currency in rates:
return rates[currency]
if default is _MISSING:
raise KeyError(currency)
return default
Katika Python 3.15 kuna kazi iliyojengwa ndani sentinel (PEP 661): MISSING = sentinel("MISSING") huunda alama ya kipekee yenye repr inayoeleweka, ambayo wakati wa kunakili inabaki yenyewe, inahifadhiwa kwa pickle, na inafaa kwa type hint kama float | MISSING. Kwenye matoleo ya zamani mbinu ya object() inaendelea kufanya kazi.
Makosa ya kawaida na kazi
- Umesahau return — kazi inarudisha
None. - Umesahau mabano —
print(greet)itachapisha kitu cha kazi, si matokeo ya wito. - Thamani chaguo-msingi inayoweza kubadilika — orodha moja ya pamoja kwa miito yote.
- Idadi isiyo sahihi ya hoja —
TypeError: greet() missing 1 required positional argument: 'name'. - Jina sawa na kazi iliyojengwa ndani — kazi yako inayoitwa
listausumitaficha ile iliyojengwa ndani.
Hitimisho
Kazi katika Python zinatangazwa kwa def, zinarudisha matokeo kwa return, na zinapokea hoja kwa mpangilio au kwa jina. *args na **kwargs zinatoa unyumbufu, / na * zinatoa ukali wa wito, lambda ni fupi kwa kazi ya mara moja, na type hints pamoja na mypy zinanasa makosa kabla ya kuendesha. Katika kozi ya Python mada hii inafundishwa kwa vitendo: kifuatiliaji cha matumizi kinagawanywa kuwa kazi zenye type hints na kukaguliwa kwa mypy.
Maswali ya mara kwa mara
Kigezo kinatofautianaje na hoja?
Kigezo ni jina lililoandikwa kwenye tangazo la kazi, hoja ni thamani halisi inayopitishwa wakati wa wito. Katika def greet(name) name ni kigezo, na katika greet("Amina") mfuatano "Amina" ni hoja.
Je, naweza kuita kazi kabla ya kutangazwa?
Kwenye kiwango cha moduli hapana: mstari wa def lazima utekelezwe kabla ya wito, vinginevyo utapata NameError. Lakini ndani ya kazi nyingine unaweza kuita kazi iliyotangazwa chini, mradi wito utokee baada ya tangazo lake.
Kazi inaweza kurudisha thamani ngapi?
Kiufundi moja, lakini thamani hiyo inaweza kuwa tuple: return a, b inarudisha tuple ya vipengele viwili, ambayo hufunguliwa kama x, y = f().
Je, ni lazima kuandika type hints?
Hapana, Python inafanya kazi bila hizo. Lakini kwenye msimbo ambao watu wengine wanausoma, type hints zinarahisisha matengenezo na kuruhusu mypy au pyright kupata makosa kabla ya kuendesha.
Je, naweza kuandika if ndani ya lambda?
Unaweza kutumia usemi wa masharti tu: lambda x: "sawa" if x % 2 == 0 else "isiyo sawa". Amri, mizunguko na mgawo ndani ya lambda haviruhusiwi.
Mada hii inafundishwa kwa kina pamoja na mazoezi katika kozi “Python 3.15: от новичка до профи”.
Nenda kwenye kozi