get_checksum_digit(self) returns the checksum digit of an isbn. The ISBNs are 13 digits long. The last digit is a checksum digit which is determined from the first 12 digits. The method calculates and returns the checksum digit.
This is how the checksum is calculated
For eg an ISBN 978133829914
A = 9 + 8 + 3 + 8 + 9 + 1 = 38
B = (7 + 1 + 3 + 2 + 9 + 4) x 3 = 78
The check digit is then:
(10 – (A + B)) mod 10
This is my Book class:
class Book:
def __init__(self, bookname, isbn = "N/A", price=0):
self.bookname, self.isbn, self.price = bookname, isbn, price
def __str__(self):
return "{}({}),${:.2f}".format(self.bookname, self.isbn, self.price)
def get_checksum_digit(self):
even_sum = 0
odd_sum = 0
for i in range(len(self.isbn)-1):
if i%2 == 0:
even_sum += int(self.isbn[i])
else:
odd_sum += int(self.isbn[i])
i_sum = even_sum + (odd_sum * 3)
self.checksum = (10 - (i_sum)) % 10
if self.checksum == 10:
return 0
return self.checksum
def update_checksum(self):
self.isbn = self.isbn.replace(self.isbn[-1], str(Book.get_checksum_digit(self)))
return self.isbn
def is_valid_isbn(self):
return int(self.isbn[-1]) == Book.get_checksum_digit(self)
My is_valid_isbn() method is not working as it should be. Any help please? It isn’t showing True after updating the ISBN last number with the checksum.
This is the test case:
book1 = Book('Onion Skin','9781603094891',14.99)
print(book1)
print(book1.is_valid_isbn())
book1.update_checksum()
print(book1)
print(book1.is_valid_isbn())
This is the output I should get:
Onion Skin(9781603094891),$14.99
False
Onion Skin(9781603094894),$14.99
True
This is the output I’m getting:
Onion Skin(9781603094891),$14.99
False
Onion Skin(9784603094894),$14.99
False
>Solution :
Pay close attention to the ISBN numbers:
Onion Skin(9781603094891),$14.99
^ ^
Onion Skin(9784603094894),$14.99
^ ^
You didn’t want to change that first 1 — changing it invalidates the checksum! That’s happening because of the way you used replace in update_checksum.
In the process of debugging the code I did some other tidying (I had to simplify get_checksum_digit way down just to be able to figure out what it was supposed to be doing). Here’s the final result:
class Book:
def __init__(self, bookname: str, isbn = "N/A", price=0.0):
self.bookname, self.isbn, self.price = bookname, isbn, price
def __str__(self) -> str:
return f"{self.bookname} ({self.isbn}), ${self.price:2f}"
def get_checksum_digit(self) -> str:
# ISBNs have 13 digits with the 13th digit computed from the first 12:
# sum the first 12 digits, multiplying every other digit by 3.
# then subtract that from 10, and use the result mod 10.
return str((10 - sum(
int(digit) * 3 if i % 2 else int(digit)
for i, digit in enumerate(self.isbn[:-1])
)) % 10)
def update_checksum(self) -> None:
self.isbn = self.isbn[:-1] + self.get_checksum_digit()
def is_valid_isbn(self) -> bool:
return self.isbn[-1] == self.get_checksum_digit()
def test_book_isbn():
isbn = '9781603094891'
book = Book('Onion Skin', isbn, 14.99)
assert not book.is_valid_isbn()
book.update_checksum()
assert book.is_valid_isbn()
assert book.isbn[:-1] == isbn[:-1]