Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
refactoring
#1
Hi all, I dont like my implementation of a cat-human age converter, could you please suggest a a more pythonic approach?

"""
    First, allow 15 human years for the first year of your cat's life.
    Then, add 9 years for the second year. For instance, a 2-year-old cat will be approximately 24 human years.
    Next, add 4 human years for each successive year of your cat's life.
    Finally, refer to the accompanying cat-age-to-human-age chart to double check your calculation.
"""

def human_age(cat_age):
    total = 0
    if cat_age == 1:
        total += 15
    if cat_age == 2:
        total += 15 + 9
    if cat_age > 2:
        total += (15 + 9) + (cat_age - 2) * 4
    return total
Reply
#2
I don't think that's necessarily un-Pythonic. If al of the comparisons were >=, to 1, 2, and 3; then you could avoid dupicating the 15 and the 9:

def human_age(cat_age):
    total = 0
    if cat_age >= 1:
        total += 15
    if cat_age >= 2:
        total += 9
    if cat_age >= 3:
        total += (cat_age - 2) * 4
    return total
If you wanted to get rid of the if statements altogether, you could have a list of the human years for each cat year ([15, 9, 4, 4, 4, ...]) and them sum the relevant number of years. Of course, you can't be sure how long that list needs to be. Wikipedia says the oldest reported cat age was 38 years old, although some of those numbers look pretty sketchy.
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#3
def cat2man(cat_years):
    human_years = {1:15, 2:24}
    return human_years.get(cat_years, 24 + (cat_years-2)*4)

for cat_years in range(1, 5):
    print(f'{cat_years} cat year(s) are equal to {cat2man(cat_years)} human years')
def cat2man2(cat_years):
    human_years = {0:15, 1:9}
    return sum(human_years.get(n, 4) for  n in range(cat_years))

for cat_years in range(1, 5):
    print(f'{cat_years} cat year(s) are equal to {cat2man2(cat_years)} human years')
these are two implementations that will print
1 cat year(s) are equal to 15 human years
2 cat year(s) are equal to 24 human years
3 cat year(s) are equal to 28 human years
4 cat year(s) are equal to 32 human years
It's up to you to decide if they are more pythonic. I qgree with ichabood that your code is not neccessarily un-pythonic
maybe I would simplify it like
def human_age(cat_age):
    if cat_age == 1:
        total = 15
    elif cat_age == 2:
        total = 24
    elif cat_age >= 3:
        total = 24 + (cat_age - 2) * 4
    return total
or even

def human_age(cat_age):
    if cat_age == 1:
        return 15
    elif cat_age == 2:
        return 24
    elif cat_age >= 3:
        return 24 + (cat_age - 2) * 4
all of the above may need extra lines of code to handle incorrect/invalid input like negative, float, str, etc.
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#4
Another way is to combine sum, itertools.repeat() and slice:

from itertools import repeat

def human_age(cat_age): 
    return sum([15, 9, *repeat(4, cat_age - 2)][:cat_age])
This handles 0 age correctly as well.
I'm not 'in'-sane. Indeed, I am so far 'out' of sane that you appear a tiny blip on the distant coast of sanity. Bucky Katt, Get Fuzzy

Da Bishop: There's a dead bishop on the landing. I don't know who keeps bringing them in here. ....but society is to blame.
Reply
#5
Good old Python, with it's one, obvious way to do things. Big Grin
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#6
from itertools import repeat, islice


def human_age(cat_age):
    return sum(islice((15, 9, *repeat(4, cat_age - 2)), 0, cat_age))
def human_age(cat_age):
    formula = (cat_age - 2) * 4
    return sum(islice((15, 9, formula), 0, cat_age))
But for beginners this is hard to understand. Most people do have problems with functional style.
I like the itertools approach very much, because you can process with it infinite data without blowing up your memory consumption. But in general the iteration is slower, than working with list-comprehension.
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply
#7
Perhaps a bit simpler to understand

def human_age(cat_age):
    return (cat_age>0)*15+(cat_age>1)*9+(cat_age>2)*(cat_age-2)*4
Also works for 0.
Reply
#8
The Zen of Python: Readability counts.

just kidding. :D
Reply
#9
Here is a very readable solution
def human_age(cat_age):
    x = cat_age
    return 8 - 3 * abs(x - 1) - 2.5 * abs(x - 2) + 9.5 * x
It also works for fractional ages such as 4.5 years.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Generalized Dice refactoring Beginner_coder123 2 2,225 Feb-05-2019, 08:45 AM
Last Post: Beginner_coder123
  Python Connect 4 refactoring Beginner_coder123 6 3,771 Oct-29-2018, 05:30 PM
Last Post: Beginner_coder123

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020