2009-03-09 12 views
4

は、あなたがこのように価値があるとしましょう:Pythonで単一値と複数値の両方をカバーする単一の実装ですか?

のn = 5

などのように、それの階乗を返すメソッド:

階乗(5)

あなたはどのように扱いますか複数の値:

NUMSの= [1,2,3,4,5]

階乗(NUMS)

だから、これらすべての値の階乗をリストとして返します。

これを処理する最もクリーンな方法は2つの方法を記述することなくですか?これらの状況を処理するには、Pythonには良い方法がありますか?

+0

スカラーを使ったこととベクトルを使ったことのうちの1つを行ったような魔法の関数のユースケースについて、いくつかの背景を教えてください。 –

+0

単一の値がそれほど有用ではないように見えますが、SumやAverageなどの関数には適しています。このように使用できる多くの機能があります。 –

+0

いいえ、値が1つだけの場合は、この単一の値を含むリストを使用してください。オブジェクトが似たように振る舞う場合、異なる型を返すことは大丈夫です。しかし、これは限界をはるかに超えています。 –

答えて

7

これが時々行われている:あなたはFactorialの体はTypeErrorを上げることは決してありません確信している場合に

、それを簡略化することができました。

def factorial(*args): 
    def fact(n): 
     if n == 0: return 1 
     return n*fact(n-1) 
    return [ fact(a) for a in args ] 

これは、単純な値とシーケンスで動作するほぼ魔法の機能を提供します。

>>> factorial(5) 
[120] 
>>> factorial(5, 6, 7) 
[120, 720, 5040] 
>>> factorial(*[5, 6, 7]) 
[120, 720, 5040] 
+0

最もクリーンな答えはこれまでのところ... –

+0

入力が単純​​な数値であってもリストを返すので、良くありません。 –

+0

私は要件が何であるかについて完全には不明です。リストと個々の値を魔法のように「均一な」方法で扱う関数の考え方は混乱します。またはそれはAPL(またはJまたはK)です。 –

9

List comprehension

[fac(n) for n in nums] 

EDIT:

申し訳ありませんが、私は、あなたが両方の配列や単一の値を処理するメソッドをしたい誤解?なぜあなたが2つの方法でこれをしないのか想像できません。

def factorial(n): 
    # implement factorial here 
    return answer 

def factorial_list(nums): 
    return [factorial(n) for n in nums] 

これに代わる方法は、何らかの型チェックを行うことです。これは、非常に魅力的な理由がある場合を除いて避けてください。

EDIT 2:

MizardXの答えは優れている、1つに投票します。乾杯。

+0

実際、あなたの答えはもっと好きです。私はこれをひとつの関数として書いてみると、ずっと複雑なコードになると思います。 – daf

+0

まあ、私もそうです:Pしかし、MizardXは実際に私がしなかった彼の質問に答えました。 :) – bouvard

+0

ありがとう、どのようにPythonは、コレクションを使用するときに正しい関数を見つけるのですか? –

6

Pythonがメソッドのオーバーロードを実行できるかどうかを確認する場合は、次のようにします。したがって、そのような複数のメソッドを実行することは、メソッドを定義するむしろPython以外の方法です。また、大文字小文字を区別するための大文字小文字のクラス名、小文字の関数/メソッドの命名規則。

あなたはとにかく先に行きたい場合は、最も簡単な方法は、単にブランチを作るために次のようになります。

def Factorial(arg): 
    if getattr(arg, '__iter__', False): # checks if arg is iterable 
    return [Factorial(x) for x in arg] 
    else: 
    # ... 

それとも、あなたは空想感じているならば、あなたは任意の関数にこれを行いデコレータを作ることができます:

def autoMap(f): 
    def mapped(arg): 
     if getattr(arg, '__iter__', False): 
      return [mapped(x) for x in arg] 
     else: 
      return f(arg) 
    return mapped 

