Reputation: 19
I am currently creating a program which will ask the user to enter a year and then states whether it is a leap year or not by seeing if the year is divisible by 4. It also has a type check, presence check and a length check. I keep on getting the AttributeError: 'int' object has no attribute 'isnumeric'
All in all, the program works well as I want it to (code below) but when the program has finished it states the aforementioned attribute error. Why does it display that message and how can I solve it?
Code:
print("Did you know that the last leap year was in 2020?")
print("To find out if a year is a leap year, use this program")
year = input("Please enter a year\n")
year = str(year)
valid = False
while valid == False:
if year == "":
print("Error. Please enter a year - it should be 4 digits long.")
year = input("Please enter a year\n")
year = year.decode(year)
valid == False
else:
if year.isnumeric() == False:
print("Error. Please enter a year - it should be 4 digits long.")
year = input("Please enter a year\n")
year = str(year)
valid == False
else:
if len(year) != 4:
print("Error. Please enter a year - it should be 4 digits long.")
year = input("Please enter a year\n")
year = str(year)
valid == False
else:
year = int(year)
rem = year%4
if rem == 0:
print(f"{year} is a leap year")
else:
print(f"{year} is not a leap year, unfortunately")
valid == True
Upvotes: 0
Views: 1514
Reputation: 71424
You set year
to an int
here:
else:
year = int(year)
and then the while
loop continues with code that assumes year
is still a str
, including this line:
else:
if year.isnumeric() == False:
Note that isnumeric
is a method on str
objects that tells you whether they contain at least one character and consist of only characters with Unicode properties Numeric_Type=Digit, Numeric_Type=Decimal, or Numeric_Type=Numeric. It is not a test for whether an object is a number, or whether a string represents a number - for example, '-1'
and '1.5'
report False
for isnumeric
. int
objects are not strings, so they have no such method.
To avoid this problem, I'd suggest separating the part of the code that gets a valid year
(as an int
) from the part of the code that figures out whether it's a leap year:
print("Did you know that the last leap year was in 2020?")
print("To find out if a year is a leap year, use this program")
# First get the year.
while True:
try:
year = int(input("Please enter a year\n"))
if len(str(year)) != 4:
raise ValueError("wrong number of digits!")
break
except ValueError:
print("Error. Please enter a year - it should be 4 digits long.")
# year is now an int with 4 digits. Now figure out if it's leap.
if year % 4 == 0:
print(f"{year} is a leap year")
# Note: there is a bug here, leap year calculation
# is actually more complicated than this!
else:
print(f"{year} is not a leap year, unfortunately")
Some general notes on the "get a valid int" loop and how to do this kind of thing more simply than what you tried initially:
input()
to a str or decode
it. input
only ever returns a str
(in modern versions of Python -- I see you lurking there, pedants).int
and writing a bunch of if
s to prevent them, just try
the conversion and use an except
to catch the ValueError
that's raised on a failure. That way you only have to write one error check, and you don't need to do it by trying to reverse-engineer what some other function will do before it does it.try/except
, you can use a raise
in the body of your try
to automatically jump to the corresponding except
instead of having to write the same error handling code twice.Upvotes: 2