FWIW, these lines are not equivalent:
@major, @minor, @patch = parts[0] || 0, parts[1] || 0, parts[2] || 0
self.major, self.minor, self.patch = parts[0] or 0, parts[1] or 0, parts[2] or 0
The Ruby case is intended to handle strings like "1", "1.2", and "1.2.3".
The Python code will throw an IndexError as written. Which is why I did this in the namedtuple example:
parts = [int(x) for x in version_string.split(".")] + [0, 0]
That ensures you'll have at least three parts so you can then:
self.major, self.minor, self.patch = parts[:3]