Python-இல் செயல்பாடுகள்: def, return, வாதங்கள், *args மற்றும் **kwargs, lambda மற்றும் வகை குறிப்புகள்
Python-இல் செயல்பாடு என்பது def என்ற சொல்லால் அறிவிக்கப்படும், பெயருடன் கூடிய குறியீட்டுத் தொகுதி; அதை அடைப்புக்குறிகளுடன் பெயரால் அழைக்கலாம்; முடிவை return மூலம் திருப்பித் தரலாம். return இல்லையென்றால் செயல்பாடு None தரும். வாதங்கள் வரிசைப்படியோ பெயராலோ அனுப்பப்படும்; *args கூடுதல் நிலை மதிப்புகளை tuple-ஆகவும், **kwargs பெயரிட்ட மதிப்புகளை அகராதியாகவும் சேகரிக்கும்; lambda ஒரே வெளிப்பாட்டைக் கொண்ட குறுகிய பெயரில்லாச் செயல்பாடு.
Python-இல் செயல்பாடு என்பது பெயருடன் கூடிய குறியீட்டுத் துண்டு; அதை வெவ்வேறு உள்ளீடுகளுடன் எத்தனை முறையும் அழைக்கலாம். அது def சொல்லால் அறிவிக்கப்படும், அளவுருக்கள் மூலம் மதிப்புகளைப் பெறும், return மூலம் முடிவைத் தரும். நீண்ட நிரல் "சுவரை" தெளிவான, சரிபார்க்கக்கூடிய படிகளாக மாற்றுவதற்கான முக்கிய வழி இதுவே.
செயல்பாட்டை அறிவிப்பது: def
செயல்பாட்டு அறிவிப்பு def-உடன் தொடங்கும்; பின்னர் பெயர், அடைப்புக்குறிக்குள் அளவுருக்கள், பெருங்குடல். உடல் நான்கு இடைவெளி உள்தள்ளலில் எழுதப்படும் — Python-இல் உள்தள்ளல் அலங்காரம் அல்ல, தொடரியலின் ஒரு பகுதி.
def greet(name):
"""பயனருக்கான வாழ்த்தை திருப்பித் தருகிறது."""
return f"வணக்கம், {name}!"
print(greet("அன்னா")) # வணக்கம், அன்னா!
தலைப்புக்குப் பின் உடனே உள்ள மூன்று மேற்கோள்களிலான சரம் docstring — செயல்பாட்டின் ஆவணம். அதை help(greet) மற்றும் எடிட்டரின் குறிப்புகள் காட்டும். செயல்பாட்டுப் பெயர்கள் PEP 8 மரபின்படி snake_case-இல் எழுதப்படுகின்றன: add_expense, get_rate.
def greet(name): வரி செயல்பாட்டின் கையொப்பம் (signature) எனப்படும்: பெயரும் அளவுருப் பட்டியலும் (இருந்தால் annotations-உம்). கையொப்பத்திலிருந்தே உடலைப் பார்க்காமல் அதை எப்படி அழைப்பது என்று வாசகர் புரிந்துகொள்ளலாம்.
Python-இல் return என்ன செய்கிறது
return செயல்பாட்டை முடித்து, அதை அழைத்தவருக்கு மதிப்பைத் தரும். இயங்கிய return-க்குப் பின் உள்ள குறியீடு இயங்காது. return இல்லையென்றால், அல்லது மதிப்பு இல்லாமல் எழுதப்பட்டிருந்தால், செயல்பாடு None தரும்.
def area(w, h):
w * h # முடிவு கணக்கிடப்பட்டு வீணாகிறது
print(area(3, 4)) # None
def area(w, h):
return w * h
print(area(3, 4)) # 12
மறந்துபோன return தொடக்கநிலையாளரின் மிகப் பொதுவான தவறுகளில் ஒன்று: செயல்பாடு "வேலை செய்கிறது", ஆனால் None தருகிறது, பிழை அடுத்த வரியில் வெளிப்படுகிறது. பல மதிப்புகளையும் திருப்பித் தரலாம் — உண்மையில் அது ஒரு tuple; அதை எளிதாகப் பிரிக்கலாம்:
def min_max(numbers):
return min(numbers), max(numbers)
low, high = min_max([4, 1, 9])
print(low, high) # 1 9
ஆரம்பத்திலேயே return தருவது தேவையற்ற உள்ளமைவைத் தவிர்க்க உதவும்: முதலில் சிறப்பு நிலைகளைத் தள்ளிவிட்டு, பிறகு முக்கிய தர்க்கத்தை எழுதுங்கள்.
def discount(price, is_member):
if price <= 0:
return 0
if not is_member:
return price
return price * 0.9
Python செயல்பாட்டு வாதங்கள்: நிலை மற்றும் பெயரிட்டவை
அளவுருக்கள் என்பவை செயல்பாட்டு அறிவிப்பில் உள்ள பெயர்கள்; வாதங்கள் அழைக்கும்போது அனுப்பப்படும் மதிப்புகள். வாதங்களை வரிசைப்படி (நிலையாக) அல்லது பெயரால் (பெயரிட்டு) அனுப்பலாம். பெயரிட்ட வாதங்கள் அழைப்பை தானாக விளக்கமளிக்கும்படி ஆக்குகின்றன; வரிசை முக்கியமற்றதாகிறது.
def add_expense(title, amount, category="மற்றவை"):
return {"title": title, "amount": amount, "category": category}
add_expense("காபி", 250) # நிலையாக
add_expense(amount=250, title="காபி") # பெயரால்
add_expense("டாக்ஸி", 600, category="போக்குவரத்து") # கலந்து
இயல்பு மதிப்புள்ள அளவுரு கட்டாயமற்றது. விதிகள்: இயல்பு மதிப்புள்ள அளவுருக்கள் கட்டாயமானவற்றுக்குப் பின் வர வேண்டும்; அழைக்கும்போது நிலை வாதங்கள் பெயரிட்ட வாதங்களுக்கு முன் வர வேண்டும். இல்லையென்றால் Python SyntaxError தரும்.
பொறி: மாற்றக்கூடிய இயல்பு மதிப்பு
இயல்பு மதிப்பு ஒரே ஒருமுறை கணக்கிடப்படுகிறது — def வரி இயங்கும்போது, ஒவ்வொரு அழைப்பின்போதும் அல்ல. அது பட்டியலோ அகராதியோ என்றால் அது எல்லா அழைப்புகளுக்கும் பொதுவாக இருக்கும்.
def add_item(item, acc=[]):
acc.append(item)
return acc
print(add_item(1)) # [1]
print(add_item(2)) # [1, 2] — பட்டியல் முந்தைய அழைப்பை "நினைவில்" வைத்திருக்கிறது
சரியான வழி — இயல்பாக None வைத்து உள்ளே புதிய பொருளை உருவாக்குவது:
def add_item(item, acc=None):
if acc is None:
acc = []
acc.append(item)
return acc
*args மற்றும் **kwargs: எத்தனை வாதங்களும்
அளவுருவுக்கு முன் உள்ள ஒரு நட்சத்திரக்குறி கூடுதல் நிலை வாதங்களை tuple-ஆகவும், இரண்டு நட்சத்திரக்குறிகள் கூடுதல் பெயரிட்ட வாதங்களை அகராதியாகவும் (dict) சேகரிக்கும். args மற்றும் kwargs பெயர்கள் ஒரு மரபு மட்டுமே; முக்கியம் நட்சத்திரக்குறிகள்.
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("அன்னா", city="சென்னை", age=30))
# {'name': 'அன்னா', 'city': 'சென்னை', 'age': 30}
அதே நட்சத்திரக்குறிகள் எதிர்த்திசையிலும் வேலை செய்யும் — அழைக்கும்போது அவை வரிசையையோ அகராதியையோ வாதங்களாக விரிக்கும்:
values = [3, 4]
print(pow(*values)) # 81
opts = {"sep": " | ", "end": "\n"}
print("a", "b", **opts) # a | b
நிலை மட்டும் மற்றும் பெயர் மட்டும் அளவுருக்கள்
அளவுரு பட்டியலில் உள்ள சாய்வுக்கோடு / மற்றும் நட்சத்திரக்குறி * தடைகளைப் போல வேலை செய்கின்றன: /-க்கு முன் உள்ளவை வரிசைப்படி மட்டுமே அனுப்பப்படும் (தொடரியல் Python 3.8-இல் வந்தது, PEP 570); *-க்குப் பின் உள்ளவை பெயரால் மட்டுமே.
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 நிலையாக மட்டுமே அனுப்பப்படும்
convert(100, 90.5) # TypeError: rate — பெயரால் மட்டுமே
பெயர் மட்டும் அளவுருக்கள் convert(100, 90.5, "EUR") போன்ற அழைப்புகளிலுள்ள குழப்பத்தைத் தடுக்கின்றன — எது எது என்று தெளிவில்லாத அழைப்புகளை.
நோக்கப் பரப்பு (scope): LEGB விதி
Python ஒரு மாறியின் பெயரை இந்தச் சங்கிலியில் தேடும்: Local (செயல்பாட்டுக்குள்) → Enclosing (வெளிப்புறச் செயல்பாட்டில்) → Global (தொகுதி மட்டத்தில்) → Built-in (len போன்ற உள்ளமைவுப் பெயர்கள்). செயல்பாட்டுக்குள் உலகளாவிய மாறியைப் படிக்கலாம்; ஆனால் அதற்கு புதிய மதிப்பை ஒதுக்க global அறிவிப்பு வேண்டும்.
limit = 1000
def check(amount):
return amount > limit # உலகளாவிய மாறியைப் படித்தல் — சரி
def raise_limit():
global limit
limit = 2000 # global இல்லாமல் உள்ளூர் மாறி உருவாகியிருக்கும்
நடைமுறையில் global-ஐத் தவிர்ப்பது நல்லது: வெளிப்புற நிலையை மாற்றும் செயல்பாட்டைச் சோதிப்பது கடினம். மதிப்பை வாதமாகப் பெற்று முடிவைத் திருப்பித் தருவது நம்பகமானது.
உள்ளமை செயல்பாடுகளும் மூடல்களும் (closures)
ஒரு செயல்பாட்டுக்குள் இன்னொன்றை அறிவிக்கலாம். உள்ளமை செயல்பாடு வெளிப்புறச் செயல்பாடு முடிந்த பின்னும் அதன் மாறிகளைப் பார்க்கும் — இதுவே மூடல் (closure). அத்தகைய மாறியை மாற்ற 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
மூடல்கள் அலங்கரிப்பாளர்களுக்கும் (decorators) செயல்பாட்டுத் தொழிற்சாலைகளுக்கும் அடிப்படை.
செயல்பாடும் ஒரு பொருளே
Python-இல் செயல்பாடு ஒரு சாதாரணப் பொருள்: அதை ஒரு மாறியில் வைக்கலாம், மற்றொரு செயல்பாட்டுக்கு அனுப்பலாம், ஒரு செயல்பாட்டிலிருந்து திருப்பித் தரலாம், அகராதியில் சேமிக்கலாம். அதற்கு பண்புக்கூறுகள் உண்டு: __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]
Python lambda: பெயரில்லாத செயல்பாடுகள்
Lambda செயல்பாடு பெயரில்லாத குறுகிய செயல்பாடு; அதன் உடல் ஒரே வெளிப்பாடு. வெளிப்பாட்டின் முடிவு தானாகத் திருப்பித் தரப்படும்; return எழுதக்கூடாது.
square = lambda x: x ** 2
print(square(4)) # 16
expenses = [("காபி", 250), ("டாக்ஸி", 600), ("மதிய உணவு", 450)]
expenses.sort(key=lambda e: e[1], reverse=True)
print(expenses) # [('டாக்ஸி', 600), ('மதிய உணவு', 450), ('காபி', 250)]
print(list(filter(lambda n: n % 2 == 0, range(10)))) # [0, 2, 4, 6, 8]
Lambda செயல்பாடுகள் sorted, max, map, filter போன்றவற்றுக்கு குறுகிய வாதமாக பொருந்தும். மேலே square போல lambda-வை ஒரு மாறிக்கு ஒதுக்குவதை PEP 8 பரிந்துரைப்பதில்லை: செயல்பாட்டுக்குப் பெயர் வேண்டுமென்றால் def எழுதுங்கள் — அப்போது traceback-இல் சரியான __name__ இருக்கும், docstring-க்கும் இடம் கிடைக்கும்.
| def | lambda | |
|---|---|---|
| பெயர் | உண்டு | இல்லை (<lambda>) |
| உடல் | எத்தனை கட்டளைகளும் | ஒரே வெளிப்பாடு |
| return | வெளிப்படையானது | மறைமுகமானது |
| Docstring, annotations | உண்டு | இல்லை |
| எங்கே பொருந்தும் | எல்லா இடங்களிலும் | குறுகிய key அல்லது callback |
வகை குறிப்புகள் (annotations): குறிப்புகள், சோதனைகள் அல்ல
Annotations அளவுருக்களின் மற்றும் முடிவின் எதிர்பார்க்கப்படும் வகைகளை விவரிக்கின்றன. Python இயக்கும்போது அவற்றைச் சரிபார்ப்பதில்லை: x: int கொண்ட செயல்பாடு சரத்தையும் அமைதியாக ஏற்கும். அவற்றைச் சரிபார்ப்பது வெளிப்புறக் கருவிகள் — mypy, pyright, ty — மற்றும் இயக்குவதற்கு முன்பே பிழையைக் காட்டும் எடிட்டர்.
def add_expense(title: str, amount: float, category: str = "மற்றவை") -> dict[str, object]:
return {"title": title, "amount": amount, "category": category}
def area(w: float, h: float) -> float:
w * h # mypy: Missing return statement
நிறுவாமல் சரிபார்ப்பை uvx mypy . மூலம் இயக்கலாம். மேலே உள்ள எடுத்துக்காட்டு annotations-இன் பயனைக் காட்டுகிறது: -> float இருக்கும்போது மறந்த return-ஐ பகுப்பாய்வாளர் உடனே பிடிக்கும்.
Python 3.12 (PEP 695) முதல் பொதுவான (generic) செயல்பாடுகளை TypeVar இல்லாமல் எழுதலாம்: வகை அளவுரு சதுர அடைப்புக்குள் குறிக்கப்படும், வகைப் புனைப்பெயர் type சொல்லால் அறிவிக்கப்படும்.
def first[T](xs: list[T]) -> T:
return xs[0]
type Money = int | float
Python 3.14-இல் (PEP 649) annotations சோம்பேறியாக (lazy) மாறின: அவை முதல் பயன்பாட்டின்போது கணக்கிடப்படுகின்றன; அதனால் கீழே அறிவிக்கப்பட்ட வகுப்பை மேற்கோள் குறிகள் இல்லாமலே குறிப்பிடலாம், from __future__ import annotations இனி தேவையில்லை.
"கொடுக்கப்படவில்லை" அல்லது "None கொடுக்கப்பட்டது": Python 3.15-இல் sentinel
இயல்பாக None வைத்தால் "வாதம் கொடுக்கப்படவில்லை" என்பதையும் "வேண்டுமென்றே None கொடுக்கப்பட்டது" என்பதையும் பிரித்துப் பார்க்க முடியாது. பல ஆண்டுகளாக இதை சொந்தக் காவல் மதிப்பால் தீர்த்தனர்:
_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
Python 3.15-இல் sentinel என்ற உள்ளமைவுச் செயல்பாடு வந்தது (PEP 661): MISSING = sentinel("MISSING") தனித்துவமான குறியை உருவாக்கும்; அதற்குப் புரியும்படியான repr உண்டு, நகலெடுத்தாலும் அதே பொருளாக இருக்கும், pickle மூலம் தொடராக்கலாம், float | MISSING போன்ற annotation-களுக்கும் பொருந்தும். பழைய பதிப்புகளில் object() முறை தொடர்ந்து வேலை செய்யும்.
செயல்பாடுகளில் பொதுவான தவறுகள்
- return மறந்தது — செயல்பாடு
Noneதருகிறது. - அடைப்புக்குறிகள் மறந்தது —
print(greet)அழைப்பின் முடிவைக் காட்டாமல் செயல்பாட்டுப் பொருளைக் காட்டும். - மாற்றக்கூடிய இயல்பு மதிப்பு — எல்லா அழைப்புகளுக்கும் பொதுவான பட்டியல்.
- தவறான எண்ணிக்கை வாதங்கள் —
TypeError: greet() missing 1 required positional argument: 'name'. - உள்ளமைவுப் பெயருடன் மோதல் —
listஅல்லதுsumஎன்ற செயல்பாடு உள்ளமைவைத் தடுக்கும்.
சுருக்கம்
Python-இல் செயல்பாடுகள் def-ஆல் அறிவிக்கப்படுகின்றன, return-ஆல் முடிவைத் திருப்பித் தருகின்றன, வாதங்களை வரிசைப்படியோ பெயராலோ ஏற்கின்றன. *args மற்றும் **kwargs நெகிழ்வைத் தரும், / மற்றும் * அழைப்பின் கடுமையைத் தரும், lambda ஒருமுறை பயன்படும் செயல்பாட்டுக்குச் சுருக்கத்தைத் தரும், வகை annotations mypy-உடன் சேர்ந்து பிழைகளை இயக்கத்துக்கு முன்பே பிடிக்கும். Python பாடநெறியில் இதை நடைமுறையில் கற்பிக்கிறோம்: செலவு கண்காணிப்பான் annotations-உடன் கூடிய செயல்பாடுகளாகப் பிரிக்கப்பட்டு mypy மூலம் சரிபார்க்கப்படுகிறது.
அடிக்கடி கேட்கப்படும் கேள்விகள்
அளவுருவுக்கும் வாதத்துக்கும் என்ன வேறுபாடு?
அளவுரு என்பது செயல்பாட்டு அறிவிப்பில் உள்ள பெயர்; வாதம் அழைக்கும்போது கொடுக்கப்படும் குறிப்பிட்ட மதிப்பு. <code>def greet(name)</code>-இல் name அளவுரு; <code>greet("அன்னா")</code>-இல் "அன்னா" என்ற சரம் வாதம்.
செயல்பாட்டை அறிவிப்பதற்கு முன் அழைக்க முடியுமா?
தொகுதி மட்டத்தில் முடியாது: அழைப்புக்கு முன் <code>def</code> வரி இயங்கியிருக்க வேண்டும், இல்லையென்றால் NameError வரும். ஆனால் மற்றொரு செயல்பாட்டுக்குள், அறிவிப்புக்குப் பின்னால் நடக்கும் அழைப்பு சரி.
ஒரு செயல்பாடு எத்தனை மதிப்புகளைத் திருப்பித் தர முடியும்?
முறையாக ஒன்று; ஆனால் அந்த ஒன்று tuple ஆக இருக்கலாம்: <code>return a, b</code> இரண்டு உறுப்புகளின் tuple-ஐத் தருகிறது; அதை <code>x, y = f()</code> என்று பிரிக்கலாம்.
வகை annotations கட்டாயமா?
இல்லை, அவை இல்லாமலும் Python வேலை செய்யும். ஆனால் மற்றவர்கள் படிக்கும் குறியீட்டில் அவை பராமரிப்பை எளிதாக்கும்; mypy அல்லது pyright இயக்குவதற்கு முன்பே பிழைகளைக் கண்டறியும்.
lambda-வில் if பயன்படுத்தலாமா?
நிபந்தனை வெளிப்பாடு மட்டும் பயன்படுத்தலாம்: <code>lambda x: "இரட்டை" if x % 2 == 0 else "ஒற்றை"</code>. lambda-வுக்குள் கட்டளைகள், சுழல்கள், ஒதுக்கல்கள் அனுமதிக்கப்படுவதில்லை.
“Python 3.15: от новичка до профи” பாடநெறியில் இந்தத் தலைப்பு பயிற்சியுடன் விரிவாக விளக்கப்பட்டுள்ளது.
பாடநெறிக்குச் செல்