6 ms·
"getting the two confused" implies that your terminology is standard, which it isn't. It is also quite common to use the term "type" to refer exclusively to pro
by zenhack 8y ago
"getting the two confused" implies that your terminology is standard, which it isn't. It is also quite common to use the term "type" to refer exclusively to properties that are checked statically.
Arguably "strong dynamic typing" is a property of libraries, not languages -- e.g. int conceptually has a method like:
def __add__(self, other):
if not isinstance(other, int):
raise TypeError(...)
return _unchecked_add_ints(self, other)
It's implemented in C for efficiency, but that's basically the semantics. Critically, this doesn't magically extend to user-written libraries, so unless you actually write all of that boilerplate nothing but a handful of methods in the standard library can be claimed to be "strongly typed". I've written code with a bunch of asserts in methods like that after determining that a large percentage of bugs were type errors that were silently doing the wrong thing. Without something like mypy, Python is untyped by any reasonable definition; it provides no support for users to actually work with types in any meaningful way.
- viraptor 8y agoI think you got the user-written part the wrong way around. It is strongly typed because unless you define the operators/methods you explicitly want to enable, they don't exist. For example if you try "object() + object()", you get an exception. You can implement the addition in a subclass, but that's explicit then. Compare to JS where "new Object() + new Object()" results in a string by default.
- zenhack 8y agoYou only get an exception if and when something in the bowels of your implementation bangs into a low-level operation that has one of these checks in it. For example: >>> import subprocess >>> subprocess.call([2]) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/lib/python2.7/subprocess.py", line 172, in call return Popen(*popenargs, **kwargs).wait() File "/usr/lib/python2.7/subprocess.py", line 394, in __init__ errread, errwrite) File "/usr/lib/python2.7/subprocess.py", line 1047, in _execute_child raise child_exception AttributeError: 'int' object has no attribute 'rfind' In the case of `object() + object()`, that check is in `object.__getattribute__` My point is that the checks are a property of a definition of those (possibly built-in) classes; the language doesn't provide any facility to talk about types as such. Nothing in the language knows that the argument to subrpocess.call should be a list of strings, it just happily executes until it hits what is essentially: >>> (2).__getattribute__('rfind') Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'int' object has no attribute 'rfind' And `__getattribute__` throws an exception. This is the best case scenario. Worst case it never hits something that these primitive types are aware is not ok, and it just does the wrong thing. There's no way to specify typing invariants in a way the language understands -- you just have to put in the manual check yourself. This is what I mean when I say strong types aren't part of the language. But if you add static types to the mix (say via mypy): If it were actually checking what should be the types involved in the code you wrote you'd get something like this: error: List item 0 has incompatible type "int"; expected "Union[bytes, str, _PathLike[Any]]" ...which is what mypy reports when run on that code. Python isn't checking the type of the argument subprocess.call ever, not even at runtime. If you're lucky, eventually you hit some code that has an explicity sanity check in it and it raises an exception. There's an interesting point in the design space that you see with julia[1], and also with mechansims like racket's contracts[2], where the types aren't checked statitcally, but they are checked at runtime, unlike the example above with subprocess, where you only get the error deep in the implementation when something actually explodes. I think you could sensibly say that the "strength" is actually a property of Julia, rather than its libraries, but not in Python, the "strength" isn't part of the language per se. The only differece with a "weakly typed" language is that those basic libraries have a much more footgun-like design -- again, not really about the language per se. [1]: https://docs.julialang.org/en/stable/manual/types/ https://docs.julialang.org/en/stable/manual/types/ [2]: https://docs.racket-lang.org/reference/contracts.html https://docs.racket-lang.org/reference/contracts.html
- joshuamorton 8y agoIn a weakly typed language, that 2 would be implicitly converted to a string. So yes, python is absolutely strongly typed, as opposed to js which is not.
- zenhack 8y agoThere's nothing stopping the implementation from doing that, if the authors of the stdlib thought it made sense: def __add__(self, other): if isinstance(other, str): return str(self) + other ... Again, my point is that the distinction is mostly library design.
- joshuamorton 8y agoIndeed, but you have to explicitly do that. The language doesn't for you. Implicit type coercion is the factor that defines weak typing. Python doesn't do implicit type coercion. Therefore it is not weakly typed. Libraries have nothing to do with it. Yes you could, but you could do the same in Java by having a method take in Object and cast. Which by the way is exactly what's happening in the python code.
- zenhack 8y agoI am interpreting the term "library" somewhat broadly -- my notion is that int isn't conceptually any more core to the language than e.g. the numpy matrix classes. It's built-in for speed, but (apart from some syntactic sugar for literals), it's semantically just another class. In this light, the distinction is happening in the code that defines the int class, not in something deep in the language semantics. The call to str isn't really a cast (which doesn't really have a counterpart in a language without static types); you're calling the constructor to the str class, which somewhere in it has a code path where it formats an int as a string (probably by way of calling the argument's __str__ method).
- joshuamorton 8y ago