强<=>弱类型不仅是关于一种数据类型的语言将语言自动将多少值强制转换为另一种数据的连续性,还涉及到对实际值的强弱程度。在Python和Java中,大多数情况下在C#中,值的类型设置为固定。在Perl中,不是那么多-实际上只有少数几个不同的值类型可以存储在变量中。
让我们一一打开案例。
蟒蛇
在Python示例中1 + "1"
,+
运算符调用__add__
for类型int
,将字符串"1"
作为参数,但是这会导致NotImplemented:
>>> (1).__add__('1')
NotImplemented
接下来,解释器尝试__radd__
str的:
>>> '1'.__radd__(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute '__radd__'
由于失败,+
操作员将结果与失败TypeError: unsupported operand type(s) for +: 'int' and 'str'
。这样,该异常并不能说明强类型,但是该运算符+
不会自动将其参数强制转换为同一类型,这说明了Python不是连续体中最弱类型的语言。
另一方面,在Python 'a' * 5
中实现了:
>>> 'a' * 5
'aaaaa'
那是,
>>> 'a'.__mul__(5)
'aaaaa'
操作不同的事实需要强类型化-但是,*
在乘法之前将值强制转换为数字的相反情况并不一定会使值弱类型化。
爪哇
Java示例String result = "1" + 1;
之所以起作用,仅是因为为方便起见,运算符+
被字符串重载。Java +
运算符使用创建一个替换序列StringBuilder
(请参阅参考资料):
String result = a + b;
// becomes something like
String result = new StringBuilder().append(a).append(b).toString()
这是一个非常静态的键入的示例,没有实际的强制性- StringBuilder
有一种append(Object)
专门用于此的方法。该文档说:
追加Object
参数的字符串表示形式。
总体效果就好像参数已由方法转换为String.valueOf(Object)
字符串,然后将该字符串的字符附加到此字符序列。
当String.valueOf
再
返回Object参数的字符串表示形式。[返回]如果参数为null
,则字符串等于"null"
; 否则,obj.toString()
返回的值。
因此,这种情况绝对不会被语言强制-将所有问题都委派给对象本身。
C#
根据此处的Jon Skeet答案,该类+
甚至都不会重载运算符string
-类似于Java,这归功于静态和强类型化,这是编译器生成的便利。
佩尔
正如perldata解释的那样,
Perl具有三种内置数据类型:标量,标量数组和标量的关联数组,称为“哈希”。标量是单个字符串(任何大小,仅受可用内存限制),数字或对某物的引用(将在perlref中进行讨论)。普通数组是按数字索引的标量的有序列表,从0开始。哈希是通过其关联的字符串键索引的无序标量值的集合。
但是,Perl没有用于数字,布尔值,字符串,空值,undefined
s,对其他对象的引用等的单独数据类型-它仅具有一种用于所有这些的类型,即标量类型。0是“ 0”的标量值。设置为字符串的标量变量实际上可以变成数字,并且从此开始,如果在数字上下文中访问,则其行为就不同于“只是字符串”。标量可以在Perl中容纳任何内容,它与系统中存在的对象一样多。而在Python中,名称仅指对象,而在Perl中,名称中的标量值是可变对象。此外,基于对象的类型系统还基于此:perl中只有3种数据类型-标量,列表和哈希。Perl中的用户定义对象是对包的引用(指向之前3个中的任何一个的指针)bless
-您可以获取任何此类值,并在需要的任何时候将其祝福给任何类。
Perl甚至允许您一时兴起地更改值的类-在Python中这是不可能的,在Python中创建某些类的值时,您需要显式构造具有该类object.__new__
或类似值的该类的值。在Python中,创建后实际上不能更改对象的本质,在Perl中,您可以做很多事情:
package Foo;
package Bar;
my $val = 42;
# $val is now a scalar value set from double
bless \$val, Foo;
# all references to $val now belong to class Foo
my $obj = \$val;
# now $obj refers to the SV stored in $val
# thus this prints: Foo=SCALAR(0x1c7d8c8)
print \$val, "\n";
# all references to $val now belong to class Bar
bless \$val, Bar;
# thus this prints Bar=SCALAR(0x1c7d8c8)
print \$val, "\n";
# we change the value stored in $val from number to a string
$val = 'abc';
# yet still the SV is blessed: Bar=SCALAR(0x1c7d8c8)
print \$val, "\n";
# and on the course, the $obj now refers to a "Bar" even though
# at the time of copying it did refer to a "Foo".
print $obj, "\n";
因此,类型标识弱绑定到变量,并且可以通过任何引用即时更改它。实际上,如果您这样做
my $another = $val;
\$another
没有类标识,即使仍然\$val
会提供祝福的引用。
TL; DR
对于Perl而言,弱类型不仅仅是自动强制,还有很多更多的是,值的类型本身并没有固定不变,这与Python是动态但非常强类型的语言不同。这蟒蛇给人TypeError
的1 + "1"
是一种迹象表明,语言是强类型,即使做一些有用的一个相反,如Java或C#不排除他们是强类型语言。