1265

2つの変数が値に設定されているPythonプログラムがあります'public'var1 is var2条件式では、失敗する比較がありますが、これに変更するとvar1 == var2、が返されますTrue

ここで、Pythonインタープリターを開いて、同じ「is」比較を行うと、成功します。

>>> s1 = 'public'
>>> s2 = 'public'
>>> s2 is s1
True

ここで何が欠けていますか?

4

15 に答える 15

1637

isアイデンティティテスト、==平等テストです。コードで何が起こるかは、次のようにインタープリターでエミュレートされます。

>>> a = 'pub'
>>> b = ''.join(['p', 'u', 'b'])
>>> a == b
True
>>> a is b
False

だから、彼らが同じではないのも不思議ではありませんよね?

言い換えればa is b、:はid(a) == id(b)

于 2009-10-01T15:45:20.020 に答える
630

ここでの他の答えは正しいです:同一性の比較にis使用され、同等性の比較に使用されます。気になるのは平等であるため(2つの文字列には同じ文字が含まれている必要があります)、この場合、演算子は単に間違っており、代わりに使用する必要があります。==is==

インタラクティブに機能する理由isは、(ほとんどの)文字列リテラルがデフォルトでインターンされているためです。ウィキペディアから:

インターンされた文字列は、文字列の比較を高速化します。これは、文字列キーを持つハッシュテーブルに大きく依存するアプリケーション(コンパイラや動的プログラミング言語ランタイムなど)のパフォーマンスのボトルネックになることがあります。インターンなしで、2つの異なる文字列が等しいことを確認するには、両方の文字列のすべての文字を調べる必要があります。これはいくつかの理由で遅いです。文字列の長さは本質的にO(n)です。通常、メモリのいくつかの領域からの読み取りが必要であり、時間がかかります。読み取りによってプロセッサキャッシュがいっぱいになるため、他のニーズに使用できるキャッシュが少なくなります。インターンされた文字列では、元のインターン操作の後に単純なオブジェクトIDテストで十分です。これは通常、ポインタの同等性テストとして実装されます。

したがって、同じ値を持つ2つの文字列リテラル(プログラムのソースコードに文字通り入力され、引用符で囲まれた単語)がある場合、Pythonコンパイラは自動的に文字列をインターンし、両方を同じ場所に格納します。メモリの場所。(これは常に発生するとは限らず、発生する場合のルールは非常に複雑であるため、本番コードではこの動作に依存しないでください!)

インタラクティブセッションでは、両方の文字列が実際には同じメモリ位置に格納されているため、それらは同じIDを持っているため、is演算子は期待どおりに機能します。ただし、他の方法で文字列を作成する場合(その文字列にまったく同じ文字が含まれている場合でも)、文字列は等しい可能性がありますが、同じ文字列ではありません。つまり、異なるIDを持っているためです。メモリ内の別の場所に保存されます。

于 2009-10-01T16:02:14.637 に答える
117

isキーワードはオブジェクトIDのテストであり==、は値の比較です。

を使用するisと、オブジェクトが同じオブジェクトである場合にのみ、結果がtrueになります。ただし、==オブジェクトの値が同じである場合は常にtrueになります。

于 2009-10-01T15:45:02.057 に答える
62

最後に注意すべきことは、このsys.intern関数を使用して、同じ文字列への参照を確実に取得できることです。

>>> from sys import intern
>>> a = intern('a')
>>> a2 = intern('a')
>>> a is a2
True

上で指摘したように、is文字列の同等性を判断するためにを使用するべきではありません。しかし、これは、を使用するためのある種の奇妙な要件があるかどうかを知るのに役立つ場合がありますis

このintern関数は、以前はPython 2に組み込まれていましたが、Python3のsysモジュールに移動されたことに注意してください。

于 2009-10-01T16:04:48.907 に答える
48

isアイデンティティテストであり、==平等テストです。これは、2つのものが同じものであるか、または単に同等でisあるかを確認する方法であることを意味します。

