2012-12-12 48 views
5

मैं एक कंटेनर जो सभी रूढ़ अंक (वास्तव में एक memoised जानवर बल प्रधानमंत्री परीक्षण खाल)अजगर एक अनंत सेट से विकल्पों argparse

import math 

def is_prime(n): 
    if n == 2 or n == 3: 
     return True 
    if n == 1 or n % 2 == 0: 
     return False 
    else: 
     return all(n % i for i in xrange(3, int(1 + math.sqrt(n)), 2)) 


class Primes(object): 

    def __init__(self): 
     self.memo = {} 

    def __contains__(self, n): 
     if n not in self.memo: 
      self.memo[n] = is_prime(n) 
     return self.memo[n] 

यही लगता है के सेट की तरह व्यवहार का दिखावा बनाने के लिए निम्नलिखित कोड है अब तक काम करने:

>>> primes = Primes() 
>>> 7 in primes 
True 
>>> 104729 in primes 
True 
>>> 100 in primes 
False 
>>> 100 not in primes 
True 

लेकिन यह अच्छी तरह से argparse के साथ खेल नहीं है:

>>> import argparse as ap 
>>> parser = ap.ArgumentParser() 
>>> parser.add_argument('prime', type=int, choices=primes, metavar='p') 
_StoreAction(option_strings=[], dest='prime', nargs=None, const=None, default=None, type=<type 'int'>, choices=<__main__.Primes object at 0x7f4e21783f10>, help=None, metavar='p') 
>>> parser.parse_args(['7']) 
Namespace(prime=7) 
>>> parser.parse_args(['11']) 
Namespace(prime=11) 
>>> parser.parse_args(['12']) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/usr/lib/python2.7/argparse.py", line 1688, in parse_args 
    args, argv = self.parse_known_args(args, namespace) 
    File "/usr/lib/python2.7/argparse.py", line 1720, in parse_known_args 
    namespace, args = self._parse_known_args(args, namespace) 
    File "/usr/lib/python2.7/argparse.py", line 1929, in _parse_known_args 
    stop_index = consume_positionals(start_index) 
    File "/usr/lib/python2.7/argparse.py", line 1885, in consume_positionals 
    take_action(action, args) 
    File "/usr/lib/python2.7/argparse.py", line 1778, in take_action 
    argument_values = self._get_values(action, argument_strings) 
    File "/usr/lib/python2.7/argparse.py", line 2219, in _get_values 
    self._check_value(action, value) 
    File "/usr/lib/python2.7/argparse.py", line 2267, in _check_value 
    tup = value, ', '.join(map(repr, action.choices)) 
TypeError: argument 2 to map() must support iteration 

docs सिर्फ इतना कहना है कि

किसी भी वस्तु का समर्थन करता है कि ऑपरेटर में विकल्प के रूप में पारित किया जा सकता मूल्य, इसलिए dict वस्तुओं, सेट वस्तुओं, कस्टम कंटेनर, आदि सभी समर्थित हैं।

स्पष्ट रूप से मैं प्राइम के अनंत "सेट" को फिर से शुरू नहीं करना चाहता हूं। तो क्यों बिल्ली argparsemap मेरी primes की कोशिश कर रहा है? क्या इसे सिर्फ in और not in की आवश्यकता नहीं है?

उत्तर

4

ऐसा प्रलेखन बग प्रतीत होता है। लिखित पुस्तकालय को choices तर्क केवल एक कंटेनर न होने की आवश्यकता है, लेकिन यह भी उपलब्ध है, यह उपलब्ध विकल्पों को सूचीबद्ध करने का प्रयास करता है, जो आपके मामले के लिए काम नहीं करेगा। आप इसे नकली __iter__ देकर इसे हैक करने का प्रयास कर सकते हैं जो कुछ जानकारीत्मक स्ट्रिंग देता है।

आप इसे पायथन बग ट्रैकर में भी एक बग के रूप में सबमिट करना चाहते हैं, क्योंकि व्यवहार वास्तव में दस्तावेज़ों द्वारा विरोधाभास है।

+0

धन्यवाद, मैंने एक मुद्दा बनाया है जैसा आपने सुझाव दिया [यहां] (http://bugs.python.org/issue16697)। – wim

5

स्रोत जहां अपवाद हो रही है बहुत स्पष्ट है, यह बाहर की जाँच:

if action.choices is not None and value not in action.choices: 
    tup = value, ', '.join(map(repr, action.choices)) 
    msg = _('invalid choice: %r (choose from %s)') % tup 
    raise ArgumentError(action, msg) 

जांच में ही ठीक है। यह एक उपयोगी त्रुटि संदेश मुद्रित करने का प्रयास करने पर बोर्क करता है, जहां यह आपको सभी संभावित विकल्प देने की कोशिश कर रहा है। मुझे लगता है कि अगर आप इसे repr स्ट्रिंग primes के रूप में कुछ ऐसा करने के लिए पुनरावर्तक को परिभाषित करते हैं, तो आप इसे सही चीज़ करने के लिए हैक कर सकते हैं।

1

choices तर्क के लिए हैं कि आप सभी अनुमत मानों (एक सीमित (छोटा) सेट) का आकलन कर सकते हैं। दस्तावेज़ इसके बारे में और अधिक स्पष्ट होना चाहिए।

primes एक अनंत सेट है। गैर-प्राइम्स के लिए ValueError बढ़ाने के लिए आप type पैरामीटर सेट कर सकते हैं।