2012-12-12 3 views
5

からPythonは私がすべての素数の集合が(実際にmemoisedブルートフォースプライムテストを隠す)のように動作するふりコンテナを作成するために、次のコードを持っている無限集合

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] 

を選択を思わargparse

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

をしかし、それは​​とうまくプレイしていない:これまでの作業をする

>>> 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は、ちょうどすべての がサポートされているなど、カスタムコンテナ、オブジェクトを設定し、オペレータにサポート

任意のオブジェクトが選択 値なので、辞書オブジェクトとして渡すことができると言います。

明らかに、無限の「セット」の素数を反復することは望ましくありません。だからどうしてこんにちは​​私の素数mapしようとしている?それはちょうどinnot inを必要としませんか?

答えて

4

これはドキュメントのバグです。書かれたライブラリでは、choices引数はコンテナだけでなく反復可能でなければなりません。利用可能なオプションをリストアップしようとしますが、これはあなたのケースでは機能しません。 __iter__という偽の情報文字列を返すだけで、ハックしようとする可能性があります。

これはPythonバグトラッカーのバグとして提出することもできます。これは実際にはドキュメントによって矛盾しているためです。

+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) 

チェック自体は結構です。有用なエラーメッセージを表示しようとしています。ここでは、すべての可能な選択肢を提供しようとしています。文字列primesreprという文字列で返すようにイテレータを定義した場合、それをハックして正しいことを行う可能性があります。

1

choicesは、すべての許容値(有限(小)セット)を列挙できる引数です。ドキュメントについては、より明確にすべきです。

primesは無限大です。 typeパラメータを設定して、非素数に対するValueErrorを上げることができます。

関連する問題