単純なpersonオブジェクトがあるとします。「ジャック」という名前で「23」歳の場合、別の23歳のジャックと同等ですが、同じ人物ではありません。

class Person(object):
   def __init__(self, name, age):
       self.name = name
       self.age = age

   def __eq__(self, other):
       return self.name == other.name and self.age == other.age

jack1 = Person('Jack', 23)
jack2 = Person('Jack', 23)

jack1 == jack2 # True
jack1 is jack2 # False

彼らは同じ年齢ですが、同じ人の実例ではありません。文字列は別の文字列と同等である可能性がありますが、同じオブジェクトではありません。

于 2013-04-29T00:56:52.640 に答える
39

これは補足ですが、慣用的なPythonでは、次のようなことがよくあります。

if x is None:
    # Some clauses

Nullオブジェクトのインスタンスが1つ(つまり、None)であることが保証されているため、これは安全です。

于 2009-10-01T18:51:32.120 に答える
32

何をしているのかわからない場合は、「==」を使用してください。それについてもう少し知識がある場合は、「なし」などの既知のオブジェクトに「is」を使用できます。

そうしないと、なぜ物事が機能しないのか、なぜこれが発生するのか疑問に思うことになります。

>>> a = 1
>>> b = 1
>>> b is a
True
>>> a = 6000
>>> b = 6000
>>> b is a
False

異なるPythonバージョン/実装間で同じままであることが保証されているかどうかさえわかりません。

于 2009-10-01T16:57:09.930 に答える
24

私のPythonでの限られた経験から、is2つのオブジェクトを比較して、同じ値を持つ2つの異なるオブジェクトではなく、同じオブジェクトであるかどうかを確認するために使用されます。 ==値が同一であるかどうかを判別するために使用されます。

これが良い例です:

>>> s1 = u'public'
>>> s2 = 'public'
>>> s1 is s2
False
>>> s1 == s2
True

s1はUnicode文字列でありs2、通常の文字列です。それらは同じタイプではありませんが、同じ値です。

于 2009-10-01T15:48:07.667 に答える
20

'is'の比較がfalseと評価された場合、2つの異なるオブジェクトが使用されるという事実と関係があると思います。trueと評価された場合、それは内部的に同じオブジェクトを使用しており、新しいオブジェクトを作成していないことを意味します。おそらく、2秒程度で作成し、最適化されたオブジェクトと最適化されたオブジェクトの間に大きな時間差がないためです。同じオブジェクトを使用します。

これが、文字列オブジェクトの値を比較するために、==ではなく等式演算子を使用する必要がある理由です。is

>>> s = 'one'
>>> s2 = 'two'
>>> s is s2
False
>>> s2 = s2.replace('two', 'one')
>>> s2
'one'
>>> s2 is s
False
>>> 

この例では、以前は「one」に等しい別の文字列オブジェクトであるs2を作成しましたがs、インタプリタが最初に「one」に割り当てなかったのと同じオブジェクトを使用しなかったため、同じオブジェクトではありません。もし私が持っていたら、それらを同じオブジェクトにしたでしょう。

于 2009-10-01T15:45:07.487 に答える
15

これは「インターン」ストリングとして知られていると思います。Pythonはこれを行い、Javaも同様であり、最適化されたモードでコンパイルする場合はCおよびC++も同様です。

2つの同じ文字列を使用する場合、2つの文字列オブジェクトを作成してメモリを浪費する代わりに、同じ内容のすべてのインターン文字列が同じメモリを指します。

これにより、同じ内容の2つの文字列が同じ文字列オブジェクトを指しているため、Pythonの「is」演算子はTrueを返します。これは、JavaとCでも発生します。

ただし、これはメモリの節約にのみ役立ちます。さまざまなインタプリタ、コンパイラ、およびJITエンジンが常にそれを実行できるとは限らないため、文字列の同等性をテストするためにこれに依存することはできません。

