Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'm a freshman in Python world, I used to program in C.

I wrote a function/method that returns the power of a number:

def pow(x, y):

    powered = x

    if y == 0:
        return 1

    while y > 1:
        powered *= x

        y -= 1

    return powered

Mine is a logic question (correctly): if I set y = 0 then it returns \$1\$, but on the last line of the code I wrote return powered then = x.

Does return work like as break?

share|improve this question
up vote 20 down vote accepted

return means "Eureka! I have found the answer! It is …." It hands that result back to the caller and stops executing any more code in this function.

Unlike x**y, your function gives incorrect results for negative or non-integer values of y. You should note that caveat in a docstring.

The standard way to do counting loops in Python is to use range() (or, in Python 2, xrange()).

To reduce the complexity of your code, you should avoid unnecessary special cases.

def pow(x, y):
    """Raise x to the power y, where y must be a nonnegative integer."""
    result = 1
    for _ in range(y):   # using _ to indicate throwaway iteration variable
        result *= x
    return result

This particular looping pattern (starting with some initial value and repeatedly applying an operation to the result) could be reduced to a one-liner:

from functools import reduce  # Optional in Python 2, required in Python 3

def pow(x, y):
    """Raise x to the power y, where y must be a nonnegative integer."""
    return reduce(lambda result, _: result * x, range(y), 1)

This solution is admittedly foreign-looking to a C programmer. The reduce() function uses 1 as the starting value (equivalent to result = 1 in the first solution). For each _ in range(y), it does result = result * x. lambda is just a way to define a simple function on the spot.


A more efficient algorithm would be repeated squaring.

share|improve this answer
3  
Hello! I up-voted your answer. I especially liked the first part of it, where you explain in a very newbie friendly way what return is, what a possible constraint over the operation parameters is, and what is the standard practice for operations like these in python. I also very much liked your last code, it's very beautiful, but I believe it's a little bit too much for a newbie to grok, since as far as I can understand it requires you to know map, filter and reduce from functional programming to truly understand it, so a newbie is more likely to copy and paste it without understanding it. – NlightNFotis Feb 15 at 21:53
    
I may be very wrong on my remarks however (the one about the reduce solution being too much for a newbie to grok). – NlightNFotis Feb 15 at 21:54
    
@NlightNFotis I have to agree, it is much better than mine. – Joe Wallis Feb 15 at 21:55
    
Best explanation of return, first code is very smooth, second one is: "what?". Thnk! – r0ck3I_I Feb 15 at 21:59
    
This is why the beginner tag is useful. – Legato Feb 16 at 2:45

Does 'return' works as 'break'?

No. What functions as a break is that you have a condition (y > 1) which will be essentially reduced to being false at some time, since for every iteration of the loop, you decrement the conditional variable (so no matter how big a value it is, it's bound to become less than one at some point, making the conditional expression evaluate to false).

At that point, return just returns the result of the computation that has happened in the loop, which is being stored in powered.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Apart from that, you have a very beautiful problem that can be solved using recursion. You can do that and use python's version of the C ternary operator (A if B else C), in order to arrive to a very beautiful and pythonic solution, that I consider to be very much in the spirit of computer science:

def pow(x, y):
    return 1 if y == 0 else x * pow(x, y - 1)

This may look weird for a newbie, but it's actually easier if you understand what happens. Let's go through it:

First of all, let's see the nature of a power computation: 2 ^ 5 is essentially (2 * 2 * 2 * 2 * 2). Our code produces the following call stack:

pow(2, 5)
2 * pow(2, 4)
2 * 2 * pow(2, 3)
2 * 2 * 2 * pow(2, 2)
2 * 2 * 2 * 2 * pow(2, 1)
2 * 2 * 2 * 2 * 2 * pow(2, 0)
2 * 2 * 2 * 2 * 2 * 1    # because of our base case that the condition eventually get's reduced to
2 * 2 * 2 * 2 * 2 
2 * 2 * 2 * 4
2 * 2 * 8
2 * 16
32

I do not know if the above is super useful to you, because that depends on your programming skills at this point, but since you mentioned you already know C, I reckoned that you may be already exposed to algorithmic concepts such as recursion and I thought that demonstrating this syntax and the concept in a nice solution might help you understand how powerful this concept is and how you could utilize it in your programs.

share|improve this answer
    
Yes, I know how iterations work. My question is about return: if y = zero then it returns 1, but going on there is another return. Does function close itself when I hit first return? – r0ck3I_I Feb 15 at 21:37
    
@r0ck3I_I Yes, it does. However, don't think about that this way. Your first return is there only as a sentinel, and that code path is only activated once you have a call like pow(x, 0) where x can be anything. In all other cases where y is not 0, then that branch is not followed, and you actually execute the loop below, and return the result of the computation after the loop condition evaluates to false. – NlightNFotis Feb 15 at 21:40
    
@r0ck3I_I In other words, you don't go through the first return at all for any y that isn't 0. – NlightNFotis Feb 15 at 21:42
    
Note that recursion is a nice academic exercise, but not recommended in practice, especially if the recursion might be very deep. – 200_success Feb 15 at 21:50
    
Ternary operator is great, Thnk! – r0ck3I_I Feb 15 at 21:51

If you didn't know you can use the builtin power function x ** y.


You should reduce the amount of blank lines, and use a for loop, i.e:

for _ in range(y):
    powered *= x

You also return x if y is negative. This is incorrect as \$x^{-y} = \frac{1}{x^y}\$.

To amend this you can create another guard clause:

if y < 0:
    return 1.0 / pow(x, -y)

Note a float cannot be passed to range so pow(4, 2.0) would now be invalid. To amend this you can use int.

def pow(x, y):
    y = int(y)
share|improve this answer
    
I know there is a**n operator. thnk anyway! – r0ck3I_I Feb 15 at 21:40
    
What happens with negative y ? – RobAu Feb 16 at 13:00
1  
@RobAu When you commented it'd return x the same as OP's. Thank you for pointing this out as I've now addressed this error. – Joe Wallis Feb 16 at 13:19

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.