2011-05-31 21 views
7

मैं एक समारोह है कि तर्क के रूप में एक और समारोह या विधि लेता में argspec उपयोग कर रहा हूँ में कोई नहीं की तरह कस्टम प्लेसहोल्डर, और रिटर्न इस तरह एक टपल:अजगर

(("arg1", obj1), ("arg2", obj2), ...) 

इसका मतलब है कि पारित कर दिया करने के लिए पहला तर्क फ़ंक्शन arg1 है और इसका obj1 का डिफ़ॉल्ट मान है, और इसी तरह।

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

class MetaNoDefault(type): 
    def __repr__(cls): 
     return cls.__name__ 
    __str__ = __repr__ 

class NoDefault(object): 
    __metaclass__ = MetaNoDefault 

अब ("arg1", NoDefault) इंगित करता है ARG1 कोई डिफ़ॉल्ट मान है, और मैं कर सकते हैं if obj1 is NoDefault: आदि जैसे मेटाक्लास इसे <class '__main__.NoDefault'> के बजाय NoDefault के रूप में प्रिंट करता है।

क्या ऐसा कोई कारण नहीं है? क्या कोई बेहतर समाधान है?

+0

क्या कोई कारण है कि आप किसी भी डिफ़ॉल्ट के लिए केवल एक तत्व के tuple नहीं हो सकता है? कुछ ऐसा: '((" arg1 ",), (" arg2 ", obj2), ...) 'जहां" arg1 "में कोई डिफ़ॉल्ट नहीं है। आप तब कर सकते हैं यदि 'len (the_tuple) == 1' आदि – Fenikso

+2

@FMc: डिफ़ॉल्ट तर्कों के आकस्मिक संशोधन से आने वाली गलतियों से बचने के लिए, म्यूटेबल डिफ़ॉल्ट का कभी भी उपयोग करना बेहतर नहीं है। – lunaryorn

+0

@ फेनिक्सो मैंने अपने प्रश्न में इस संभावना को शामिल किया है। संक्षेप में, मुझे यह सुरुचिपूर्ण लगता है, भले ही यह _is_ सहज ज्ञान युक्त है। –

उत्तर

5

मेरा पसंदीदा प्रहरी Ellipsis है, और अगर मैं अपने आप को quote हो सकता है:

यह वहाँ है, यह एक वस्तु है, यह एक सिंगलटन है, और उसका नाम "की कमी" का अर्थ है, और यह overused कोई भी नहीं है (जिसे सामान्य डेटा प्रवाह के हिस्से के रूप में एक कतार में रखा जा सकता है)। YMMV।

+1

हालांकि, यह पायथन 3 में गायब हो रहा है: -o – Keith

+3

@ केथ: उद्धरण, कृपया। पायथन 3 में AFAIK आप 'ए = ...' कह सकते हैं (यानी '...' वाक्यविन्यास स्लाइस के बाहर इस्तेमाल किया जा सकता है), इसलिए मुझे लगता है कि यह गायब नहीं हो रहा है। – tzot

+0

ऐसा लगता है कि मैं खुद को [यहां तक ​​कि पहले] से उद्धृत कर सकता हूं (http://mail.python.org/pipermail/python-list/2004- अगस्त/273139.html) :) – tzot

3

ऐसे उद्देश्यों के लिए ऐसी प्रेषित वस्तुओं का उपयोग न करने का कोई कारण नहीं है। एक वर्ग वस्तु के लिए एक विकल्प के रूप में, आप भी एक डायनामिक रूप से तैयार प्रकार का एक सिंगलटन उदाहरण बना सकते हैं:

NoDefault = type('NoDefault', (object,), { 
    '__str__': lambda s: 'NoDefault', '__repr__': lambda s: 'NoDefault'})() 
4

मैं कुछ समय पहले एक ऐसी ही स्थिति थी। यहां मैं क्या आया था।

# Works like None, but is also a no-op callable and empty iterable. 
class NULLType(type): 
    def __new__(cls, name, bases, dct): 
     return type.__new__(cls, name, bases, dct) 
    def __init__(cls, name, bases, dct): 
     super(NULLType, cls).__init__(name, bases, dct) 
    def __str__(self): 
     return "" 
    def __repr__(self): 
     return "NULL" 
    def __nonzero__(self): 
     return False 
    def __len__(self): 
     return 0 
    def __call__(self, *args, **kwargs): 
     return None 
    def __contains__(self, item): 
     return False 
    def __iter__(self): 
     return self 
    def next(*args): 
     raise StopIteration 
NULL = NULLType("NULL", (type,), {}) 

यह एक शून्य कॉल करने योग्य और अनुक्रम के रूप में भी कार्य कर सकता है।