10

C# を勉強しているときに、動的に型付けされた Python が次のコードでエラーを発生させることは、非常に奇妙であることがわかりました。

i = 5
print i + " "

一方、静的に型付けされた C# は通常、同様のコードを処理します。

int i = 5;
Console.Write(i + " ");

私は別の方法を期待します (python ではキャストせずにこれを行うことができますが、C# では int を string に、または string を int にキャストする必要があります)。

強調しておきたいのは、私はどの言語が優れているかを尋ねているのではなく、その言語をこのように実装した理由が何であるかを知りたいということです。

4

6 に答える 6

23

ここで何かがおかしいというのはあなたの言うとおりです。奇妙なのは+、どちらの言語でも文字列連結を意味することです! int を文字列に連結できるかどうかは、 「連結」を意味する+奇妙さに比べれば小さなポイントです。+

文字列の連結を意味するために最初にどの言語の使用が許可されたかはわかりません+が、その誤機能が何度も何度も繰り返されたため、今では通常、それがどれほど奇妙であるかさえ気付かないほどです. 通常の追加のプロパティのいくつかをリストし、文字列が測定されるかどうかを見てみましょう.

  • 加算は交換可能ですが、文字列の連結はそうではありません。x + y != y + x
  • 加算は連想ですが、C# の文字列連結はそうではありません。(x + y) + z は、たとえば y と z が整数の場合、x + (y + z) と等しい必要はありません。
  • 加算は逆演算の減算と対になっており、x + y が z の場合、z - y は x であるという性質があります。文字列にはそのような操作はありません。
  • 加算には左右の同一性があり、文字列の連結もそうです。(空の文字列)。

4分の1は良くない。文字列の連結は足し算とは非常に異なりますが、なぜ演算子を共有する必要があるのでしょうか?

私はこれをあまり言いませんが、C は正しかったです。文字列連結演算子は、まさに連結でなければなりません。C では"X" "Y"を意味し"XY"ます。2 つの文字列リテラルを並べて配置すると、それらは 3 番目に連結されます。

于 2013-10-23T23:04:27.873 に答える
9

これは実際には静的/動的な質問ではなく、言語設計の哲学の問題です。

Python では、+は数値の加算と文字列の連結として定義されています。プログラミングの経験が少しでもあれば、これは完全に合理的な動作です。

しかし、それぞれが 1 つずつある場合はどうなるでしょうか。文字列を数値に変換しようとしますか、それとも数値を文字列に変換しますか? どちらも、プログラミングをまったく行ったことのある人にとっては完全に合理的な動作ですが、言語が異なれば、これがどのように発生するかについても異なるルールがあるため、経験のある言語に応じて、他の人が行う仮定とは異なる仮定を行うことができます。すでに。

Python には、その指針となる原則の 1 つとして、「明示的は暗黙的よりも優れている」( import this) があるため、必要な動作を明示的に指定する必要があります。どのように?もちろん、文字列または数値を目的の型に変換することによって。次に、それらは両方とも文字列または両方の数値であり、動作は明らかです。

結果として得られるコードは、何をするかを推測する必要がないため、(Python をあまり知らなくても) 読みやすくなっています。

于 2013-10-23T21:52:53.773 に答える
9

これは、実際には静的型付けと動的型付けの領域ではありません。むしろ、それは強力な型付けと弱い型付けの対比です (少なくとも、ウィキペディアがプログラミング言語の特徴付けでたまたま使用している一般的に使用されている用語によると)。そして、C# と Python はどちらも厳密に型指定されています (その定義による)。

残念ながら、これらの概念はすべて白黒ではなく、グレースケールであり、起動するには不明確です。ただし、結果として、言語が型チェックを実行する強度と、実行するチェックには微妙な違いがあります。

あなたの特定の状況では、C#operator +が文字列と数値 (実際には任意のオブジェクト) をオーバーロードしますが、Python はそうではありません。これにより、この場合、Python がわずかに厳密になります。

于 2013-10-23T21:26:19.660 に答える
3

C# の場合、 ToString() for Int32(int) と呼ばれるメソッドがあり、そのほとんどすべての型があります。この場合、ポインター型は例外です。

StringC#のクラスは、この場合String.Concat(Object, Object)+を呼び出すだけの演算子をオーバーロードしています。

私の意見では、これは何よりも .NET Framework の動作の結果です。

于 2013-10-23T21:46:07.160 に答える
2

ここでは、Python データ モデル ( http://docs.python.org/2/reference/datamodel.html#emulating-numeric-types ) を理解することが役立ちます。

を実行すると、これが舞台裏にa + b変換されます。a.__add__(b)これは、静的型付けの欠如を考慮して、python が演算子のオーバーロードをサポートする方法です。

C# では、ToString() メソッドを介して文字列に暗黙的にキャストできます。Python には、暗黙的なキャストの概念がありません。ToString() はすべてのオブジェクトで定義されたメソッドであり、C# には静的型付けがあるため、これは機能します。そのため、オブジェクトがいつキャストされるかは呼び出し元にとって明らかです。

この動作を実際に確認したい場合は、次を実行できます (ただし、本番環境では実行しないでください)。

class MyString(str):
    def __add__(self, other):
        """ automatically concatenate other values as strings """
        return super(MyString, self).__add__(str(other))

s = MyString("this is a string")
print s + 1

もちろん、上記の変換を見ると、print 1 + s. 文字列に変換するだけの場合でも、型変換について明示することをお勧めします。特殊なケースでは気が狂ってしまうからです。

于 2013-10-23T22:02:44.577 に答える
1

ここでは動的型付けは実際には機能しません。どちらの言語も i が int で " " が文字列であることを理解しています。違いは、C# には (int,string) 引数を取る関数 + がありますが、Python にはありません。

于 2013-10-23T21:28:59.673 に答える