पायथन गलत संख्या वाले तर्कों के साथ फ़ंक्शन कॉल की अनुमति क्यों देता है?


80

पायथन मेरी पहली गतिशील भाषा है। मैंने हाल ही में एक फ़ंक्शन कॉल को गलत तरीके से गलत संख्या में तर्कों की आपूर्ति करने के लिए कोडित किया। यह उस समय अपवाद के साथ विफल हुआ जब फ़ंक्शन को बुलाया गया था। मुझे उम्मीद थी कि एक गतिशील भाषा में भी, स्रोत फ़ाइल के पार्स होने पर इस तरह की त्रुटि का पता लगाया जा सकता है।

मैं समझता हूं कि वास्तविक तर्कों के प्रकार को तब तक नहीं जाना जाता है जब तक कि फ़ंक्शन को नहीं कहा जाता है, क्योंकि एक ही चर में अलग-अलग समय में किसी भी प्रकार के मूल्य हो सकते हैं। लेकिन वो जैसे ही स्रोत फ़ाइल पार्स की जाती है, तर्कों संख्या ज्ञात हो जाती है। जब प्रोग्राम चल रहा है तो यह बदलने वाला नहीं है।

ताकि यह एक दार्शनिक सवाल न हो

इसे स्टैक ओवरफ्लो के दायरे में रखने के लिए, मुझे इस तरह से प्रश्न को वाक्यांश देना चाहिए। क्या कोई विशेषता है, जो पायथन की पेशकश करता है, जिससे उसे फ़ंक्शन कॉल में तर्कों की संख्या की जांच करने में देरी होती है जब तक कि कोड वास्तव में निष्पादित नहीं होता है?


17
क्या होगा अगर नाम पूरी तरह से रनटाइम पर एक अलग फ़ंक्शन को संदर्भित करता है?
जोंशरपे

खैर, एक प्रतिवाद के रूप में, आह्वान के लिए तर्कों की गिनती को f(*args)पार्सिंग चरण के दौरान नहीं जाना जाएगा।
औकाज़ रोजाल्स्की

3
यह ध्यान दिया जाना चाहिए कि, प्रकार के सिद्धांत में, कार्यों के मामले में मूल्यों के प्रकार में तर्कों की संख्या शामिल है।
PyRulez

9
जब तक आप वास्तव में इसे कॉल करने का प्रयास नहीं करेंगे, तब पायथन को कैसे पता चलेगा कि आप किस फ़ंक्शन को कॉल करने जा रहे हैं? ऐसा नहीं है कि पायथन में कार्यों के नाम हैं। (यह व्यंग्य नहीं है)
user253751

1
@ मिनीबिस: ठीक है, नहीं। उनके नाम हैं। वे विशेष रूप से उन नामों से जुड़े नहीं हैं , यद्यपि। एक समारोह के रूप में परिभाषित def foo(): whateverकिया गया है foo.__name__ == 'foo', लेकिन वह ऐसा करने से आप बंद नहीं होगा foo = some_other_functionया bar = foo
user2357112

जवाबों:


146

अजगर को पता नहीं चल सकता है कि आप किस वस्तु को कॉलिंग समाप्त करेंगे, क्योंकि गतिशील होने के कारण, आप फ़ंक्शन ऑब्जेक्ट को स्वैप कर सकते हैं । किसी भी समय। और इनमें से प्रत्येक ऑब्जेक्ट में अलग-अलग तर्क हो सकते हैं।

यहाँ एक चरम उदाहरण है:

import random

def foo(): pass
def bar(arg1): pass
def baz(arg1, arg2): pass

the_function = random.choice([foo, bar, baz])
print(the_function())

उपरोक्त कोड में अपवाद को बढ़ाने के लिए 2 से 3 मौका है। लेकिन पायथन को इस बारे में कोई जानकारी नहीं है कि प्राथमिकता होगी या नहीं!

और मैंने डायनेमिक मॉड्यूल इंपोर्ट, डायनामिक फंक्शन जेनरेशन, अन्य __call__कॉल करने योग्य ऑब्जेक्ट्स ( विधि के साथ कोई भी ऑब्जेक्ट कहा जा सकता है), या कैच-ऑल तर्क ( *argsऔर **kwargs) के साथ भी शुरू नहीं किया है।

लेकिन इस अतिरिक्त को स्पष्ट करने के लिए, आप अपने प्रश्न का विवरण दें:

जब प्रोग्राम चल रहा है तो यह बदलने वाला नहीं है।

यह ऐसा नहीं है, पायथन में नहीं, एक बार मॉड्यूल लोड होने के बाद आप फ़ंक्शन ऑब्जेक्ट्स सहित मॉड्यूल नेमस्पेस में किसी भी ऑब्जेक्ट को हटा, जोड़ या बदल सकते हैं।


मैंने फंक्शन टेबल को पहले देखा है, इसलिए यह काफी बुरा नहीं हो सकता है । ओह रुको, तालिका में कार्य *तर्कों का उपयोग नहीं करते .... और यह अजगर है .... हां, बहुत चरम।
रे तोल

3
अब यह एक टी-शर्ट है। (यदि आप पता नहीं लगा सकते हैं कि
अटेंशन

@PyRulez: regex-parsing पोस्ट की यूनिकॉर्न-आकार की प्रति के साथ मेरी टी-शर्ट एक URL का उपयोग करती है। आप बस जोड़ सकते हैं https://stackoverflow.com/a/34567789और इसके साथ किया जा सकता है।
मार्टिन पीटर्स

4
@PyRulez: लेकिन यह वास्तव में एक प्रेषण सूची है। बिंदु उदहारण देते हैं कि आप वस्तुओं के रूप में कार्य करता है का उपयोग कर सकते है, और आप-सामने जो एक कहा जाता है पता नहीं कर सकते हैं। अन्यथा यह एक सामान्य तकनीक है
मार्टिन पीटर्स

हो सकता है कि उपयोगकर्ता को इसकी मूल समस्या में मदद करने के लिए: कोड के चलने से पहले गलती का पता लगाना, स्थैतिक सत्यापन उपकरण के उपयोग का उल्लेख किया जा सकता है।
ज़ेवियर कॉम्बेल

35

पारित किए जाने वाले तर्कों की संख्या ज्ञात है, लेकिन फ़ंक्शन नहीं जिसे वास्तव में कहा जाता है। इस उदाहरण को देखें:

def foo():
    print("I take no arguments.")

def bar():
    print("I call foo")
    foo()

यह स्पष्ट लग सकता है, लेकिन हमें "fubar.py" नामक एक फ़ाइल में डाल दें। अब, एक इंटरैक्टिव पायथन सत्र में, यह करें:

>>> import fubar
>>> fubar.foo()
I take no arguments.
>>> fubar.bar()
I call foo
I take no arguments.

यह स्पष्ट था। अब मज़ेदार हिस्से के लिए। हम एक ऐसे फ़ंक्शन को परिभाषित करेंगे जिसमें गैर-शून्य राशि के तर्क की आवश्यकता होती है:

>>> def notfoo(a):
...    print("I take arguments!")
...

अब हम कुछ ऐसा करते हैं जिसे मंकी पैचिंग कहा जाता है । हम वास्तव में मॉड्यूल में फ़ंक्शन को बदल सकते हैं :foofubar

>>> fubar.foo = notfoo

अब, जब हम बुलाएंगे bar, एक TypeErrorउठाया जाएगा; नाम fooअब उस फ़ंक्शन को संदर्भित करता है जिसे हमने मूल फ़ंक्शन के बजाय पूर्व-ज्ञात- के रूप में परिभाषित किया था foo

>>> fubar.bar()
I call foo
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/horazont/tmp/fubar.py", line 6, in bar
    foo()
TypeError: notfoo() missing 1 required positional argument: 'a'

तो इस तरह की स्थिति में भी, जहाँ यह बहुत स्पष्ट प्रतीत हो सकता है कि बुलाया फ़ंक्शन fooकोई तर्क नहीं लेता है, पायथन केवल यह जान सकता है कि यह वास्तव में fooफ़ंक्शन है जिसे तब बुलाया जा रहा है जब वह उस स्रोत लाइन को निष्पादित करता है।

यह पायथन की एक संपत्ति है जो इसे शक्तिशाली बनाता है, लेकिन यह इसके कुछ सुस्ती का कारण भी बनता है। वास्तव में, मॉड्यूल को केवल कुछ समय पहले अजगर-विचारों की मेलिंग सूची पर प्रदर्शन में सुधार के लिए रीड-ओनली बनाया गया है, लेकिन इससे कोई वास्तविक समर्थन नहीं मिला।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.