Reputation: 1759
I am trying to work out how to pass itertools.product a dynamic number of arguments.
I have the following code which worked as expected printing out lines with each line having 4 characters in a different order:
#!/usr/bin/env python3.5
import sys, itertools, multiprocessing, functools
alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ12234567890!@#$%^&*?,()-=+[]/;"
num_parts = 4
part_size = len(alphabet) // num_parts
def do_job(first_bits):
for x in itertools.product(first_bits, alphabet, alphabet, alphabet):
print(''.join(x))
if __name__ == '__main__':
pool = multiprocessing.Pool(processes=4)
results = []
for i in range(num_parts):
if i == num_parts - 1:
first_bit = alphabet[part_size * i :]
else:
first_bit = alphabet[part_size * i : part_size * (i+1)]
pool.apply_async(do_job, (first_bit,))
pool.close()
pool.join()
Then I tried to make it completely dynamic using the following code, where the number of alphabet arguments is created on the fly based on the num_parts variable:
#!/usr/bin/env python3.5
import sys, itertools, multiprocessing, functools
alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ12234567890!@#$%^&*?,()-=+[]/;"
num_parts = 4
part_size = len(alphabet) // num_parts
dynamicArgs = []
def do_job(first_bits):
for x in itertools.product(first_bits, *dynamicArgs):
print(''.join(x))
if __name__ == '__main__':
pool = multiprocessing.Pool(processes=4)
results = []
for x in range(num_parts-1):
dynamicArgs.append(alphabet)
for i in range(num_parts):
if i == num_parts - 1:
first_bit = alphabet[part_size * i :]
else:
first_bit = alphabet[part_size * i : part_size * (i+1)]
pool.apply_async(do_job, (first_bit,))
pool.close()
pool.join()
But this does not work as expected... it outputs lines with one character on each line and iterates over the alphabet only a single time.
How can I pass a dynamic number of alphabet variables as arguments to itertools.product ?
Thanks for your time.
Upvotes: 2
Views: 1082
Reputation: 180391
You can just multiply the list of strings:
def do_job(first_bits):
for x in itertools.product(first_bits, *[alphabet] * 3):
You could also use itertools.repeat:
from itertools import repeat
def do_job(first_bits, times):
for x in itertools.product(first_bits, *repeat(alphabet, times)):
Upvotes: 1
Reputation: 6963
Is this what you are trying to do?
import sys, itertools, multiprocessing, functools
alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ12234567890!@#$%^&*?,()-=+[]/;"
repeats = 5
alphabets = [ alphabet ] * repeats
def do_job(first_bits):
for x in itertools.product(first_bits, *alphabets):
print(''.join(x))
do_job('12345')
You can use the *
operator on arrays which repeats the elements.
Output:
1aaaaa
1aaaab
1aaaac
1aaaad
1aaaae
1aaaaf
1aaaag
1aaaah
1aaaai
1aaaaj
1aaaak
[...]
Upvotes: 0