Is Python strongly typed?
I've come across links that say Python is a strongly typed language.
However, I thought in strongly typed languages you couldn't do this:
bob = 1 bob = "bob"
I thought a strongly typed language didn't accept type-changing at run-time. Maybe I've got a wrong (or too simplistic) definition of strong/weak types.
So, is Python a strongly or weakly typed language?
Why is Python a dynamic language and also a strongly typed , Both Java and Python are strongly typed languages. Examples of weakly typed languages are Perl and Rexx. A third distinction may be made� Python is strongly typed as the interpreter keeps track of all variables types. It's also very dynamic as it rarely uses what it knows to limit variable usage. In Python, it's the program's responsibility to use built-in functions like isinstance() and issubclass() to test variable types and correct usage.
There are some important issues that I think all of the existing answers have missed.
Weak typing means allowing access to the underlying representation. In C, I can create a pointer to characters, then tell the compiler I want to use it as a pointer to integers:
char sz = "abcdefg"; int *i = (int *)sz;
On a little-endian platform with 32-bit integers, this makes
i into an array of the numbers
0x00676665. In fact, you can even cast pointers themselves to integers (of the appropriate size):
intptr_t i = (intptr_t)&sz;
And of course this means I can overwrite memory anywhere in the system.*
char *spam = (char *)0x12345678 spam = 0;
* Of course modern OS's use virtual memory and page protection so I can only overwrite my own process's memory, but there's nothing about C itself that offers such protection, as anyone who ever coded on, say, Classic Mac OS or Win16 can tell you.
Traditional Lisp allowed similar kinds of hackery; on some platforms, double-word floats and cons cells were the same type, and you could just pass one to a function expecting the other and it would "work".
Most languages today aren't quite as weak as C and Lisp were, but many of them are still somewhat leaky. For example, any OO language that has an unchecked "downcast",* that's a type leak: you're essentially telling the compiler "I know I didn't give you enough information to know this is safe, but I'm pretty sure it is," when the whole point of a type system is that the compiler always has enough information to know what's safe.
* A checked downcast doesn't make the language's type system any weaker just because it moves the check to runtime. If it did, then subtype polymorphism (aka virtual or fully-dynamic function calls) would be the same violation of the type system, and I don't think anyone wants to say that.
Very few "scripting" languages are weak in this sense. Even in Perl or Tcl, you can't take a string and just interpret its bytes as an integer.* But it's worth noting that in CPython (and similarly for many other interpreters for many languages), if you're really persistent, you can use
ctypes to load up
libpython, cast an object's
id to a
POINTER(Py_Object), and force the type system to leak. Whether this makes the type system weak or not depends on your use cases—if you're trying to implement an in-language restricted execution sandbox to ensure security, you do have to deal with these kinds of escapes…
* You can use a function like
struct.unpack to read the bytes and build a new int out of "how C would represent these bytes", but that's obviously not leaky; even Haskell allows that.
Meanwhile, implicit conversion is really a different thing from a weak or leaky type system.
Every language, even Haskell, has functions to, say, convert an integer to a string or a float. But some languages will do some of those conversions for you automatically—e.g., in C, if you call a function that wants a
float, and you pass it in
int, it gets converted for you. This can definitely lead to bugs with, e.g., unexpected overflows, but they're not the same kinds of bugs you get from a weak type system. And C isn't really being any weaker here; you can add an int and a float in Haskell, or even concatenate a float to a string, you just have to do it more explicitly.
"a" + 1 gives you
"a1"), while Python does a lot fewer (
"a" + 1 raises an exception, but
1.0 + 1 does give you
2.0*). It's just hard to put that sense into formal terms—why shouldn't there be a
+ that takes a string and an int, when there are obviously other functions, like indexing, that do?
* Actually, in modern Python, that can be explained in terms of OO subtyping, since
isinstance(2, numbers.Real) is true. I don't think there's any sense in which
Finally, there's another, completely orthogonal, definition of "strong" vs. "weak" typing, where "strong" means powerful/flexible/expressive.
For example, Haskell lets you define a type that's a number, a string, a list of this type, or a map from strings to this type, which is a perfectly way to represent anything that can be decoded from JSON. There's no way to define such a type in Java. But at least Java has parametric (generic) types, so you can write a function that takes a List of T and know that the elements are of type T; other languages, like early Java, forced you to use a List of Object and downcast. But at least Java lets you create new types with their own methods; C only lets you create structures. And BCPL didn't even have that. And so on down to assembly, where the only types are different bit lengths.
So, in that sense, Haskell's type system is stronger than modern Java's, which is stronger than earlier Java's, which is stronger than C's, which is stronger than BCPL's.
So, where does Python fit into that spectrum? That's a bit tricky. In many cases, duck typing allows you to simulate everything you can do in Haskell, and even some things you can't; sure, errors are caught at runtime instead of compile time, but they're still caught. However, there are cases where duck typing isn't sufficient. For example, in Haskell, you can tell that an empty list of ints is a list of ints, so you can decide that reducing
+ over that list should return 0*; in Python, an empty list is an empty list; there's no type information to help you decide what reducing
+ over it should do.
* In fact, Haskell doesn't let you do this; if you call the reduce function that doesn't take a start value on an empty list, you get an error. But its type system is powerful enough that you could make this work, and Python's isn't.
Static vs. dynamic typing of programming languages, Smalltalk, Perl, Ruby, Python, and Self are all "strongly typed" in the sense that typing errors are prevented at runtime and they do little implicit type conversion, but� I’ll try to clarify where the doubt lies. So, come along. First thing: Python is strongly typed language. (I agree with Mayank when he says that Python is dynamic, but let’s remain focused, we’ll come to that little later.)
I cannot change the type of
1 by adding the string
'12', but I can choose what types I store in a variable and change that during the program's run time.
The opposite of dynamic typing is static typing; the declaration of variable types doesn't change during the lifetime of a program. The opposite of strong typing is weak typing; the type of values can change during the lifetime of a program.
Strong and weak typing, > Python is considered a weakly-typed or dynamically-typed programming language. This isn't right. Weak/strong typing is on a different axis than� Strongly typed is a concept used to refer to a programming language that enforces strict restrictions on intermixing of values with differing data types. When such restrictions are violated and error (exception) occurs. Techopedia explains Strongly Typed Examples of strongly typed languages in existence include Java, Ruby, Smalltalk and Python.
According to this wiki Python article Python is both dynamically and strongly typed (provides a good explanation too).
Perhaps you are thinking about statically typed languages where types can not change during program execution and type checking occurs during compile time to detect possible errors.
This SO question might be of interest: Dynamic type languages versus static type languages and this Wikipedia article on Type Systems provides more information
Python's typing is Dynamic so you can change an string variable to an int
x = 'somestring' x = 50
Python typing is Strong so you can't merge types:
'foo' + 3 --> TypeError: cannot concatenate 'str' and 'int' objects
'foo'+3 = 'foo3'
Regarding Type Inference
Java forces you to explicitly declare your object types
int x = 50
Kotlin uses inference to realize it's an
x = 50
But because both languages use static types,
x can't be changed from an
int. Neither language would allow a dynamic change like
x = 50 x = 'now a string'
How to Use Static Type Checking in Python 3.6, Smalltalk, Perl, Ruby, Python, and Self are all "strongly typed" in the sense that typing errors are prevented at runtime and they do little implicit type conversion, but these languages make no use of static type checking: the compiler does not check or enforce type constraint rules.
Initially PEP 484 defined Python static type system as using nominal subtyping. This means that a class A is allowed where a class B is expected if and only if A is a subclass of B. This requirement previously also applied to abstract base classes, such as Iterable.
But Python is a dynamically typed language. It doesn’t know about the type of the variable until the code is run. So declaration is of no use. What it does is, It stores that value at some memory location and then binds that variable name to that memory container.
- One example I don't see very often but I think is important to show that Python is not completely strongly typed, is all the things that evaluate to boolean: docs.python.org/release/2.5.2/lib/truth.html
- Not so sure if this is a counter example: Things can evaluate to a boolean, but they don't suddenly "become" a boolean. It's almost as if someone implicitly called something like as_boolean(<value>), which is not the same as the type of the object itself changing, right?
- Being truthy in boolean context is not a counterexample, because nothing is actually being converted to
False. But what about number promotion?
1.0 + 2works just as well in Python as it does in Perl or C, even though
"1.0" + 2doesn't. I agree with @jbrendel that this isn't really an implicit conversion, it's just overloading—but in the same sense, Perl isn't doing any implicit conversion either. If functions don't have declared parameter types, there's nowhere for implicit conversions to happen.
- @gsingh2011 Truthiness is useful and not weak typing on its own, but an accidental
if isValid(value) - 1can leak. The boolean is coerced into integer, which is then evaluated as a truthy value.
False - 1becomes truthy and
True - 1becomes falsy, leading to an embarrassingly difficult two-layered off-by-one error to debug. In this sense, python is mostly strongly typed; type coercions don't usually cause logical errors.
- This answer is brilliant! A shame it's languished for so long at the bottom of the list.
- Just a little comment to your C example:
char szis not a pointer to char, it is array of char, and in the assignment it decays into pointer.
- The description in the link strongly typed: "Generally, a strongly typed language has stricter typing rules at compile time, which implies that errors and exceptions are more likely to happen during compilation." implies Python is a weakly typed language..., is wiki wrong?
- @s̮̦̩e̝͓c̮͔̞ṛ̖̖e̬̣̦t̸͉̥̳̼: that's not implied at all. Python has strict typing rules at compile time, each object created has just one type. And 'generally' doesn't imply anything, it just means that Python is an exception to that.
'x' + 3may be
operator+overloading and doing the type conversion behind the scene?
- Anyway, your answer is actually more concise and easy to understand than the above ones.
- Several years later - another useful and relevant resource: youtu.be/_AEJHKGk9ns