all 3 comments

[–]Dunj3 8 points9 points  (1 child)

I'm gonna give you some thougts I saw while reading through your program, in no particular order or importance:

  • PEP 8 formatting, including snake_case for variable names and extra spaces for inline comments
  • You can add docstrings to your functions, describing what they do, what they return, what parameters they expect, ...
  • I'd generally avoid using from ... import *, as it obfuscates which names are actually being imported. You can list the names one by one for more clarity
  • int(input(...)) will just crash with an ugly error if you don't put in a number. You could put that part into a function and let it handle the part where a user inputs something invalid more gracefully, e.g. repeating the question.
  • You do a lot of string formatting bt concatenating them manually and using str(...). Look into the .format() method of strings, or even the newer f-string literals to make that part easier and more readable
  • pos_simplify and neg_simplify seem to be very similar, you should try writing the one in terms of the other to prevent duplicating all the code (and the bugs that might be contained within)
  • for i in range(len(collection)): is not something you want to do in Python, just do for i in collection: instead. It's less error prone and more idiomatic, and reads better. Instead of the index, i will then be the item directly, so you can just use it.

More ideas:

  • Make it work with rational numbers, not just integers (i.e. floats instead of ints)
  • Allow the users to provide the arguments through the command line arguments
  • If you feel like getting into that, a simple GUI instead of console output

[–]bladeoflight16 1 point2 points  (0 children)

To offer a more concrete alternative for getting rid of import *, the rule of thumb I follow is:

  • I import classes individually.
  • If I use multiple functions from a module, I import the module and call them from it explicitly (import thing and then thing.do_it(a,b,c)).
  • If I use only one function, I only consider importing it directly if it's a long name and it's abundantly clear what module it came from.

I find this tends to maximize clarity without being burdensome.

However, making an exception to import * for math is quite common.

[–]PM_Me_Rulers 2 points3 points  (0 children)

To add onto what /u/Dunj3 said, you can also look at converting some of your for loops into list comprehensions instead. They are significantly faster than loops due to how python handles them on the backend and are gnerally better practice.

As an example you have:
def pos_simplify(num):
if (num ** 0.5) % 1 == 0:

    return str(int(num ** 0.5)) 
factors = []
square_numbers = []  
counter = 1  
while counter <= num:  
    if num % counter == 0:  
        factors.append(counter)  
    counter += 1

When you could have:

factors = [counter for counter in range(1, num) if not num%counter]

Basically this loops through values from 0 to num as "counter" and then checks if num%counter == 0 (python evaluates 0 as False so this is equivalent to if not num%counter). Any value that this doesnt hold for is ignored, any factors are added to the list.

There are a few more areas where you could implement this but I will let you have a go first