@autoMap 
def fact(x): 
    if x == 1 or x == 0: 
     return 1 
    else: 
     return fact(x-1) + fact(x-2) 

>>> fact(3) 
3 
>>> fact(4) 
5 
>>> fact(5) 
8 
>>> fact(6) 
13 
>>> fact([3,4,5,6]) 
[3, 5, 8, 13] 

よりPython的な方法は、可変引数の長さを使用することであるが:

def autoMap2(f): 
    def mapped(*arg): 
     if len(arg) != 1: 
      return [f(x) for x in arg] 
     else: 
      return f(arg[0]) 
    return mapped 

@autoMap2 
def fact(n): 
# ... 

>>> fact(3,4,5,6) 
[3, 5, 8, 13] 

Pディープマッピングデコレータに2つのウッティング・アム・アンマーゼー:それは反復可能なら

def autoDeepMap(f): 
    def mapped(*args): 
     if len(args) != 1: 
      return [mapped(x) for x in args] 
     elif getattr(args[0], '__iter__', False): 
      return [mapped(x) for x in args[0]] 
     else: 
      return f(args[0]) 
    return mapped 

@autoDeepMap 
def fact(n): 
# ... 

>>> fact(0) 
1 
>>> fact(0,1,2,3,4,5,6) 
[1, 1, 2, 3, 5, 8, 13] 
>>> fact([0,1,2,3,4,5,6]) 
[1, 1, 2, 3, 5, 8, 13] 
>>> fact([0,1,2],[3,4,5,6]) 
[[1, 1, 2], [3, 5, 8, 13]] 
>>> fact([0,1,2],[3,(4,5),6]) 
[[1, 1, 2], [3, [5, 8], 13]] 
+0

デコレータを再帰的にするには、argのxの[f(x)]を[argのxのmapped(x)]に変更します。 –

+0

MizardX:あなたは私の心を吹き飛ばした。いいアイデア:) –

+0

しかし、これはフィボナッチです... :) –

13
def Factorial(arg): 
    try: 
     it = iter(arg) 
    except TypeError: 
     pass 
    else: 
     return [Factorial(x) for x in it] 
    return math.factorial(arg) 

は、recursivly適用されます。それ以外の場合は、正常に処理してください

また、最後のreturnexceptブロックに移動することもできます。

def Factorial(arg): 
    try: 
     return [Factorial(x) for x in arg] 
    except TypeError: 
     return math.factorial(arg) 
+0

getattr(obj、 '__iter__'、False)は、 'obj'がtry/except(遅いかもしれない)なしでiterableであるかどうかをチェックする方法です。 –

+0

@Andrey Fedorov:ほとんどの場合、try/exceptは実際にはより高速です。 –

+0

@MizardX: 'Factorial'のボディがあなたの前にあります。したがって、 'arg'が反復可能でないときに、' TypeError' *が生成されることを確実にすることができます。上記の2つのバージョンのFactorialは同じことをしますが、より単純です。 – jfs

3

それとも、リスト内包構文を好きで、新しいメソッドを持つスキップしたくない場合:

def factorial(num): 
    if num == 0: 
     return 1 
    elif num > 0: 
     return num * factorial(num - 1) 
    else: 
     raise Exception("Negative num has no factorial.") 

nums = [1, 2, 3, 4, 5] 
# [1, 2, 3, 4, 5] 

map(factorial, nums) 
# [1, 2, 6, 24, 120, 720] 
3

あなたがnumpyの/ scipyのダウンロードのvectorizeを見てみたいことがあります。 numpyの世界では

は、あなたが最後のケースは、生ではなく、単一要素のnumpyの配列を返すことに注意してくださいものの

vFactorial=np.vectorize(Factorial) 
    vFactorial([1,2,3,4,5]) 
    vFactorial(6) 

のようなものにしてくださいあなたの単一のint-argの階乗機能、 を与えられましたint。

関連する問題