ISBN Number CheckISBN missing number solverRefactoring complex phone validationsValidation check and...
Is there any use for defining additional entity types in a SOQL FROM clause?
What causes the sudden spool-up sound from an F-16 when enabling afterburner?
How to deal with fear of taking dependencies
Prime joint compound before latex paint?
Is it wise to focus on putting odd beats on left when playing double bass drums?
Can the Produce Flame cantrip be used to grapple, or as an unarmed strike, in the right circumstances?
A poker game description that does not feel gimmicky
Copycat chess is back
Is every set a filtered colimit of finite sets?
If a centaur druid Wild Shapes into a Giant Elk, do their Charge features stack?
Pristine Bit Checking
Extreme, but not acceptable situation and I can't start the work tomorrow morning
Denied boarding due to overcrowding, Sparpreis ticket. What are my rights?
Is ipsum/ipsa/ipse a third person pronoun, or can it serve other functions?
How do I create uniquely male characters?
Unbreakable Formation vs. Cry of the Carnarium
What do you call something that goes against the spirit of the law, but is legal when interpreting the law to the letter?
What is the meaning of "of trouble" in the following sentence?
What does "enim et" mean?
Can I find out the caloric content of bread by dehydrating it?
"My colleague's body is amazing"
Was there ever an axiom rendered a theorem?
Lied on resume at previous job
How to move the player while also allowing forces to affect it
ISBN Number Check
ISBN missing number solverRefactoring complex phone validationsValidation check and code-savingLexer for C- in PythonConnect 4 refine the diagonal checkFile presence check for an automated workflowValidation logic for range check with input can be String or NumberDecide if number is Armstrong numberProgram to check if a date is valid or notCredit card validity check
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ margin-bottom:0;
}
$begingroup$
I’ve recently coded a way of checking a 10-digit ISBN.
I was wondering if the code works to check the numbers, and if there are any flaws in my code.
def isbn(number):
try:
numberreal = number
#keeps real number with "-"
numberzero = number.replace("-", "")
#this makes sure python doesnt drop the first 0 if it is at the start
number = number.replace("-", "")
number = int(number)
number = str(numberzero)
print("The ISBN Number Entered is", numberreal)
num = int(number[0]) * 10 + int(number[1]) * 9 + int(number[2]) * 8 + int(number[3]) * 7 + int(number[4]) * 6 + int(number[5]) * 5 + int(number[6]) * 4 + int(number[7]) * 3 + int(number[8]) * 2
num = num%11
checknum = 11 - num
print("The Check Digit Should Be", checknum, "and the one in the code provided was", number[9])
if int(checknum) == int(number[9]):
print("The Check Digit Provided Is Correct")
else:
print("The Check Digit Provided Is Incorrect")
except ValueError:
print("Not Valid Number")
error()
except IndexError:
print("Not 10 Digits")
error()
def error():
print("Error")
running = True
while running == True:
isbn(input("What is the isbn 10 digit number? "))
restart = input("Do You Want Restart?")
restart = restart.lower()
if restart in ("yes", "y", "ok", "sure", ""):
print("Restartingn" + "-" * 34)
else:
print("closing Down")
running = False
python python-3.x validation
$endgroup$
add a comment |
$begingroup$
I’ve recently coded a way of checking a 10-digit ISBN.
I was wondering if the code works to check the numbers, and if there are any flaws in my code.
def isbn(number):
try:
numberreal = number
#keeps real number with "-"
numberzero = number.replace("-", "")
#this makes sure python doesnt drop the first 0 if it is at the start
number = number.replace("-", "")
number = int(number)
number = str(numberzero)
print("The ISBN Number Entered is", numberreal)
num = int(number[0]) * 10 + int(number[1]) * 9 + int(number[2]) * 8 + int(number[3]) * 7 + int(number[4]) * 6 + int(number[5]) * 5 + int(number[6]) * 4 + int(number[7]) * 3 + int(number[8]) * 2
num = num%11
checknum = 11 - num
print("The Check Digit Should Be", checknum, "and the one in the code provided was", number[9])
if int(checknum) == int(number[9]):
print("The Check Digit Provided Is Correct")
else:
print("The Check Digit Provided Is Incorrect")
except ValueError:
print("Not Valid Number")
error()
except IndexError:
print("Not 10 Digits")
error()
def error():
print("Error")
running = True
while running == True:
isbn(input("What is the isbn 10 digit number? "))
restart = input("Do You Want Restart?")
restart = restart.lower()
if restart in ("yes", "y", "ok", "sure", ""):
print("Restartingn" + "-" * 34)
else:
print("closing Down")
running = False
python python-3.x validation
$endgroup$
$begingroup$
I am sure that you wrote this for the learning experience, at least in part – so but if ISBN parsing is a specific thing on your to-do list, the uninventively-named PyISBN module – pyisbn.readthedocs.org – is something I can personally vouch for, as like a dependably no-nonsense and solid library.Here’s the function in their codebase that’s roughly analogous to what you posted: github.com/JNRowe/pyisbn/blob/master/pyisbn/…
$endgroup$
– fish2000
May 8 '14 at 16:33
add a comment |
$begingroup$
I’ve recently coded a way of checking a 10-digit ISBN.
I was wondering if the code works to check the numbers, and if there are any flaws in my code.
def isbn(number):
try:
numberreal = number
#keeps real number with "-"
numberzero = number.replace("-", "")
#this makes sure python doesnt drop the first 0 if it is at the start
number = number.replace("-", "")
number = int(number)
number = str(numberzero)
print("The ISBN Number Entered is", numberreal)
num = int(number[0]) * 10 + int(number[1]) * 9 + int(number[2]) * 8 + int(number[3]) * 7 + int(number[4]) * 6 + int(number[5]) * 5 + int(number[6]) * 4 + int(number[7]) * 3 + int(number[8]) * 2
num = num%11
checknum = 11 - num
print("The Check Digit Should Be", checknum, "and the one in the code provided was", number[9])
if int(checknum) == int(number[9]):
print("The Check Digit Provided Is Correct")
else:
print("The Check Digit Provided Is Incorrect")
except ValueError:
print("Not Valid Number")
error()
except IndexError:
print("Not 10 Digits")
error()
def error():
print("Error")
running = True
while running == True:
isbn(input("What is the isbn 10 digit number? "))
restart = input("Do You Want Restart?")
restart = restart.lower()
if restart in ("yes", "y", "ok", "sure", ""):
print("Restartingn" + "-" * 34)
else:
print("closing Down")
running = False
python python-3.x validation
$endgroup$
I’ve recently coded a way of checking a 10-digit ISBN.
I was wondering if the code works to check the numbers, and if there are any flaws in my code.
def isbn(number):
try:
numberreal = number
#keeps real number with "-"
numberzero = number.replace("-", "")
#this makes sure python doesnt drop the first 0 if it is at the start
number = number.replace("-", "")
number = int(number)
number = str(numberzero)
print("The ISBN Number Entered is", numberreal)
num = int(number[0]) * 10 + int(number[1]) * 9 + int(number[2]) * 8 + int(number[3]) * 7 + int(number[4]) * 6 + int(number[5]) * 5 + int(number[6]) * 4 + int(number[7]) * 3 + int(number[8]) * 2
num = num%11
checknum = 11 - num
print("The Check Digit Should Be", checknum, "and the one in the code provided was", number[9])
if int(checknum) == int(number[9]):
print("The Check Digit Provided Is Correct")
else:
print("The Check Digit Provided Is Incorrect")
except ValueError:
print("Not Valid Number")
error()
except IndexError:
print("Not 10 Digits")
error()
def error():
print("Error")
running = True
while running == True:
isbn(input("What is the isbn 10 digit number? "))
restart = input("Do You Want Restart?")
restart = restart.lower()
if restart in ("yes", "y", "ok", "sure", ""):
print("Restartingn" + "-" * 34)
else:
print("closing Down")
running = False
python python-3.x validation
python python-3.x validation
edited Apr 30 '14 at 18:05
Jamal♦
30.6k11121227
30.6k11121227
asked Apr 30 '14 at 15:50
Oliver PerringOliver Perring
143138
143138
$begingroup$
I am sure that you wrote this for the learning experience, at least in part – so but if ISBN parsing is a specific thing on your to-do list, the uninventively-named PyISBN module – pyisbn.readthedocs.org – is something I can personally vouch for, as like a dependably no-nonsense and solid library.Here’s the function in their codebase that’s roughly analogous to what you posted: github.com/JNRowe/pyisbn/blob/master/pyisbn/…
$endgroup$
– fish2000
May 8 '14 at 16:33
add a comment |
$begingroup$
I am sure that you wrote this for the learning experience, at least in part – so but if ISBN parsing is a specific thing on your to-do list, the uninventively-named PyISBN module – pyisbn.readthedocs.org – is something I can personally vouch for, as like a dependably no-nonsense and solid library.Here’s the function in their codebase that’s roughly analogous to what you posted: github.com/JNRowe/pyisbn/blob/master/pyisbn/…
$endgroup$
– fish2000
May 8 '14 at 16:33
$begingroup$
I am sure that you wrote this for the learning experience, at least in part – so but if ISBN parsing is a specific thing on your to-do list, the uninventively-named PyISBN module – pyisbn.readthedocs.org – is something I can personally vouch for, as like a dependably no-nonsense and solid library.Here’s the function in their codebase that’s roughly analogous to what you posted: github.com/JNRowe/pyisbn/blob/master/pyisbn/…
$endgroup$
– fish2000
May 8 '14 at 16:33
$begingroup$
I am sure that you wrote this for the learning experience, at least in part – so but if ISBN parsing is a specific thing on your to-do list, the uninventively-named PyISBN module – pyisbn.readthedocs.org – is something I can personally vouch for, as like a dependably no-nonsense and solid library.Here’s the function in their codebase that’s roughly analogous to what you posted: github.com/JNRowe/pyisbn/blob/master/pyisbn/…
$endgroup$
– fish2000
May 8 '14 at 16:33
add a comment |
1 Answer
1
active
oldest
votes
$begingroup$
Right now, the code doesn't work. Your code only validates ISBNs that use Arabic numerals, but some ISBNs can end in an "X". Quoting from the ISBN FAQs:
Why do some ISBNs end in an "X"?
In the case of the check digit, the last digit of the ISBN, the upper case X can appear. The method of determining the check digit for the ISBN is the modulus 11 with the weighting factors 10 to 1. The Roman numeral X is used in lieu of 10 where ten would occur as a check digit.
So you should think about how you’d fix that first.
Comments on the existing isbn()
function
This isn't how I'd write it. Your function doesn’t return a True/False value. The code which acts interactively, and prints things to the user, and the code which validates the ISBN, are both intertwined. I would separate the two. This will make debugging issues like the "X" easier, and you can reuse the validating function later.
For example, if you wanted to enter IBSNs to a database, and verify that the entered numbers were accurate, you could get a True/False value from the function without printing to the console.
Here are some general comments on the existing isbn()
function:
It's not clear what the difference between the
numberzero
,numberreal
andnumber
variables are. This is a side-effect of mixing the validation and printing code.Give it a more specific name, and add a docstring (a way to document functions in Python). Later you may want to validate ISBN-13 codes, and you don't want the namespace cluttered.
There are better ways of handling errors than printing the word "Error" to the console. You could raise a custom
ValueError
, or something else.The line which constructs
num
is excessively long: you can usesum()
and a list comprehension to construct it in a more compact way, and it will make it clearer what formula you're using later down the line.The line
num = num%11
can be replaced bynum %= 11
. Just makes things slightly neater.
With those points in mind, here's how I might rewrite your function:
def validate_isbn10(number):
"""A function for validating ISBN-10 codes."""
formatted_num = number.replace("-", "")
if len(formatted_num) != 10:
raise ValueError('The number %s is not a 10-digit string.' % number)
check_sum = sum(int(formatted_num[i]) * (10 - i) for i in xrange(8))
check_sum %= 11
check_digit = 11 - check_sum
if formatted_num[-1] == "X":
return check_digit == 10
else:
return check_digit == int(formatted_num[-1])
If you wanted to be able to tell the user what the correct check digit should be (in the event of an incorrectly formatted string), then you could factor our a check_digit()
function as well.
I leave it as an exercise to write a separate function which interactively prompts the user for an ISBN-10 code, and tells them whether or nots it correctly formatted.
Comments on the rest of the code
Here are some things that concern me in the rest of your code:
You should wrap the interactive code in a
if __name__ == "__main__":
block. This means that it will only run if the file is executed directly, but you can alsoimport
the file to just get the function definitions (say, if you wanted to use this ISBN validator in a larger project).
The line
while running == True:
. If you're going to compare to booleans, then it's much more idiomatic to writewhile running is True:
, or even better,while running:
. But that's not a good way to do it.
Instead, suppose you have a
interactive_user_isbn()
function which runs the interactive session with the user. Then at the end of that function, if they want to go again, then you can ask them, and if they do, call the function again.
Make the repeat prompt more explicit about what will be repeated, and give them a hint about what they can type to repeat the function.
If they type nothing, then I would err on assuming that they don't want to go again, but that's just my opinion.
Something like:
def interactive_user_isbn():
# ask the user for an ISBN
# check if it's correct
# pay the user a compliment etc
repeat = input("Do you want to check another number? (y/n)")
if repeat.lower() in ["yes", "y", "ok", "sure"]:
print("n")
interactive_user_isbn()
else:
print("Okay, bye!")
$endgroup$
$begingroup$
thnx this is realy helpful and realy helps me learn a lot more about this sort of thing. while running: is a lot better way then I was using so thanks for that.
$endgroup$
– Oliver Perring
May 17 '14 at 10:40
$begingroup$
Should bexrange(9)
I think. See this short clip: youtube.com/watch?v=5qcrDnJg-98
$endgroup$
– Leonid
Apr 17 '16 at 5:06
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f48588%2fisbn-number-check%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
$begingroup$
Right now, the code doesn't work. Your code only validates ISBNs that use Arabic numerals, but some ISBNs can end in an "X". Quoting from the ISBN FAQs:
Why do some ISBNs end in an "X"?
In the case of the check digit, the last digit of the ISBN, the upper case X can appear. The method of determining the check digit for the ISBN is the modulus 11 with the weighting factors 10 to 1. The Roman numeral X is used in lieu of 10 where ten would occur as a check digit.
So you should think about how you’d fix that first.
Comments on the existing isbn()
function
This isn't how I'd write it. Your function doesn’t return a True/False value. The code which acts interactively, and prints things to the user, and the code which validates the ISBN, are both intertwined. I would separate the two. This will make debugging issues like the "X" easier, and you can reuse the validating function later.
For example, if you wanted to enter IBSNs to a database, and verify that the entered numbers were accurate, you could get a True/False value from the function without printing to the console.
Here are some general comments on the existing isbn()
function:
It's not clear what the difference between the
numberzero
,numberreal
andnumber
variables are. This is a side-effect of mixing the validation and printing code.Give it a more specific name, and add a docstring (a way to document functions in Python). Later you may want to validate ISBN-13 codes, and you don't want the namespace cluttered.
There are better ways of handling errors than printing the word "Error" to the console. You could raise a custom
ValueError
, or something else.The line which constructs
num
is excessively long: you can usesum()
and a list comprehension to construct it in a more compact way, and it will make it clearer what formula you're using later down the line.The line
num = num%11
can be replaced bynum %= 11
. Just makes things slightly neater.
With those points in mind, here's how I might rewrite your function:
def validate_isbn10(number):
"""A function for validating ISBN-10 codes."""
formatted_num = number.replace("-", "")
if len(formatted_num) != 10:
raise ValueError('The number %s is not a 10-digit string.' % number)
check_sum = sum(int(formatted_num[i]) * (10 - i) for i in xrange(8))
check_sum %= 11
check_digit = 11 - check_sum
if formatted_num[-1] == "X":
return check_digit == 10
else:
return check_digit == int(formatted_num[-1])
If you wanted to be able to tell the user what the correct check digit should be (in the event of an incorrectly formatted string), then you could factor our a check_digit()
function as well.
I leave it as an exercise to write a separate function which interactively prompts the user for an ISBN-10 code, and tells them whether or nots it correctly formatted.
Comments on the rest of the code
Here are some things that concern me in the rest of your code:
You should wrap the interactive code in a
if __name__ == "__main__":
block. This means that it will only run if the file is executed directly, but you can alsoimport
the file to just get the function definitions (say, if you wanted to use this ISBN validator in a larger project).
The line
while running == True:
. If you're going to compare to booleans, then it's much more idiomatic to writewhile running is True:
, or even better,while running:
. But that's not a good way to do it.
Instead, suppose you have a
interactive_user_isbn()
function which runs the interactive session with the user. Then at the end of that function, if they want to go again, then you can ask them, and if they do, call the function again.
Make the repeat prompt more explicit about what will be repeated, and give them a hint about what they can type to repeat the function.
If they type nothing, then I would err on assuming that they don't want to go again, but that's just my opinion.
Something like:
def interactive_user_isbn():
# ask the user for an ISBN
# check if it's correct
# pay the user a compliment etc
repeat = input("Do you want to check another number? (y/n)")
if repeat.lower() in ["yes", "y", "ok", "sure"]:
print("n")
interactive_user_isbn()
else:
print("Okay, bye!")
$endgroup$
$begingroup$
thnx this is realy helpful and realy helps me learn a lot more about this sort of thing. while running: is a lot better way then I was using so thanks for that.
$endgroup$
– Oliver Perring
May 17 '14 at 10:40
$begingroup$
Should bexrange(9)
I think. See this short clip: youtube.com/watch?v=5qcrDnJg-98
$endgroup$
– Leonid
Apr 17 '16 at 5:06
add a comment |
$begingroup$
Right now, the code doesn't work. Your code only validates ISBNs that use Arabic numerals, but some ISBNs can end in an "X". Quoting from the ISBN FAQs:
Why do some ISBNs end in an "X"?
In the case of the check digit, the last digit of the ISBN, the upper case X can appear. The method of determining the check digit for the ISBN is the modulus 11 with the weighting factors 10 to 1. The Roman numeral X is used in lieu of 10 where ten would occur as a check digit.
So you should think about how you’d fix that first.
Comments on the existing isbn()
function
This isn't how I'd write it. Your function doesn’t return a True/False value. The code which acts interactively, and prints things to the user, and the code which validates the ISBN, are both intertwined. I would separate the two. This will make debugging issues like the "X" easier, and you can reuse the validating function later.
For example, if you wanted to enter IBSNs to a database, and verify that the entered numbers were accurate, you could get a True/False value from the function without printing to the console.
Here are some general comments on the existing isbn()
function:
It's not clear what the difference between the
numberzero
,numberreal
andnumber
variables are. This is a side-effect of mixing the validation and printing code.Give it a more specific name, and add a docstring (a way to document functions in Python). Later you may want to validate ISBN-13 codes, and you don't want the namespace cluttered.
There are better ways of handling errors than printing the word "Error" to the console. You could raise a custom
ValueError
, or something else.The line which constructs
num
is excessively long: you can usesum()
and a list comprehension to construct it in a more compact way, and it will make it clearer what formula you're using later down the line.The line
num = num%11
can be replaced bynum %= 11
. Just makes things slightly neater.
With those points in mind, here's how I might rewrite your function:
def validate_isbn10(number):
"""A function for validating ISBN-10 codes."""
formatted_num = number.replace("-", "")
if len(formatted_num) != 10:
raise ValueError('The number %s is not a 10-digit string.' % number)
check_sum = sum(int(formatted_num[i]) * (10 - i) for i in xrange(8))
check_sum %= 11
check_digit = 11 - check_sum
if formatted_num[-1] == "X":
return check_digit == 10
else:
return check_digit == int(formatted_num[-1])
If you wanted to be able to tell the user what the correct check digit should be (in the event of an incorrectly formatted string), then you could factor our a check_digit()
function as well.
I leave it as an exercise to write a separate function which interactively prompts the user for an ISBN-10 code, and tells them whether or nots it correctly formatted.
Comments on the rest of the code
Here are some things that concern me in the rest of your code:
You should wrap the interactive code in a
if __name__ == "__main__":
block. This means that it will only run if the file is executed directly, but you can alsoimport
the file to just get the function definitions (say, if you wanted to use this ISBN validator in a larger project).
The line
while running == True:
. If you're going to compare to booleans, then it's much more idiomatic to writewhile running is True:
, or even better,while running:
. But that's not a good way to do it.
Instead, suppose you have a
interactive_user_isbn()
function which runs the interactive session with the user. Then at the end of that function, if they want to go again, then you can ask them, and if they do, call the function again.
Make the repeat prompt more explicit about what will be repeated, and give them a hint about what they can type to repeat the function.
If they type nothing, then I would err on assuming that they don't want to go again, but that's just my opinion.
Something like:
def interactive_user_isbn():
# ask the user for an ISBN
# check if it's correct
# pay the user a compliment etc
repeat = input("Do you want to check another number? (y/n)")
if repeat.lower() in ["yes", "y", "ok", "sure"]:
print("n")
interactive_user_isbn()
else:
print("Okay, bye!")
$endgroup$
$begingroup$
thnx this is realy helpful and realy helps me learn a lot more about this sort of thing. while running: is a lot better way then I was using so thanks for that.
$endgroup$
– Oliver Perring
May 17 '14 at 10:40
$begingroup$
Should bexrange(9)
I think. See this short clip: youtube.com/watch?v=5qcrDnJg-98
$endgroup$
– Leonid
Apr 17 '16 at 5:06
add a comment |
$begingroup$
Right now, the code doesn't work. Your code only validates ISBNs that use Arabic numerals, but some ISBNs can end in an "X". Quoting from the ISBN FAQs:
Why do some ISBNs end in an "X"?
In the case of the check digit, the last digit of the ISBN, the upper case X can appear. The method of determining the check digit for the ISBN is the modulus 11 with the weighting factors 10 to 1. The Roman numeral X is used in lieu of 10 where ten would occur as a check digit.
So you should think about how you’d fix that first.
Comments on the existing isbn()
function
This isn't how I'd write it. Your function doesn’t return a True/False value. The code which acts interactively, and prints things to the user, and the code which validates the ISBN, are both intertwined. I would separate the two. This will make debugging issues like the "X" easier, and you can reuse the validating function later.
For example, if you wanted to enter IBSNs to a database, and verify that the entered numbers were accurate, you could get a True/False value from the function without printing to the console.
Here are some general comments on the existing isbn()
function:
It's not clear what the difference between the
numberzero
,numberreal
andnumber
variables are. This is a side-effect of mixing the validation and printing code.Give it a more specific name, and add a docstring (a way to document functions in Python). Later you may want to validate ISBN-13 codes, and you don't want the namespace cluttered.
There are better ways of handling errors than printing the word "Error" to the console. You could raise a custom
ValueError
, or something else.The line which constructs
num
is excessively long: you can usesum()
and a list comprehension to construct it in a more compact way, and it will make it clearer what formula you're using later down the line.The line
num = num%11
can be replaced bynum %= 11
. Just makes things slightly neater.
With those points in mind, here's how I might rewrite your function:
def validate_isbn10(number):
"""A function for validating ISBN-10 codes."""
formatted_num = number.replace("-", "")
if len(formatted_num) != 10:
raise ValueError('The number %s is not a 10-digit string.' % number)
check_sum = sum(int(formatted_num[i]) * (10 - i) for i in xrange(8))
check_sum %= 11
check_digit = 11 - check_sum
if formatted_num[-1] == "X":
return check_digit == 10
else:
return check_digit == int(formatted_num[-1])
If you wanted to be able to tell the user what the correct check digit should be (in the event of an incorrectly formatted string), then you could factor our a check_digit()
function as well.
I leave it as an exercise to write a separate function which interactively prompts the user for an ISBN-10 code, and tells them whether or nots it correctly formatted.
Comments on the rest of the code
Here are some things that concern me in the rest of your code:
You should wrap the interactive code in a
if __name__ == "__main__":
block. This means that it will only run if the file is executed directly, but you can alsoimport
the file to just get the function definitions (say, if you wanted to use this ISBN validator in a larger project).
The line
while running == True:
. If you're going to compare to booleans, then it's much more idiomatic to writewhile running is True:
, or even better,while running:
. But that's not a good way to do it.
Instead, suppose you have a
interactive_user_isbn()
function which runs the interactive session with the user. Then at the end of that function, if they want to go again, then you can ask them, and if they do, call the function again.
Make the repeat prompt more explicit about what will be repeated, and give them a hint about what they can type to repeat the function.
If they type nothing, then I would err on assuming that they don't want to go again, but that's just my opinion.
Something like:
def interactive_user_isbn():
# ask the user for an ISBN
# check if it's correct
# pay the user a compliment etc
repeat = input("Do you want to check another number? (y/n)")
if repeat.lower() in ["yes", "y", "ok", "sure"]:
print("n")
interactive_user_isbn()
else:
print("Okay, bye!")
$endgroup$
Right now, the code doesn't work. Your code only validates ISBNs that use Arabic numerals, but some ISBNs can end in an "X". Quoting from the ISBN FAQs:
Why do some ISBNs end in an "X"?
In the case of the check digit, the last digit of the ISBN, the upper case X can appear. The method of determining the check digit for the ISBN is the modulus 11 with the weighting factors 10 to 1. The Roman numeral X is used in lieu of 10 where ten would occur as a check digit.
So you should think about how you’d fix that first.
Comments on the existing isbn()
function
This isn't how I'd write it. Your function doesn’t return a True/False value. The code which acts interactively, and prints things to the user, and the code which validates the ISBN, are both intertwined. I would separate the two. This will make debugging issues like the "X" easier, and you can reuse the validating function later.
For example, if you wanted to enter IBSNs to a database, and verify that the entered numbers were accurate, you could get a True/False value from the function without printing to the console.
Here are some general comments on the existing isbn()
function:
It's not clear what the difference between the
numberzero
,numberreal
andnumber
variables are. This is a side-effect of mixing the validation and printing code.Give it a more specific name, and add a docstring (a way to document functions in Python). Later you may want to validate ISBN-13 codes, and you don't want the namespace cluttered.
There are better ways of handling errors than printing the word "Error" to the console. You could raise a custom
ValueError
, or something else.The line which constructs
num
is excessively long: you can usesum()
and a list comprehension to construct it in a more compact way, and it will make it clearer what formula you're using later down the line.The line
num = num%11
can be replaced bynum %= 11
. Just makes things slightly neater.
With those points in mind, here's how I might rewrite your function:
def validate_isbn10(number):
"""A function for validating ISBN-10 codes."""
formatted_num = number.replace("-", "")
if len(formatted_num) != 10:
raise ValueError('The number %s is not a 10-digit string.' % number)
check_sum = sum(int(formatted_num[i]) * (10 - i) for i in xrange(8))
check_sum %= 11
check_digit = 11 - check_sum
if formatted_num[-1] == "X":
return check_digit == 10
else:
return check_digit == int(formatted_num[-1])
If you wanted to be able to tell the user what the correct check digit should be (in the event of an incorrectly formatted string), then you could factor our a check_digit()
function as well.
I leave it as an exercise to write a separate function which interactively prompts the user for an ISBN-10 code, and tells them whether or nots it correctly formatted.
Comments on the rest of the code
Here are some things that concern me in the rest of your code:
You should wrap the interactive code in a
if __name__ == "__main__":
block. This means that it will only run if the file is executed directly, but you can alsoimport
the file to just get the function definitions (say, if you wanted to use this ISBN validator in a larger project).
The line
while running == True:
. If you're going to compare to booleans, then it's much more idiomatic to writewhile running is True:
, or even better,while running:
. But that's not a good way to do it.
Instead, suppose you have a
interactive_user_isbn()
function which runs the interactive session with the user. Then at the end of that function, if they want to go again, then you can ask them, and if they do, call the function again.
Make the repeat prompt more explicit about what will be repeated, and give them a hint about what they can type to repeat the function.
If they type nothing, then I would err on assuming that they don't want to go again, but that's just my opinion.
Something like:
def interactive_user_isbn():
# ask the user for an ISBN
# check if it's correct
# pay the user a compliment etc
repeat = input("Do you want to check another number? (y/n)")
if repeat.lower() in ["yes", "y", "ok", "sure"]:
print("n")
interactive_user_isbn()
else:
print("Okay, bye!")
edited May 23 '17 at 12:40
Community♦
1
1
answered Apr 30 '14 at 17:29
alexwlchanalexwlchan
8,1051552
8,1051552
$begingroup$
thnx this is realy helpful and realy helps me learn a lot more about this sort of thing. while running: is a lot better way then I was using so thanks for that.
$endgroup$
– Oliver Perring
May 17 '14 at 10:40
$begingroup$
Should bexrange(9)
I think. See this short clip: youtube.com/watch?v=5qcrDnJg-98
$endgroup$
– Leonid
Apr 17 '16 at 5:06
add a comment |
$begingroup$
thnx this is realy helpful and realy helps me learn a lot more about this sort of thing. while running: is a lot better way then I was using so thanks for that.
$endgroup$
– Oliver Perring
May 17 '14 at 10:40
$begingroup$
Should bexrange(9)
I think. See this short clip: youtube.com/watch?v=5qcrDnJg-98
$endgroup$
– Leonid
Apr 17 '16 at 5:06
$begingroup$
thnx this is realy helpful and realy helps me learn a lot more about this sort of thing. while running: is a lot better way then I was using so thanks for that.
$endgroup$
– Oliver Perring
May 17 '14 at 10:40
$begingroup$
thnx this is realy helpful and realy helps me learn a lot more about this sort of thing. while running: is a lot better way then I was using so thanks for that.
$endgroup$
– Oliver Perring
May 17 '14 at 10:40
$begingroup$
Should be
xrange(9)
I think. See this short clip: youtube.com/watch?v=5qcrDnJg-98$endgroup$
– Leonid
Apr 17 '16 at 5:06
$begingroup$
Should be
xrange(9)
I think. See this short clip: youtube.com/watch?v=5qcrDnJg-98$endgroup$
– Leonid
Apr 17 '16 at 5:06
add a comment |
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f48588%2fisbn-number-check%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
$begingroup$
I am sure that you wrote this for the learning experience, at least in part – so but if ISBN parsing is a specific thing on your to-do list, the uninventively-named PyISBN module – pyisbn.readthedocs.org – is something I can personally vouch for, as like a dependably no-nonsense and solid library.Here’s the function in their codebase that’s roughly analogous to what you posted: github.com/JNRowe/pyisbn/blob/master/pyisbn/…
$endgroup$
– fish2000
May 8 '14 at 16:33