于 2009-10-01T15:59:38.653 に答える
14

実際には、is演算子はIDをチェックし、==演算子は同等性をチェックします。

言語リファレンスから:

タイプは、オブジェクトの動作のほぼすべての側面に影響します。オブジェクトIDの重要性でさえ、ある意味で影響を受けます。不変型の場合、新しい値を計算する操作は、実際には同じ型と値を持つ既存のオブジェクトへの参照を返す可能性がありますが、可変オブジェクトの場合、これは許可されません。たとえば、a=1の後。b = 1、aとbは、実装に応じて、値が1の同じオブジェクトを参照する場合としない場合がありますが、c=[]の後です。d = []、cおよびdは、新しく作成された2つの異なる一意の空のリストを参照することが保証されています。(c = d = []はcとdの両方に同じオブジェクトを割り当てることに注意してください。)

したがって、上記のステートメントから、不変型である文字列は、「is」でチェックすると失敗し、「is」でチェックすると成功する可能性があると推測できます。

同じことが当てはまりinttupleこれも不変タイプです。

于 2014-08-08T17:04:58.627 に答える
13

オペレーターは==値の同等性をテストします。オペレーターはisオブジェクトのIDをテストし、Pythonは2つが本当に同じオブジェクトであるかどうか(つまり、メモリ内の同じアドレスに存在するかどうか)をテストします。

>>> a = 'banana'
>>> b = 'banana'
>>> a is b
True

この例では、Pythonは1つの文字列オブジェクトのみを作成し、両方ともaそれをb参照しています。その理由は、Pythonが内部的にいくつかの文字列をキャッシュし、最適化として再利用するためです。メモリには、aとbで共有される文字列「バナナ」があります。通常の動作をトリガーするには、より長い文字列を使用する必要があります。

>>> a = 'a longer banana'
>>> b = 'a longer banana'
>>> a == b, a is b
(True, False)

2つのリストを作成すると、次の2つのオブジェクトが得られます。

>>> a = [1, 2, 3]
>>> b = [1, 2, 3]
>>> a is b
False

この場合、2つのリストは同じ要素を持っているため同等ですが、同じオブジェクトではないため同一ではありません。2つのオブジェクトが同一である場合、それらも同等ですが、同等である場合、必ずしも同一であるとは限りません。

がオブジェクトaを参照していて、を割り当てるb = a場合、両方の変数が同じオブジェクトを参照します。

>>> a = [1, 2, 3]
>>> b = a
>>> b is a
True
于 2017-07-05T04:59:32.280 に答える
7

isメモリの場所を比較します。オブジェクトレベルの比較に使用されます。

==プログラム内の変数を比較します。値レベルでのチェックに使用されます。

isアドレスレベルの同等性をチェックします

==値レベルの同等性をチェックします

于 2017-09-14T20:27:43.400 に答える
2

isはアイデンティティテストであり、==同等性テストです(Pythonのドキュメントを参照)。

ほとんどの場合、の場合a is ba == b。ただし、例外があります。たとえば、次のとおりです。

>>> nan = float('nan')
>>> nan is nan
True
>>> nan == nan
False

したがって、同一性テストにのみ使用できis、同等性テストには使用できません。

于 2017-04-24T11:37:33.460 に答える
-2

この質問に取り組む際に明確にしなければならない基本的な概念は、 is==の違いを理解することです。

「is」はメモリ位置を比較します。id(a)== id(b)の場合、aはbがtrueを返し、それ以外の場合はfalseを返します。

つまり、これはメモリ位置の比較に使用されていると言えます。一方、

==は等価性テストに使用されます。つまり、結果の値のみを比較するだけです。以下に示すコードは、上記の理論の例として機能する場合があります。

コード

コードはこちらをクリックしてください

文字列リテラル(変数に割り当てられていない文字列)の場合、メモリアドレスは図のようになります。したがって、id(a)== id(b)です。これを残すことは自明です。

于 2020-12-26T16:31:42.433 に答える