私は次のような行でいくつかのコードに出会いました
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]
これは、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]
が変更されます。
なぜこれが起こるのですか?
比較の規則は次のとおりです。
2つの文字列または2つの数値タイプを注文する場合、注文は予想どおりに行われます(文字列の辞書順、整数の数値順)。
数値型と非数値型を注文すると、数値型が最初に来ます。
どちらも数値ではない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
>>> x = [1,2,3,4,5]
>>> x<2
False
>>> x[False]
1
>>> x[True]
2
Boolは単純に整数に変換されます。インデックスは0または1です。
あなたの質問の元のコードはPython2.でのみ機能します。x
がPython2のlist
である場合、比較x < y
はFalse
がy
egerである場合____int
です。これは、リストと整数を比較する意味がないためです。ただし、Python2では、オペランドが比較可能でない場合、CPythonでは 型の名前のアルファベット順 ;に基づいて比較が行われます。さらに、混合型の比較では、すべての数値が最初になります。これはCPython 2のドキュメントでは詳しく説明されておらず、異なるPython2実装では異なる結果が得られる可能性があります。 [1, 2, 3, 4, 5] < 2
は数値であり、CPythonのFalse
よりも「小さい」ため、2
はlist
と評価されます。この混合比較は、最終的には 機能があいまいすぎると見なされる であり、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の配列)の多くのデータ型があります。使用しているコードが何か他のことをした場合、それはx
がlist
ではないであったが、演算子<
を持つ他のクラスのインスタンスがオーバーライドされてbool
ではない値を返したためです。そして、この値はx[]
(別名__getitem__
/__setitem__
)によって特別に処理されました
これにはもう1つの用途があります。コードゴルフです。コードゴルフは、可能な限り少ないソースコードバイトで問題を解決するプログラムを作成する技術です。
return(a,b)[c<d]
とほぼ同等です
if c < d:
return b
else:
return a
ただし、aとbは両方とも最初のバージョンでは評価されますが、2番目のバージョンでは評価されません。
c<d
はTrue
またはFalse
に評価されます。(a, b)
はタプルです。
タプルのインデックス作成は、リストのインデックス作成と同様に機能します:(3,5)[1]
== 5
。True
は1
と等しく、False
は0
と等しくなります。
(a,b)[c<d]
(a,b)[True]
(a,b)[1]
b
またはFalse
の場合:
(a,b)[c<d]
(a,b)[False]
(a,b)[0]
a
スタック交換ネットワークには、数バイトを節約するためにpythonにできる多くの厄介なことの良いリストがあります。 https://codegolf.stackexchange.com/questions/54/tips-for-golfing-in-python
通常のコードではこれは決して使用すべきではありませんが、あなたの場合、x
は整数と比較できるものとして、またスライスをサポートするコンテナーとして機能することを意味します。これは非常に珍しい組み合わせです。他の人が指摘しているように、おそらくNumpyのコードでしょう。
一般的にはanythingを意味します。 x
がlist
または_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つの可能性にすぎないことに注意してください。ほぼすべてを自由に実装できます。