Converting an angle in degrees to a pretty string representing it in radians Given an angle in degrees, output a pretty string representation of its value in radians as a fraction.

Where pretty means:


Simplified as much as possible.
With no unnecessary ones.
Using the Unicode character that represents pi: π
With a single minus in front if negative (a minus at the denominator is not allowed).


For example: degrees_to_pretty_radians(-120) #=&gt; '-2π/3'



I wanted to write this in Python too to compare it to how it looked implemented in Javascript

The code is pretty straightforward and passes a lot of test-cases, but I am still interested in any kind of feedback:

def degrees_to_pretty_radians(angle: "in degrees") \
                    -&gt; "Pretty string for the value in radians.":
    """
    &gt;&gt;&gt; tests = [0, 1, 18, 31, 45, 60, 120, 180, 270, 360, 480]
    &gt;&gt;&gt; all_tests = tests + [-x for x in tests]
    &gt;&gt;&gt; for angle in all_tests: print(angle, degrees_to_pretty_radians(angle))
    0 0π
    1 π/180
    18 π/10
    31 31π/180
    45 π/4
    60 π/3
    120 2π/3
    180 π
    270 3π/2
    360 2π
    480 8π/3
    0 0π
    -1 -π/180
    -18 -π/10
    -31 -31π/180
    -45 -π/4
    -60 -π/3
    -120 -2π/3
    -180 -π
    -270 -3π/2
    -360 -2π
    -480 -8π/3

    """
    gcd = fractions.gcd(angle, 180)
    denominator = "" if 180 // gcd == 1 else "/{}".format(180 // gcd)
    numerator = "" if abs(angle // gcd) == 1 else abs(angle // gcd)
    sign = "-" if angle &lt; 0 else ""
    return "{}{}π{}".format(sign, numerator, denominator)
Here are some thoughts on your code:


I'm not too fond of function annotations – Maybe it's just me, but I find the function annotations a slightly confusing syntax addition. I would rather extend the docstring with this information.
Compress the doctests a little – You get bonus points for using doctests, but I would compress the output somewhat. Maybe build an array of result values, and do a comparison against that. Or simply reduce the number of values. As it stands, it is more doctests code than actual code doing something useful
Avoid duplicating calculations – You do the 180 // gcd and abs(angle // gcd) twice. One for the if and one as a result. This could possibly read better using temporary variables to both avoid the double calculation, and to simplify the ternary statements.


However there is an even neater solution to avoid most of your code, and that is to use all of the capabilities of the fractions module. Using this module your function can be reduced to:

rads = fractions.Fraction(angle, 180)
return "{}π/{}".format(angle, rads.numerator, rads.denominator)


Of course, this does return mostly the same as your function returns, but it does return some of the basic cases like "0π/1" or "1π/3". These could be handled using some ternary operations, which leads us back to code similar to your original code (but without exposing the calculations, and with compression (not reduction) of test cases):

def degrees_to_pretty_radians(degrees):
    """Return the degrees in fractions of π:

    &gt;&gt;&gt; tests = [0, 1, 18, 31, 45, 60, 120, 180, 270, 360, 480]
    &gt;&gt;&gt; all_tests = tests + [-x for x in tests]
    &gt;&gt;&gt; expected_result = ['0π', 'π/180', 'π/10', '31π/180',
    ...        'π/4', 'π/3', '2π/3', 'π', '3π/2', '2π', '8π/3',
    ...        '0π', '-π/180', '-π/10', '-31π/180',
    ...        '-π/4', '-π/3', '-2π/3', '-π', '-3π/2', '-2π', '-8π/3']
    &gt;&gt;&gt; actual_result = [degrees_to_pretty_radians(d) for d in all_tests]
    &gt;&gt;&gt; actual_result == expected_result
    True
    """

    rads = fractions.Fraction(degrees, 180)
    numerator = "" if rads.numerator == 1 else \
                "-" if rads.numerator == -1 else \
                rads.numerator
    denominator = "" if rads.denominator == 1 else \
                  "/{}".format(rads.denominator)
    return "{}π{}".format(numerator, denominator)