web-dev-qa-db-ja.com

Pythonでx [x <2] = 0はどういう意味ですか?

私は次のような行でいくつかのコードに出会いました

x[x<2]=0

バリエーションをいじってみても、この構文が何をするのか、私はまだ固執しています。

例:

>>> x = [1,2,3,4,5]
>>> x[x<2]
1
>>> x[x<3]
1
>>> x[x>2]
2
>>> x[x<2]=0
>>> x
[0, 2, 3, 4, 5]
83
aberger

これは、NumPy arraysでのみ意味があります。リストの動作は役に立たず、Python 2(Python 3ではない)に固有です。元のオブジェクトが本当にリストではなくNumPy配列(以下を参照)。

ただし、ここのコードでは、xは単純なリストです。

以来

x < 2

false、つまり0

x[x<2]x[0]

x[0]が変更されます。

逆に、x[x>2]x[True] または x[1]

そう、 x[1]が変更されます。

なぜこれが起こるのですか?

比較の規則は次のとおりです。

  1. 2つの文字列または2つの数値タイプを注文する場合、注文は予想どおりに行われます(文字列の辞書順、整数の数値順)。

  2. 数値型と非数値型を注文すると、数値型が最初に来ます。

  3. どちらも数値ではない2つの互換性のない型を注文すると、それらは型名のアルファベット順に並べられます。

したがって、次の順序があります

数値<リスト<文字列<タプル

How does Python Compare string and int?の受け入れられた答えを参照してください。

xがNumPy配列の場合、構文はboolean配列のインデックス付けにより意味をなします。その場合、x < 2はブール値ではありません。 xの各要素が2未満かどうかを表すブール値の配列です。x[x < 2] = 0は、xの2未満の要素を選択し、それらのセルを0に設定します。Indexingを参照してください。

>>> x = np.array([1., -1., -2., 3])
>>> x < 0
array([False,  True,  True, False], dtype=bool)
>>> x[x < 0] += 20   # All elements < 0 get increased by 20
>>> x
array([  1.,  19.,  18.,   3.]) # Only elements < 0 are affected
117
trans1st0r
>>> x = [1,2,3,4,5]
>>> x<2
False
>>> x[False]
1
>>> x[True]
2

Boolは単純に整数に変換されます。インデックスは0または1です。

45
Karoly Horvath

あなたの質問の元のコードはPython2.でのみ機能します。xがPython2のlistである場合、比較x < yFalseyegerである場合____intです。これは、リストと整数を比較する意味がないためです。ただし、Python2では、オペランドが比較可能でない場合、CPythonでは 型の名前のアルファベット順 ;に基づいて比較が行われます。さらに、混合型の比較では、すべての数値が最初になります。これはCPython 2のドキュメントでは詳しく説明されておらず、異なるPython2実装では異なる結果が得られる可能性があります。 [1, 2, 3, 4, 5] < 2は数値であり、CPythonのFalseよりも「小さい」ため、2listと評価されます。この混合比較は、最終的には 機能があいまいすぎると見なされる であり、Python3.0で削除されました。


現在、<の結果はboolです。そして boolサブクラスint

>>> isinstance(False, int)
True
>>> isinstance(True, int)
True
>>> False == 0
True
>>> True == 1
True
>>> False + 5
5
>>> True + 5
6

したがって、基本的には、比較が真か偽かに応じて要素0または1を使用します。


Python3で上記のコードを試すと、 Python3. の変更によりTypeError: unorderable types: list() < int()が得られます:

順序の比較

Python 3.0は、比較の順序付けの規則を簡素化しました。

順序比較演算子(<<=>=>)は、オペランドに意味のある自然な順序がない場合にTypeError例外を発生させます。したがって、1 < ''0 > None、またはlen <= lenのような式は無効になります。 None < Noneは、TypeErrorを返す代わりにFalseを発生させます。当然の結果として、異種リストのソートは意味をなさないようになりました。すべての要素が互いに比較可能でなければなりません。これは==および!=演算子には適用されないことに注意してください。異なる比較不能な型のオブジェクトは、常に互いに等しくないものを比較します。


