Duck typing with otherwise useless statements (remotely Pythonic)?Replacements for switch statement in Python?What's the canonical way to check for type in Python?How to determine a Python variable's type?What is the python “with” statement designed for?What is duck typing?Duck typing in the C# compilerHow to handle “duck typing” in Python?Minimum Methods for Ordering with Duck Typing in Python 3.1Is this duck-typing in Python?Python type annotation for custom duck type
Did I make a mistake by ccing email to boss to others?
How were servants to the Kaiser of Imperial Germany treated and where may I find more information on them
Echo with obfuscation
Grepping string, but include all non-blank lines following each grep match
How do I prevent inappropriate ads from appearing in my game?
Do you waste sorcery points if you try to apply metamagic to a spell from a scroll but fail to cast it?
Typing CO_2 easily
How much do grades matter for a future academia position?
Why didn’t Eve recognize the little cockroach as a living organism?
If the only attacker is removed from combat, is a creature still counted as having attacked this turn?
Would this string work as string?
Why is the sun approximated as a black body at ~ 5800 K?
How many people need to be born every 8 years to sustain population?
Anime with legendary swords made from talismans and a man who could change them with a shattered body
Animation: customize bounce interpolation
What should be the ideal length of sentences in a blog post for ease of reading?
"Oh no!" in Latin
Sound waves in different octaves
Why does the Persian emissary display a string of crowned skulls?
What is the meaning of "You've never met a graph you didn't like?"
Check if object is null and return null
Is there anyway, I can have two passwords for my wi-fi
Deciphering cause of death?
How to test the sharpness of a knife?
Duck typing with otherwise useless statements (remotely Pythonic)?
Replacements for switch statement in Python?What's the canonical way to check for type in Python?How to determine a Python variable's type?What is the python “with” statement designed for?What is duck typing?Duck typing in the C# compilerHow to handle “duck typing” in Python?Minimum Methods for Ordering with Duck Typing in Python 3.1Is this duck-typing in Python?Python type annotation for custom duck type
The below will raise a TypeError for floats.
from math import factorial
def divide_factorials(a, b):
return factorial(a) / factorial(b)
>>> divide_factorials(6.1, 5)
*** ValueError: factorial() only accepts integral values
That's perfect until I want to incorporate an optimization.
def divide_factorials(a, b):
if a == b:
return 1
return factorial(a) / factorial(b)
Now I've lost my TypeError from floats where stop == start.
>>> divide_factorials(3.3, 3.3)
1
I could get my TypeError back with isinstance, but that requires my knowing exactly what will and will not work in factorial (or any other function I might be calling). It's tempting to do something like
def divide_factorials(a, b):
# duck type first
factorial((a + b) % 1)
if a == b:
return 1
return factorial(a) / factorial(b)
This seems more robust, but less obvious. For (I'm sure) good reasons, I haven't seen this pattern before. What's the best reason not to do it?
I could dress it up with assert or try/except, but
assert factorial((a + b) % 1) is not None
# or
try:
factorial((a + b) % 1)
except TypeError:
raise TypeError
seem, if anything, a bit MORE cryptic.
python python-3.x duck-typing
add a comment |
The below will raise a TypeError for floats.
from math import factorial
def divide_factorials(a, b):
return factorial(a) / factorial(b)
>>> divide_factorials(6.1, 5)
*** ValueError: factorial() only accepts integral values
That's perfect until I want to incorporate an optimization.
def divide_factorials(a, b):
if a == b:
return 1
return factorial(a) / factorial(b)
Now I've lost my TypeError from floats where stop == start.
>>> divide_factorials(3.3, 3.3)
1
I could get my TypeError back with isinstance, but that requires my knowing exactly what will and will not work in factorial (or any other function I might be calling). It's tempting to do something like
def divide_factorials(a, b):
# duck type first
factorial((a + b) % 1)
if a == b:
return 1
return factorial(a) / factorial(b)
This seems more robust, but less obvious. For (I'm sure) good reasons, I haven't seen this pattern before. What's the best reason not to do it?
I could dress it up with assert or try/except, but
assert factorial((a + b) % 1) is not None
# or
try:
factorial((a + b) % 1)
except TypeError:
raise TypeError
seem, if anything, a bit MORE cryptic.
python python-3.x duck-typing
"incorporate an optimization". Have you tested how longreturn factorial(a) / factorial(b)
takes to execute? Is this in a tight loop? "Premature optimisation...."
– roganjosh
Mar 7 at 22:02
add a comment |
The below will raise a TypeError for floats.
from math import factorial
def divide_factorials(a, b):
return factorial(a) / factorial(b)
>>> divide_factorials(6.1, 5)
*** ValueError: factorial() only accepts integral values
That's perfect until I want to incorporate an optimization.
def divide_factorials(a, b):
if a == b:
return 1
return factorial(a) / factorial(b)
Now I've lost my TypeError from floats where stop == start.
>>> divide_factorials(3.3, 3.3)
1
I could get my TypeError back with isinstance, but that requires my knowing exactly what will and will not work in factorial (or any other function I might be calling). It's tempting to do something like
def divide_factorials(a, b):
# duck type first
factorial((a + b) % 1)
if a == b:
return 1
return factorial(a) / factorial(b)
This seems more robust, but less obvious. For (I'm sure) good reasons, I haven't seen this pattern before. What's the best reason not to do it?
I could dress it up with assert or try/except, but
assert factorial((a + b) % 1) is not None
# or
try:
factorial((a + b) % 1)
except TypeError:
raise TypeError
seem, if anything, a bit MORE cryptic.
python python-3.x duck-typing
The below will raise a TypeError for floats.
from math import factorial
def divide_factorials(a, b):
return factorial(a) / factorial(b)
>>> divide_factorials(6.1, 5)
*** ValueError: factorial() only accepts integral values
That's perfect until I want to incorporate an optimization.
def divide_factorials(a, b):
if a == b:
return 1
return factorial(a) / factorial(b)
Now I've lost my TypeError from floats where stop == start.
>>> divide_factorials(3.3, 3.3)
1
I could get my TypeError back with isinstance, but that requires my knowing exactly what will and will not work in factorial (or any other function I might be calling). It's tempting to do something like
def divide_factorials(a, b):
# duck type first
factorial((a + b) % 1)
if a == b:
return 1
return factorial(a) / factorial(b)
This seems more robust, but less obvious. For (I'm sure) good reasons, I haven't seen this pattern before. What's the best reason not to do it?
I could dress it up with assert or try/except, but
assert factorial((a + b) % 1) is not None
# or
try:
factorial((a + b) % 1)
except TypeError:
raise TypeError
seem, if anything, a bit MORE cryptic.
python python-3.x duck-typing
python python-3.x duck-typing
asked Mar 7 at 22:00
ShayShay
439413
439413
"incorporate an optimization". Have you tested how longreturn factorial(a) / factorial(b)
takes to execute? Is this in a tight loop? "Premature optimisation...."
– roganjosh
Mar 7 at 22:02
add a comment |
"incorporate an optimization". Have you tested how longreturn factorial(a) / factorial(b)
takes to execute? Is this in a tight loop? "Premature optimisation...."
– roganjosh
Mar 7 at 22:02
"incorporate an optimization". Have you tested how long
return factorial(a) / factorial(b)
takes to execute? Is this in a tight loop? "Premature optimisation...."– roganjosh
Mar 7 at 22:02
"incorporate an optimization". Have you tested how long
return factorial(a) / factorial(b)
takes to execute? Is this in a tight loop? "Premature optimisation...."– roganjosh
Mar 7 at 22:02
add a comment |
1 Answer
1
active
oldest
votes
It's indeed quite cryptic to call a function that is meant to perform calculations for the sole purpose of making a type validation. It makes the intention of the code unclear, and therefore makes the code un-Pythonic.
I would simply repeat the same explicit type validation if it's important. Moreover, the right way to optimize factorial division is to not call a factorial function, but to iterate from the divisor plus one to the dividend and aggregate the product instead:
def divide_factorials(a, b):
if not all(isinstance(i, int) for i in (a, b)):
raise TypeError('divide_factorials() only accepts integral values')
product = 1
for i in range(b + 1, a + 1):
product *= i
return product
factorial((5.5 + 4.5) % 1) will indeed raise a ValueError. This is the kind of surprise I'm trying to avoid by duck typing. But I do take your point that it's unclear.
– Shay
Mar 8 at 16:21
Ah indeed I forgot that5.5 + 4.5
still results in a floating number. I've removed that point from my answer then.
– blhsing
Mar 8 at 16:28
You seem to be requiring that all inputs are floats, not that all inputs are integers.
– user2357112
Mar 8 at 16:30
@user2357112 Oops that was obvious. Not sure what I was thinking. Thanks.
– blhsing
Mar 8 at 16:31
1
This does require a >= b. But I'll accept this as the most explicit and obvious pattern for such a function.
– Shay
Mar 11 at 11:39
add a comment |
Your Answer
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: "1"
;
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: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
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%2fstackoverflow.com%2fquestions%2f55053480%2fduck-typing-with-otherwise-useless-statements-remotely-pythonic%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
It's indeed quite cryptic to call a function that is meant to perform calculations for the sole purpose of making a type validation. It makes the intention of the code unclear, and therefore makes the code un-Pythonic.
I would simply repeat the same explicit type validation if it's important. Moreover, the right way to optimize factorial division is to not call a factorial function, but to iterate from the divisor plus one to the dividend and aggregate the product instead:
def divide_factorials(a, b):
if not all(isinstance(i, int) for i in (a, b)):
raise TypeError('divide_factorials() only accepts integral values')
product = 1
for i in range(b + 1, a + 1):
product *= i
return product
factorial((5.5 + 4.5) % 1) will indeed raise a ValueError. This is the kind of surprise I'm trying to avoid by duck typing. But I do take your point that it's unclear.
– Shay
Mar 8 at 16:21
Ah indeed I forgot that5.5 + 4.5
still results in a floating number. I've removed that point from my answer then.
– blhsing
Mar 8 at 16:28
You seem to be requiring that all inputs are floats, not that all inputs are integers.
– user2357112
Mar 8 at 16:30
@user2357112 Oops that was obvious. Not sure what I was thinking. Thanks.
– blhsing
Mar 8 at 16:31
1
This does require a >= b. But I'll accept this as the most explicit and obvious pattern for such a function.
– Shay
Mar 11 at 11:39
add a comment |
It's indeed quite cryptic to call a function that is meant to perform calculations for the sole purpose of making a type validation. It makes the intention of the code unclear, and therefore makes the code un-Pythonic.
I would simply repeat the same explicit type validation if it's important. Moreover, the right way to optimize factorial division is to not call a factorial function, but to iterate from the divisor plus one to the dividend and aggregate the product instead:
def divide_factorials(a, b):
if not all(isinstance(i, int) for i in (a, b)):
raise TypeError('divide_factorials() only accepts integral values')
product = 1
for i in range(b + 1, a + 1):
product *= i
return product
factorial((5.5 + 4.5) % 1) will indeed raise a ValueError. This is the kind of surprise I'm trying to avoid by duck typing. But I do take your point that it's unclear.
– Shay
Mar 8 at 16:21
Ah indeed I forgot that5.5 + 4.5
still results in a floating number. I've removed that point from my answer then.
– blhsing
Mar 8 at 16:28
You seem to be requiring that all inputs are floats, not that all inputs are integers.
– user2357112
Mar 8 at 16:30
@user2357112 Oops that was obvious. Not sure what I was thinking. Thanks.
– blhsing
Mar 8 at 16:31
1
This does require a >= b. But I'll accept this as the most explicit and obvious pattern for such a function.
– Shay
Mar 11 at 11:39
add a comment |
It's indeed quite cryptic to call a function that is meant to perform calculations for the sole purpose of making a type validation. It makes the intention of the code unclear, and therefore makes the code un-Pythonic.
I would simply repeat the same explicit type validation if it's important. Moreover, the right way to optimize factorial division is to not call a factorial function, but to iterate from the divisor plus one to the dividend and aggregate the product instead:
def divide_factorials(a, b):
if not all(isinstance(i, int) for i in (a, b)):
raise TypeError('divide_factorials() only accepts integral values')
product = 1
for i in range(b + 1, a + 1):
product *= i
return product
It's indeed quite cryptic to call a function that is meant to perform calculations for the sole purpose of making a type validation. It makes the intention of the code unclear, and therefore makes the code un-Pythonic.
I would simply repeat the same explicit type validation if it's important. Moreover, the right way to optimize factorial division is to not call a factorial function, but to iterate from the divisor plus one to the dividend and aggregate the product instead:
def divide_factorials(a, b):
if not all(isinstance(i, int) for i in (a, b)):
raise TypeError('divide_factorials() only accepts integral values')
product = 1
for i in range(b + 1, a + 1):
product *= i
return product
edited Mar 8 at 16:30
answered Mar 7 at 22:31
blhsingblhsing
39.5k41743
39.5k41743
factorial((5.5 + 4.5) % 1) will indeed raise a ValueError. This is the kind of surprise I'm trying to avoid by duck typing. But I do take your point that it's unclear.
– Shay
Mar 8 at 16:21
Ah indeed I forgot that5.5 + 4.5
still results in a floating number. I've removed that point from my answer then.
– blhsing
Mar 8 at 16:28
You seem to be requiring that all inputs are floats, not that all inputs are integers.
– user2357112
Mar 8 at 16:30
@user2357112 Oops that was obvious. Not sure what I was thinking. Thanks.
– blhsing
Mar 8 at 16:31
1
This does require a >= b. But I'll accept this as the most explicit and obvious pattern for such a function.
– Shay
Mar 11 at 11:39
add a comment |
factorial((5.5 + 4.5) % 1) will indeed raise a ValueError. This is the kind of surprise I'm trying to avoid by duck typing. But I do take your point that it's unclear.
– Shay
Mar 8 at 16:21
Ah indeed I forgot that5.5 + 4.5
still results in a floating number. I've removed that point from my answer then.
– blhsing
Mar 8 at 16:28
You seem to be requiring that all inputs are floats, not that all inputs are integers.
– user2357112
Mar 8 at 16:30
@user2357112 Oops that was obvious. Not sure what I was thinking. Thanks.
– blhsing
Mar 8 at 16:31
1
This does require a >= b. But I'll accept this as the most explicit and obvious pattern for such a function.
– Shay
Mar 11 at 11:39
factorial((5.5 + 4.5) % 1) will indeed raise a ValueError. This is the kind of surprise I'm trying to avoid by duck typing. But I do take your point that it's unclear.
– Shay
Mar 8 at 16:21
factorial((5.5 + 4.5) % 1) will indeed raise a ValueError. This is the kind of surprise I'm trying to avoid by duck typing. But I do take your point that it's unclear.
– Shay
Mar 8 at 16:21
Ah indeed I forgot that
5.5 + 4.5
still results in a floating number. I've removed that point from my answer then.– blhsing
Mar 8 at 16:28
Ah indeed I forgot that
5.5 + 4.5
still results in a floating number. I've removed that point from my answer then.– blhsing
Mar 8 at 16:28
You seem to be requiring that all inputs are floats, not that all inputs are integers.
– user2357112
Mar 8 at 16:30
You seem to be requiring that all inputs are floats, not that all inputs are integers.
– user2357112
Mar 8 at 16:30
@user2357112 Oops that was obvious. Not sure what I was thinking. Thanks.
– blhsing
Mar 8 at 16:31
@user2357112 Oops that was obvious. Not sure what I was thinking. Thanks.
– blhsing
Mar 8 at 16:31
1
1
This does require a >= b. But I'll accept this as the most explicit and obvious pattern for such a function.
– Shay
Mar 11 at 11:39
This does require a >= b. But I'll accept this as the most explicit and obvious pattern for such a function.
– Shay
Mar 11 at 11:39
add a comment |
Thanks for contributing an answer to Stack Overflow!
- 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.
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%2fstackoverflow.com%2fquestions%2f55053480%2fduck-typing-with-otherwise-useless-statements-remotely-pythonic%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
"incorporate an optimization". Have you tested how long
return factorial(a) / factorial(b)
takes to execute? Is this in a tight loop? "Premature optimisation...."– roganjosh
Mar 7 at 22:02