When programmers talk about typing, most of the time they aren't talking about the odious task of pressing keys on a keyboard (watch any programmer and look to see how much of their time they spend actually typing out code. What you'll see instead is a lot of frowning and staring at the screen with an expression of great consternation as you can see them think "why the hell didn't my code do what I thought?"). Instead they're talking about the types of variables. Now you're probably familiar with the idea that there are numbers and strings and lists, and mixing and matching them will only lead to more headaches, but types are so much more interesting and potentially powerful than those handful of shallow built-ins. Different programming languages have incredibly different approaches to types. Sometimes this leads to more frustration because the type system is too strict or lax, and sometimes it can save your ass.
Broadly speaking, languages can be broken down into statically typed languages and dynamically typed languages.
If a language is statically typed its variables cannot change types at runtime. If a language is dynamically typed its variables can change types at runtime.
This static/dynamic distinction is something you may see pop up again, by the way. Static things happen at build time and dynamic things happen at runtime.
The advantage to statically typed languages is that you can't screw up the type, because the compiler will refuse to compile the code. Here's a basic example in C:
int greeting(char *name) {
printf("Hello %s!\n", name);
}
int main() {
greeting("Sequoia"); // Works
greeting(42); // Nope, the compiler will give you an error.
}
The big advantage here is type safety, saving the programmer from themself.
Now, let's consider the analogous program in python:
def greeting(name):
print('Hello ', name, '!')
greeting('Sequoia')
greeting(42)
Now the print function can print anything in python, so it works really well in this case. But sometimes you want the additional safety which comes with static types.
Python also has this idea of "duck typing", that is "if it walks like a duck, and it talks like a duck, then it might as well be a duck". Say you need a data structure like a mathematical set. That is, each element is unique, it's easy to find the intersection or union of two sets, and the order you put an item into a set doesn't matter. You still want to be able to iterate over the elements in the set, and check how many items are in the set. This is easy enough to implement:
class set:
items = []
offset = 0
def __init__(self, iterable):
for item in iterable:
self.items.append(item)
def __len__(self):
return len(self.items)
def __iter__(self):
if self.offset == len(self):
self.offset = 0
raise StopIteration
item = self.items[self.offset]
self.offset += 1
return item
Since this class implements some of the same functions as a list you can use it nearly anywhere you can use a list! This is the key advantage to using Duck typing.
Incidentally, Python includes a built in set type which works pretty much like this but is a lot more efficient. It uses something called a 'hash map' or 'hash table' to provide really fast lookups.
Here's another example of duck typing:
import math
class Circle:
def __init__(self, radius):
self.radius = radius
def area(self):
return math.pi * self.radius * self.radius
def perimeter(self):
return math.pi * 2 * self.radius
class Rectangle:
def __init__(self, height, width):
self.height = height
self.width = width
def area(self):
return self.height * self.width
def perimeter(self):
return 2 * self.height + 2 * self.width
# Since both Circle and Square both implement these methods they'll both work.
def shape_info(shape):
print(shape.area())
print(shape.perimeter())
square = Rectangle(4, 4)
c = Circle(10)
shape_info(square)
shape_info(c)
Some languages have a way of formalizing and enforcing this Duck Typing approach. For instance, in C++ you can use duck typing and the compiler will catch many errors which you wouldn't find in Python until they occurred at runtime. Other languages like Go have an idea of interfaces, a way of formalizing the methods which you create in Python. Again, the difference is that you can check the types at compile time to catch errors.
Here is an example of the same shapes program in Go. Notice how I have to explicitly declare the Shape interface and have to explicitly declare the types of all of these variables. This allows the compiler to check that all of the types are correct before running the program.
import "fmt"
import "math"
// Any object which has an Area method and a Perimeter method is a shape
type Shape interface {
Area() float64
Perimeter() float64
}
// A Rectangle has two numbers, a height and a width
// Since we implement the Area and Perimeter functions it is a shape.
type Rectangle struct {
height float64
width float64
}
// A Circle just has a radius
// Again, since we implement the Area and Perimeter functions it is a shape.
type Rectangle struct {
type Circle struct {
radius float64
}
// Implement the Area method for the Rectangle structure.
// r is just like self in Python.
func (Rectangle r) Area() float64 {
return r.width * r.height
}
func (Rectangle r) Perimeter() float64 {
return 2 * r.width + 2 * r.height
}
func (Circle c) Area() float64 {
return math.Pi * c.radius c.radius
}
func (Circle c) Perimeter() float64 {
return math.Pi * 2 * c.radius
}
// This function can take any shape
func shape_info(Shape s) {
fmt.Println(s.Area())
fmt.Println(s.Perimeter())
}
func main() {
square := Rectangle{ height: 4, width: 4 }
c := Circle{radius: 10}
shape_info(square)
shape_info(c)
}
Other languages like Haskell have even more complicated type systems which enforce certain mathematical properties on your types. This helps make programs easily composable and makes them really robust to errors, but also makes the language a royal pain sometimes which has little traction outside of academia. Once you get a handle on Python and a statically typed language under your belt I encourage you to take a look at Haskell. It will change the way you think about programming.