オーバーロード何かをするための比較演算子different(pandasのデータフレーム、numpyの配列)の多くのデータ型があります。使用しているコードが何か他のことをした場合、それはxlistではないであったが、演算子<を持つ他のクラスのインスタンスがオーバーライドされてboolではない値を返したためです。そして、この値はx[](別名__getitem__/__setitem__)によって特別に処理されました

14
Antti Haapala

これにはもう1つの用途があります。コードゴルフです。コードゴルフは、可能な限り少ないソースコードバイトで問題を解決するプログラムを作成する技術です。

return(a,b)[c<d]

とほぼ同等です

if c < d:
    return b
else:
    return a

ただし、aとbは両方とも最初のバージョンでは評価されますが、2番目のバージョンでは評価されません。

c<dTrueまたはFalseに評価されます。
(a, b)はタプルです。
タプルのインデックス作成は、リストのインデックス作成と同様に機能します:(3,5)[1] == 5
True1と等しく、False0と等しくなります。

  1. (a,b)[c<d]
  2. (a,b)[True]
  3. (a,b)[1]
  4. b

またはFalseの場合:

  1. (a,b)[c<d]
  2. (a,b)[False]
  3. (a,b)[0]
  4. a

スタック交換ネットワークには、数バイトを節約するためにpythonにできる多くの厄介なことの良いリストがあります。 https://codegolf.stackexchange.com/questions/54/tips-for-golfing-in-python

通常のコードではこれは決して使用すべきではありませんが、あなたの場合、xは整数と比較できるものとして、またスライスをサポートするコンテナーとして機能することを意味します。これは非常に珍しい組み合わせです。他の人が指摘しているように、おそらくNumpyのコードでしょう。

9
Filip Haglund

一般的にはanythingを意味します。 xlistまたは_numpy.ndarray_である場合の意味は既に説明されていますが、一般的には比較演算子(_<_、_>_、...)、およびget/set-item(_[...]_-- syntax)の実装方法。

_x.__getitem__(x.__lt__(2))      # this is what x[x < 2] means!
x.__setitem__(x.__lt__(2), 0)   # this is what x[x < 2] = 0 means!
_

なぜなら:

  • _x < value_はx.__lt__(value)と同等です
  • _x[value]_は(ほぼ)x.__getitem__(value)と同等です
  • _x[value] = othervalue_は(ほぼ)x.__setitem__(value, othervalue)と同等です。

これはカスタマイズしてanythingを実行できます。ちょうど例として(少しnumpys-booleanインデックス付けを模倣します):

_class Test:
    def __init__(self, value):
        self.value = value

    def __lt__(self, other):
        # You could do anything in here. For example create a new list indicating if that 
        # element is less than the other value
        res = [item < other for item in self.value]
        return self.__class__(res)

    def __repr__(self):
        return '{0} ({1})'.format(self.__class__.__name__, self.value)

    def __getitem__(self, item):
        # If you index with an instance of this class use "boolean-indexing"
        if isinstance(item, Test):
            res = self.__class__([i for i, index in Zip(self.value, item) if index])
            return res
        # Something else was given just try to use it on the value
        return self.value[item]

    def __setitem__(self, item, value):
        if isinstance(item, Test):
            self.value = [i if not index else value for i, index in Zip(self.value, item)]
        else:
            self.value[item] = value
_

それでは、それを使用するとどうなるか見てみましょう。

_>>> a = Test([1,2,3])
>>> a
Test ([1, 2, 3])
>>> a < 2  # calls __lt__
Test ([True, False, False])
>>> a[Test([True, False, False])] # calls __getitem__
Test ([1])
>>> a[a < 2] # or short form
Test ([1])

>>> a[a < 2] = 0  # calls __setitem__
>>> a
Test ([0, 2, 3])
_

これは1つの可能性にすぎないことに注意してください。ほぼすべてを自由に実装できます。

6
MSeifert