在学习C#时我发现它很奇怪,动态类型的Python会在以下代码中出现错误:
i = 5
print i + " "
而静态类型的C#通常会进行类似的代码:
int i = 5;
Console.Write(i + " ");
我希望有其他方法(在python中我可以在没有任何强制转换的情况下执行此操作,但C#将要求我将int转换为string或string转换为int)。
只是为了强调,我不是在问什么语言更好,我很好奇这种语言实施背后的原因是什么。
答案 0 :(得分:23)
你说得对,这里有点奇怪。奇怪的是,+
表示两种语言中的字符串连接! +
是否可以将int连接到字符串上是一个小点,而奇怪的是+
意味着“连接”。
我不知道哪种语言首先允许+
用于表示字符串连接,但这种错误一再重复,所以现在我们通常甚至都没有注意到它是多么奇怪。让我们列出正常添加的一些属性,看看字符串是否正常。
四分之一不好。字符串连接与添加非常不同,那么它们为什么要共享一个运算符呢?
我不经常这样说,但是 C做对了。字符串连接运算符应该只是:连接。在C "X" "Y"
中表示"XY"
。如果你把两个字符串文字放在一起,它们会连接成第三个。
答案 1 :(得分:9)
这不是静态与动态类型的区域。相反,它是强与弱类型(至少根据一些常用的术语,维基百科也恰好在其编程语言的特征描述中使用)。 C#和Python都是强类型的(根据定义)。
遗憾的是,所有这些概念都不是黑白色,而是灰度级,并且定义不明确。然而,结果是语言执行类型检查的强度有细微差别,检查 。
恰巧在您的特定情况下,C#会为字符串和数字(实际上是任意对象)重载operator +
,而Python则不会。在这种情况下,这可能会使Python变得更加严格。
答案 2 :(得分:9)
这不是一个静态/动态的问题,而是语言设计哲学的问题。
在Python中,+
被定义为数字的加法和字符串的连接。如果您有一点编程经验,这是非常合理的行为。
但是当你有一个时,会发生什么?它是否尝试将字符串转换为数字,还是将数字转换为字符串?对于任何完成任何编程的人来说,这两者都是完全合理的行为,但由于不同的语言对于这种情况的发生方式有不同的规则,因此根据您使用的语言,您可能会做出与其他人不同的假设。已经
Python的指导原则之一是“显式优于隐式”(import this
),因此它可以明确说明您想要的行为。怎么样?当然,通过将字符串或数字转换为所需的类型。然后它们都是字符串或两个数字,行为是显而易见的。
生成的代码更容易阅读(即使你不太了解Python),因为你不必猜测它会做什么。
答案 3 :(得分:3)
对于C#,Int32
(int)和ToString()的所有类型都有一个名为almost的方法 - 指针类型在这种情况下是例外。
C#中的String
类重载了+
运算符,在这种情况下,只调用String.Concat(Object, Object)。
在我看来,这更多是.NET Framework工作的结果。
答案 4 :(得分: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
的问题。我建议明确你的类型转换,即使只是转换为字符串,因为边缘情况会让你发疯。
答案 5 :(得分:1)
动态类型在这里并没有发挥作用,两种语言都理解我是一个int而“”是一个字符串。区别在于C#有一个带有(int,string)参数的函数+,而Python没有。