Pythonのチルダ演算子


199

Pythonのチルダ演算子の使用法は何ですか?

文字列が回文かどうかをチェックするなど、文字列またはリストの両側で何かを実行することを考えることができます。

def is_palindromic(s):
    return all(s[i] == s[~i] for i in range(len(s) / 2)) 

他の良い使い方は?


11
~特別なメソッドによって実装された単項補数演算子は、(または2.xで)によって返される値を論理的に否定する演算子 __invert__とは関係がないことに注意してください。また、によって実装される単項否定演算子とは無関係です。たとえば、はfalseでないか、false はまだです。not__bool____nonzero__-__neg__~True == -2False-False == 0
Eryk Sun、

@eryksun、あなたが言ったことは正しいですが(-False==0)あなたがについて話していた~ので、~False == -1それは紛らわしく、それは偽ではありません。
ギル

3
@ GuilhermedeLazari、2番目の例は算術否定(__neg__)と比較することです。たぶん私はTrue、たとえば-True == -1-2やFalsefalse ではないを使い続けたほうがいいでしょう。これは~True結果をより明確にリンクし、aの算術否定はboolその論理否定とは異なることを示しています。私は深くなることを試みていませんでした。私は3つの操作と、時々混乱する基になる特別なメソッドを強調表示していました。
Eryk Sun、

回答:


192

これはCから借用した単項演算子(単一の引数を取る)であり、すべてのデータ型はバイトを解釈するための異なる方法です。これは「反転」または「補数」演算であり、入力データのすべてのビットが反転されます。

Pythonでは、整数の場合、整数の2の補数表現のビットが反転され(b <- b XOR 1各ビットの場合と同様)、結果は再び2の補数の整数として解釈されます。したがって、整数の場合~xはと同等(-x) - 1です。

~演算子の具体化された形式は、として提供されoperator.invertます。独自のクラスでこの演算子をサポートするには、__invert__(self)メソッドを指定します。

>>> import operator
>>> class Foo:
...   def __invert__(self):
...     print 'invert'
...
>>> x = Foo()
>>> operator.invert(x)
invert
>>> ~x
invert

同じクラスのインスタンスでもあるインスタンスの「補数」または「逆数」を持つことが重要であるクラスは、反転演算子の可能な候補です。ただし、演​​算子のオーバーロードは、誤用すると混乱を招く可能性があるため__invert__、クラスにメソッドを提供する前に、そうすることが本当に意味があることを確認してください。(バイト文字列の'\xff'すべてのビットを反転することは意味がありますが、バイト文字列[ex:]はこの演算子をサポートしないことに注意してください。)


16
良い説明ですが、注意が必要です-オペレーターの過負荷に関するすべての安全上の免責事項がここに当てはまります-法案に完全に適合しない限り、それは良い考えではありません。
Eli Bendersky、2011年

Eliのフィードバックは、最後の段落の回答に組み込まれています。
wberry


26

ビット単位の補数演算子である~だけでなく、ブール値を元に戻すのにも役立ちますが、boolここでは従来の型ではないため、を使用する必要がありますnumpy.bool_


これについては、

import numpy as np
assert ~np.True_ == np.False_

論理値を逆にすると便利な場合があります。たとえば、以下の~演算子を使用してデータセットをクレンジングし、NaNなしの列を返します。

from numpy import NaN
import pandas as pd

matrix = pd.DataFrame([1,2,3,4,NaN], columns=['Number'], dtype='float64')
# Remove NaN in column 'Number'
matrix['Number'][~matrix['Number'].isnull()]

numpy.NaNと定義されているようnumpy.floatです。試してみると~numpy.NaN、pythonは、単項演算子~がtypeに対して定義されていないと不平を言っていnumpy.floatます。
M.Herzkamp 2017年

2
@ M.Herzkamp、そうです。NaN、+ Inf、および-Infは、浮動小数点数の特殊なケースです。浮動小数点数のビットを反転すると無意味な結果が生成されるため、Pythonでは許可されていません。そのため、最初にデータ配列で.isnull()またはnp.isnan()を呼び出し、次に結果のブール値を反転する必要があります。
geofflee 2017年

7
その~True結果は-2になり、numpyブール値の場合~np.True_はになりFalseます。
クリスチャンヘレンツ2017

良いヒント!ここでデータセットをソートするために使用されているのを見ました: github.com/yu4u/age-gender-estimation/blob/master/create_db.py
mLstudent33

19

一つは、配列のインデックス付けの場合には、ことに注意してくださいarray[~i]になりますreversed_array[i]。これは、配列の最後から始まるインデックスと見なすことができます。

[0, 1, 2, 3, 4, 5, 6, 7, 8]
    ^                 ^
    i                ~i

2
これは主に、~iPythonが喜んで受け入れる配列インデックスの開始点として機能する(つまり、負の値)がインデックスを折り返し、後ろから選択するためです。
悲鳴

4

私がこれを実際に使用したのは、でのみnumpy/pandasです。たとえば、.isin() データフレームメソッドを使用します。

ドキュメントでは、この基本的な例を示しています

>>> df.isin([0, 2])
        num_legs  num_wings
falcon      True       True
dog        False       True

しかし、代わり [0、2]にないすべての行が必要な場合はどうでしょうか。

>>> ~df.isin([0, 2])
        num_legs  num_wings
falcon     False       False
dog        True        False

2

私はこのリートコードの問題解決していましたが、Zitao Wangというユーザーがこの美しい解決策に出会いました

問題はdivisonのとでは使用せずに、残りのすべての数値の積を見つける与えられた配列の各要素のためにこのように書きO(n)時間を

標準ソリューションは次のとおりです。

Pass 1: For all elements compute product of all the elements to the left of it
Pass 2: For all elements compute product of all the elements to the right of it
        and then multiplying them for the final answer 

彼の解決策は、利用することでforループを1つだけ使用します。彼は左の製品と右の製品をその場で計算します~

def productExceptSelf(self, nums):
    res = [1]*len(nums)
    lprod = 1
    rprod = 1
    for i in range(len(nums)):
        res[i] *= lprod
        lprod *= nums[i]
        res[~i] *= rprod
        rprod *= nums[~i]
    return res

-2

これはマイナーな使用法ですチルドです...

def split_train_test_by_id(data, test_ratio, id_column):
    ids = data[id_column]
    in_test_set = ids.apply(lambda id_: test_set_check(id_, test_ratio)) 
    return data.loc[~in_test_set], data.loc[in_test_set]

上記のコードは「機械学習の実践」からのものです

代わりにチルダ(〜記号)を使用します-インデックスマーカーに署名

あなたがマイナスを使うように-整数インデックス用です

例)

array = [1,2,3,4,5,6]
print(array[-1])

と同じです

print(array[~1])

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.