Reputation: 18859
I'm not well versed in Python as I have a Java background. I have this simple class:
## Class declaration
class SemVersion:
major: int
minor: int
patch: int
def __init__(self, major, minor, patch):
self.major = major
self.minor = minor
self.patch = patch
def incrementMinor(self):
print(self)
self.minor = self.minor + 1
return self
def toString(self):
return self.major + "." + self.minor + "." + self.patch
def toSnapshotString(self):
return self.toString() + "-SNAPSHOT"
The following statement throws an error:
newDevelopVersion = releaseSemVersion.incrementMinor()
Exception:
Traceback (most recent call last): File "C:\devenv\java\apps\vsb-letters-transfer-api\release_preprod.py", line 41, in newDevelopVersion = releaseSemVersion.incrementMinor() File "C:\devenv\java\apps\vsb-letters-transfer-api\release_helpers.py", line 17, in incrementMinor self.minor = self.minor + 1 TypeError: can only concatenate str (not "int") to str
I'd like to understand how Python can manage not to recognize it as an integer as I declared it as such and just increment the way I asked it.
I'm sure there is a reasonable explanation for it.
I don't see how I asked anywhere to add a string to an int or anything of that nature.
Many thanks.
Upvotes: 0
Views: 158
Reputation: 281
First of all, some considerations when using Python:
Python do not enforce type, type hints just helps you and others to understand what is expected on some method or function
Variables and method name must be in snake_case
format, following the best practices described on pep8
Now, refactoring your example, you should be able to perform your desired operation with:
class SemVersion:
major: int
minor: int
patch: int
def __init__(self, major, minor, patch):
self.major = major
self.minor = minor
self.patch = patch
def increment_minor(self):
self.minor = self.minor + 1
return self
def to_string(self):
return self.major + "." + self.minor + "." + self.patch
def to_snapshot_string(self):
return self.toString() + "-SNAPSHOT"
# Your class instance
develop_vision = SemVersion(
major=1,
minor=2,
patch=3
)
print(f"Initial value of minor: {develop_vision.minor}")
develop_vision.increment_minor()
develop_vision.increment_minor()
print(f"New value of minor: {develop_vision.minor}")
Now, if you want to check your constructor arguments type, pydantic can help you!
# Make sure that your virtual environment is active
$ pip3 install pydantic
Adapt your class to use pydantic validations
from pydantic import BaseModel, StrictInt
class SemVersion(BaseModel):
major: StrictInt
minor: StrictInt
patch: StrictInt
# You don't need build a constructure anymore, pydantic do it for you
def increment_minor(self):
self.minor = self.minor + 1
return self
def to_string(self):
return self.major + "." + self.minor + "." + self.patch
def to_snapshot_string(self):
return self.toString() + "-SNAPSHOT"
# Your class instance
develop_vision = SemVersion(
major=1,
minor=2,
patch='10'
)
print(develop_vision)
If you try to run this code, using a string like '10', you will get an exception from pydantic, like this:
Traceback (most recent call last):
File "/home/jns/Desktop/stack.py", line 23, in <module>
develop_vision = SemVersion(
File "pydantic/main.py", line 341, in pydantic.main.BaseModel.__init__
pydantic.error_wrappers.ValidationError: 1 validation error for SemVersion
patch
value is not a valid integer (type=type_error.integer)
Upvotes: 1
Reputation: 563
Python doesn't enforce types from annotations. The annotations are primarily for documentation purposes.
You are likely passing in an str
to the constructor when you initialize your object which would have made the interpreter think releaseSemVersion.minor
is a string instead of an int
.
You can avoid this by adding a check in __init__()
as follows
def __init__(self, major, minor, patch):
if not isinstance(major, int):
raise TypeError('major must by of type int')
if not isinstance(minor, int):
raise TypeError('minor must by of type int')
if not isinstance(patch, int):
raise TypeError('patch must by of type int')
self.major = major
self.minor = minor
self.patch = patch
Upvotes: 2