Jul-20-2017, 02:52 PM
For example, let's rewrite your program to use itertools. If there's no other benefit, I hope you'd agree that it's at least easier to read (and much shorter), which is a nice benefit, but is unrelated to speed.
import itertools import string import time var = 3 if var == 1: printable = list(string.printable) for i in range(5): del printable[-1] elif var == 2: printable = list(str(string.ascii_uppercase + string.ascii_lowercase)) elif var == 3: printable = list(string.ascii_lowercase) password = input("What is the password? -> ") def ispass(guess): return "".join(guess) == password def find_password(): attempt_length = 0 while True: attempt_length += 1 guesses = itertools.product(printable, repeat=attempt_length) for guess in guesses: if ispass(guess): return guess print("char added") #guess = find_password() import cProfile cProfile.run("guess = find_password()") # prints correct guess, or incorrect if len(guess) exceded limit print("The password is: " + "".join(guess))The profiler gives us this:
Output:What is the password? -> spam
char added
char added
char added
689617 function calls in 0.165 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.165 0.165 <string>:1(<module>)
6 0.000 0.000 0.000 0.000 cp437.py:18(encode)
344799 0.072 0.000 0.106 0.000 eggs.py:17(ispass)
1 0.058 0.058 0.165 0.165 eggs.py:21(find_password)
6 0.000 0.000 0.000 0.000 {built-in method _codecs.charmap_encode}
1 0.000 0.000 0.165 0.165 {built-in method builtins.exec}
3 0.001 0.000 0.001 0.000 {built-in method builtins.print}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
344799 0.034 0.000 0.034 0.000 {method 'join' of 'str' objects}
The password is: spam
This is much faster (0.767 seconds down to 0.165 seconds). Now we see that the ispass() function and the inbuilt str.join() methods are the big hogs. So, let's rewrite the ispass() function to avoid calling str.join...# convert it to a tuple # "spam" => ("s", "p", "a", "m") password = tuple(password) def ispass(guess): return guess == password
Output:What is the password? -> spam
char added
char added
char added
344818 function calls in 0.091 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.091 0.091 <string>:1(<module>)
6 0.000 0.000 0.000 0.000 cp437.py:18(encode)
344799 0.035 0.000 0.035 0.000 eggs.py:21(ispass)
1 0.055 0.055 0.091 0.091 eggs.py:25(find_password)
6 0.000 0.000 0.000 0.000 {built-in method _codecs.charmap_encode}
1 0.000 0.000 0.091 0.091 {built-in method builtins.exec}
3 0.001 0.000 0.001 0.000 {built-in method builtins.print}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
The password is: spam
BOOM! Now it's fast enough for us to do 5 character passwords without hating our life too much...Output:What is the password? -> spams
char added
char added
char added
char added
8964817 function calls in 2.255 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 2.255 2.255 <string>:1(<module>)
8 0.000 0.000 0.000 0.000 cp437.py:18(encode)
8964793 0.859 0.000 0.859 0.000 eggs.py:21(ispass)
1 1.395 1.395 2.255 2.255 eggs.py:25(find_password)
8 0.000 0.000 0.000 0.000 {built-in method _codecs.charmap_encode}
1 0.000 0.000 2.255 2.255 {built-in method builtins.exec}
4 0.001 0.000 0.001 0.000 {built-in method builtins.print}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
The password is: spams
There's a few other things we can do, but that's all I've got time for now.