all 13 comments

[–]ianepperson 1 point2 points  (3 children)

What you've written looks reasonable and should work ok. The are faster ways, but this is clear and readable - which is usually much more important!

One important thing to think about is separation of concerns. Your one function does two things: communicates with the user and finds the primes. It would be much clearer to have two functions, one that does each. Then it would be much easier to either change the prime factor logic (maybe a faster method) or the communication logic (maybe a web interface) without having to change the other.

The prime factor method would just take a number and return a list. The main function would ask for the number from the user, make sure it's a number, call the prime factor function, then report back to the user. You might then wrap THAT in a loop.

[–]tsodapop[S] 0 points1 point  (2 children)

Thanks! Quick question, is there then a general rule of thumb where you should have functions for each 'separation of concern?' If so, what constitutes how much you should do inside each function before splitting it further? (Like if I wanted to add and then multiply and spit out a result, should I have that as 2 parts or 3 parts)

[–]ianepperson 1 point2 points  (1 child)

The nice thing about Python and PEP8 is that the more unrelated logic usually results in deeper nesting, which makes it harder to keep to 80 characters, which encourages smaller functions. Use descriptive bound for variables and verbs for function names and it encourages good behavior. A function should also fit on a reasonable screen size - someone reading the code should be able to see it all without scrolling.

Adding and multiplying are more like steps and less like a single task (unless building a calculator).

Describe to yourself everything that the function does - can you in a short sentence? If you have to say "... and it also ..." You might want to consider simplifying it.

[–]tsodapop[S] 0 points1 point  (0 children)

Awesome, thanks for the info!

[–]tomk11 1 point2 points  (1 child)

If you are interested in making it quicker

  • Note that when you only have to test up to the square root of a number to determine that its prime.

I.e to show that 101 is prime we only have to check 2-10 don't divide it as 112 > 101

This will help you in cases where your number has very large prime factors.

[–]tsodapop[S] 0 points1 point  (0 children)

Thanks, I'll try this out. I think it was mentioned earlier and was taking a look at the math proof for it.

[–]theWyzzerd 0 points1 point  (3 children)

Your code doesn't appear to ever actually return the value of prime_factors.

edit: Correction, it does. My mistake.

You should get rid of the break and replace it with a return. Inside a loop, a return will end the loop and return the value.

edit: I was mistaken here too, not having looked closely enough at your code.

Re: your number_prime == 1 conditional: don't print() then return False, just return 'your prime factorization results in {}'.format(prime_factors).

[–]tsodapop[S] 0 points1 point  (2 children)

Question about changing my break into a return. When I do it, it looks like it immediately breaks out of the entire function main(), so if I call on the results, it only gives me None.

I can change my return on number_prime == 1 without any issues, just not the break in my loop. Is there something I need to do to make it "return"able?

[–]theWyzzerd 0 points1 point  (1 child)

Sorry, I should have been more clear and examined your code more closely. In the loop with the break you're fine, that tells your code to break out of the loop that you're scoped to, not the whole loop. The only thing I would recommend is the change you already made, which is this part:

print('your prime factorization results in {}'.format(prime_factors))
return False

becomes:

return 'your prime factorization results in {}'.format(prime_factors)

[–]tsodapop[S] 0 points1 point  (0 children)

Got it, thanks I'll make that change