私は次のような行を持ついくつかのコードに出くわしました
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]
私は次のような行を持ついくつかのコードに出くわしました
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]
TypeError: unorderable types: list() < int()
ます。
回答:
これは、NumPy配列でのみ意味があります。リストを使用した動作は役に立たず、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つの互換性のないタイプを注文する場合、それらはタイプ名のアルファベット順に並べられます。
したがって、次の順序があります
数値<リスト<文字列<タプル
Pythonはstringとintをどのように比較しますか?の受け入れられた答えを参照してください。。
xがNumPy配列の場合、ブール配列のインデックス付けにより、構文の意味がわかります。その場合、x < 2
ブール値ではありません。これは、の各要素がx
2未満であるかどうかを表すブール値の配列です。x[x < 2] = 0
次に、2未満の要素を選択し、x
それらのセルを0に設定します。「索引付け」を参照してください。
>>> 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
import
にnumpyを参照してください。
[0 if i < 2 else i for i in x]
。)または、これはNumpyで推奨されるスタイルですか?
x[x<2]
numpy配列を[0 if i<2 else i for i in x]
返しますが、リストを返します。これは、x[x<2]
がインデックス作成操作(numpy / scipy / pandasではデータをマスクする機能のためにスライス操作と呼ばれる)であるのに対し、リスト内包表記は新しいオブジェクト定義であるためです。NumPyのインデックス作成を
>>> x = [1,2,3,4,5]
>>> x<2
False
>>> x[False]
1
>>> x[True]
2
ブール値は単純に整数に変換されます。インデックスは0または1のいずれかです。
x<2 == false
か、なぜですか?
bool
整数に変換されず、bool
Pythonでは整数である
bool
サブクラスですint
。
あなたの質問の元のコードでは、場合にのみPythonの2で動作しx
ているlist
のPython 2には、比較がx < y
あるFalse
場合y
であるint
エゲル。これは、リストを整数と比較することは意味がないためです。ただし、Python 2では、オペランドが比較できない場合、比較はCPythonで型の名前のアルファベット順に基づいています。さらに、混合タイプの比較では、すべての数値が最初になります。これはCPython2のドキュメントでも詳しく説明されておらず、Python2の実装が異なれば結果も異なる可能性があります。それはある[1, 2, 3, 4, 5] < 2
と評価されたFalse
ため2
、が数値でありlist
、CPythonのaよりも「小さい」ます。この混合比較は最終的に機能がわかりにくいと見なされ、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.0での変更がTypeError: unorderable types: list() < int()
原因で発生します。
注文の比較
Python 3.0は、比較の順序付けのルールを簡素化しました。
注文比較演算子(
<
、<=
、>=
、>
)上げるTypeError
オペランドが意味のある自然順序付けを持っていない場合に例外を。このように、のような表現1 < ''
、0 > None
またはlen <= len
もはや有効であり、例えばNone < None
昇給TypeError
の代わりに返しますFalse
。当然の結果として、異種リストの並べ替えはもはや意味がありません。すべての要素が互いに比較可能でなければなりません。これは==
と!=
演算子には適用されないことに注意してください。異なるタイプの比較できないオブジェクトは、常に互いに等しくないように比較されます。
比較演算子をオーバーロードして別のことを行うデータ型はたくさんあります(パンダのデータフレーム、numpyの配列)。使用しているコードが他のことを行った場合、それはでx
はなく、list
演算子が<
オーバーライドされてbool
;ではない値を返す他のクラスのインスタンスであったためです。そして、この値はx[]
(aka __getitem__
/ __setitem__
)によって特別に処理されました。
+False
こんにちはPerl、ちょっとJavaScript、お元気ですか?
UNARY_POSITIVE
、__pos__
__setitem__
代わりに意味したと思います__getitem__
。また、私の答えがあなたの答えのその部分に触発されたことを気にしないでください。
__getitem__
ものの均等にされている可能性__setitem__
と__delitem__
これにはもう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に対して実行できる多くの厄介なことの良いリストがあります。/codegolf/54/tips-for-golfing-in-python
通常のコードではこれを使用しないでください。あなたの場合はx
、整数と比較できるものとして、また非常に珍しい組み合わせであるスライスをサポートするコンテナーとして機能することを意味します。他の人が指摘しているように、それはおそらくNumpyコードです。
Code Golf is the art of writing programs
: ')
一般的に、それは何を意味する可能性があります。それは、すでにあれば、それが何を意味するのかを説明してx
いるlist
か、numpy.ndarray
一般的にはそれだけで(どのように比較演算子に依存し<
、>
そしてまた、取得/設定項目(どのように...、)[...]
-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)
です。これを行うためにカスタマイズすることができます何もしたいし。例として(少し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つの可能性にすぎないことに注意してください。必要なほとんどすべてを自由に実装できます。