12

これはおそらく非常に率直な質問ですが、その理由を簡単に説明していただけませんか?

以下のコードでは、ランダム カードを取得するためにリストが必要です。

 import random
 card = random.choice (["hearts", "clubs", "frogs"])

なぜリストが必要なのか、なぜこれができないのか、私は困惑しています。

import = random
card = random.choice("hearts" , "clubs", "frogs")

できないのはいいのですが、理由を知りたいだけですか?

4

7 に答える 7

31

マーフィーの法則により、間違った方法で実行できるものは、いつの日か誰かによって間違った方法で実行されます。提案された API が必要です

random.choice(*lst)

選択する値がリスト (または他の順序) にある場合lst。誰かが書くとき

random.choice(lst)

lst代わりに、例外ではなく常に返されます。「明示的は暗黙的よりも優れている」という Python の原則により、いくつかの余分な文字を入力する必要があります。

(確かに、他のrandom.choice("foobar")人が指摘した結果は、初心者には驚くかもしれませんが、言語に慣れると、その仕組みに感謝するでしょう。)

于 2013-06-11T15:14:50.017 に答える
8

random.choice問題は、3 つの要素を持つ単一のパラメーターではなく、3 つのパラメーターで呼び出していることです。random.choice(('one', 'two', 'three'))たとえば試してみてください。

長さと適切な(インデックス付けに)任意のシーケンスが実行されます-要素を選択するため__getitem__に0との間の数値が選択されるためです。len(something)

そのため、必要に応じて代わりにタプルを使用できます。

于 2013-06-11T15:13:06.710 に答える
7

なぜなら、最初のスニペット

["hearts","clubs","frogs"]

関数に 1 つの引数のみを送信します (リスト)

2 つ目は 3 つの文字列を関数に送信します。この関数choiceは、単一の引数のみを取るように装備されています。したがって、値を返すためにランダムなインデックスを選択できるように、リストまたはインデックス付けできるものとして送信する必要があります

于 2013-06-11T15:14:06.607 に答える
5

random.choiceインデックス作成をサポートする任意のシーケンスで機能します。

>>> random.choice("foobar")              #string
'o'
>>> random.choice(("foo","bar","spam"))  #tuple
'spam' 
>>> random.choice(["foo","bar","spam"])  #list
'spam'

セットでは機能しません:

>>> random.choice({"foo","bar","spam"})
Traceback (most recent call last):
  File "<ipython-input-313-e97c3088a7ef>", line 1, in <module>
    random.choice({"foo","bar","spam"})
  File "/usr/lib/python2.7/random.py", line 274, in choice
    return seq[int(self.random() * len(seq))]  # raises IndexError if seq is empty
TypeError: 'set' object does not support indexing

ではrandom.choice("hearts" , "clubs", "frogs")、実際には に 3 つの引数を渡しましたがchoice、 は 1 つのパラメーターのみをrandom.choice想定しており、それもインデックス作成をサポートする必要があります。

しかしrandom.choice、dict に数値キー (0 から len(dict)-1 の間) がある場合、dict で機能します。内部的には次のようになります。

dic[int(random() * len(seq))] 

例:

>>> dic = dict(zip([1, 2, 3, 4, 5, 6], "abcdef"))
>>> random.choice(dic)
'b'
>>> random.choice(dic)
'd'
>>> random.choice(dic)
'd'
>>> random.choice(dic)    #fails as 0 was not found in dic
Traceback (most recent call last): 
  File "<ipython-input-366-5cfa0e5f2911>", line 1, in <module>
    random.choice(dic)
  File "/usr/lib/python2.7/random.py", line 274, in choice
    return seq[int(self.random() * len(seq))]  # raises IndexError if seq is empty
KeyError: 0
于 2013-06-11T15:13:52.237 に答える
4

random.choiceがそのまま実装されている理由と、それが実際にあなたがおそらく望むものである理由について、上記のいくつかの良い答えがあります。

任意の数の引数で Choice を呼び出せるようにしたい場合は、自分で簡単にラップできます。

import random

def random_choice_of_arbitrary_args(*args):
    return random.choice(args)

もちろん、おそらくもっと簡潔な名前を付けるでしょう。

これには、次の驚くべき動作があります。

>>> random_choice_of_arbitrary_args([1, 2, 3])
[1, 2, 3]

これは、最終的に random.choice に、1 つの要素を持つシーケンスのランダムな要素を与えるように指示しているためです。したがって、より良い実装は次のようになります。

import random

def my_choice(*args):
    if len(args) == 1:
        return random.choice(args[0])
    else:
        return random.choice(args)
于 2013-06-11T15:21:46.090 に答える
2

実装を見てください。から乱数0 to len(input_sequence)を選択し、そのインデックスを使用してランダムな項目を選択します。

ドキュメントには、入力はシーケンスでなければならないと書かれているため、おそらくより良い答えです。

于 2013-06-11T15:13:43.820 に答える
0

簡単に言えば、それはrandom.choice関数が定義された方法ではないからです。私の推測では、反復可能な引数を 1 つ受け入れる方が、可変数の任意の引数を受け入れるよりもクリーンな方法であるという理由だけで、この決定が下されたのだと思います。

したがって、次のように関数を定義します。

# This is (approximately) how it's actually written
def choice(iterable):
    #choose from iterable

これよりもきれいです:

# This is kind of ugly
def choice(*args):
    #make sure *args exists, choose from among them.

実際に記述されている方法では、任意の種類の 1 つの反復可能なアイテムを渡すことができます。これは、クリーンで便利です。2 番目の方法で定義されていると、使用時に簡単に台無しにrandom.choice([1, 2, 3])なります[1, 2, 3]

于 2013-06-11T15:14:31.507 に答える