Sampling method
(削除) is the wrong kind of sampling here since it draws k random samples from the given population/alphabet without repetition. Instead you should should use sample()
(削除ここまで)choices()
which allows repetition of the same items.
Normally you want as much entropy as possible in the given "space" (here: k = 15 items chosen from N = 66 Arabic digits, basic Latin letters and some punctuation). If you disallow repetitions you reduce the size of the key space (although not significantly1) and risk more (frequent) collisions at no benefit and more costly sample computation2.
Source of (pseudo-)randomness
You should also consider that the random
module’s default (pseudo-)random number generator is not normally "safe". See Gaipher’s comment for a possible safe alternative.
Avoid magic numbers, allow parameters if possible
Additionally you should avoid unexplained "magic numbers" (like 15) and allow parameters (with sensible defaults) for arbitrarily chosen values (like length
).
Resulting code
def generate_unique_key(length=15):
array = # ... construct character set
return "".join(random.choices(array, k=length))
For Python versions prior to 3.6 you can provide a simple implementations of choices()
yourself:
import random
try:
random_choices = random.choices
except AttributeError:
import itertools
def random_choices(population, *, k=1):
return map(random.choice, itertools.repeat(population, k))
1 Key space comparison:
- with repetition: \$N^k = 66^{15} \approx 2.0 \cdot 10^{27}\$
- without repetition: \$\prod^{N}_{i=N-k+1} i = \frac{!N}{!(N - k)} = \frac{!66}{!(66 - 15)} \approx 3.5 \cdot 10^{26}\$
2 An optimal algorithm for random samples without repetition is more complex than one with repetition and requires either \$O(k)\$ intermediate storage or \$O(k^2)\$ runtime (with k being the sample size) to keep track of previously drawn items.
Sampling method
(削除) is the wrong kind of sampling here since it draws k random samples from the given population/alphabet without repetition. Instead you should should use sample()
(削除ここまで)choices()
which allows repetition of the same items.
Normally you want as much entropy as possible in the given "space" (here: k = 15 items chosen from N = 66 Arabic digits, basic Latin letters and some punctuation). If you disallow repetitions you reduce the size of the key space (although not significantly1) and risk more (frequent) collisions at no benefit and more costly sample computation2.
Source of (pseudo-)randomness
You should also consider that the random
module’s default (pseudo-)random number generator is not normally "safe". See Gaipher’s comment for a possible safe alternative.
Avoid magic numbers, allow parameters if possible
Additionally you should avoid unexplained "magic numbers" (like 15) and allow parameters (with sensible defaults) for arbitrarily chosen values (like length
).
Resulting code
def generate_unique_key(length=15):
array = # ... construct character set
return "".join(random.choices(array, k=length))
For Python versions prior to 3.6 you can provide a simple implementations of choices()
yourself:
import random
try:
random_choices = random.choices
except AttributeError:
def random_choices(population, *, k=1):
return map(random.choice, itertools.repeat(population, k))
1 Key space comparison:
- with repetition: \$N^k = 66^{15} \approx 2.0 \cdot 10^{27}\$
- without repetition: \$\prod^{N}_{i=N-k+1} i = \frac{!N}{!(N - k)} = \frac{!66}{!(66 - 15)} \approx 3.5 \cdot 10^{26}\$
2 An optimal algorithm for random samples without repetition is more complex than one with repetition and requires either \$O(k)\$ intermediate storage or \$O(k^2)\$ runtime (with k being the sample size) to keep track of previously drawn items.
Sampling method
(削除) is the wrong kind of sampling here since it draws k random samples from the given population/alphabet without repetition. Instead you should should use sample()
(削除ここまで)choices()
which allows repetition of the same items.
Normally you want as much entropy as possible in the given "space" (here: k = 15 items chosen from N = 66 Arabic digits, basic Latin letters and some punctuation). If you disallow repetitions you reduce the size of the key space (although not significantly1) and risk more (frequent) collisions at no benefit and more costly sample computation2.
Source of (pseudo-)randomness
You should also consider that the random
module’s default (pseudo-)random number generator is not normally "safe". See Gaipher’s comment for a possible safe alternative.
Avoid magic numbers, allow parameters if possible
Additionally you should avoid unexplained "magic numbers" (like 15) and allow parameters (with sensible defaults) for arbitrarily chosen values (like length
).
Resulting code
def generate_unique_key(length=15):
array = # ... construct character set
return "".join(random.choices(array, k=length))
For Python versions prior to 3.6 you can provide a simple implementations of choices()
yourself:
import random
try:
random_choices = random.choices
except AttributeError:
import itertools
def random_choices(population, *, k=1):
return map(random.choice, itertools.repeat(population, k))
1 Key space comparison:
- with repetition: \$N^k = 66^{15} \approx 2.0 \cdot 10^{27}\$
- without repetition: \$\prod^{N}_{i=N-k+1} i = \frac{!N}{!(N - k)} = \frac{!66}{!(66 - 15)} \approx 3.5 \cdot 10^{26}\$
2 An optimal algorithm for random samples without repetition is more complex than one with repetition and requires either \$O(k)\$ intermediate storage or \$O(k^2)\$ runtime (with k being the sample size) to keep track of previously drawn items.
Sampling method
(削除) is the wrong kind of sampling here since it draws k random samples from the given population/alphabet without repetition. Instead you should should use sample()
(削除ここまで)choices()
which allows repetition of the same items.
Normally you want as much entropy as possible in the given "space" (here: k = 15 items chosen from N = 66 Arabic digits, basic Latin letters and some punctuation). If you disallow repetitions you reduce the size of the key space (although not significantly1) and risk more (frequent) collisions at no benefit and more costly sample computation2.
Source of (pseudo-)randomness
You should also consider that the random
module’s default (pseudo-)random number generator is not normally "safe". See Gaipher’s comment for a possible safe alternative.
Avoid magic numbers, allow parameters if possible
Additionally you should avoid unexplained "magic numbers" (like 15) and allow parameters (with sensible defaults) for arbitrarily chosen values (like length
).
Resulting code
def generate_unique_key(length=15):
array = # ... construct character set
return "".join(random.choices(array, k=length))
For Python versions prior to 3.6 you can provide a simple implementations of choices()
yourself:
import random
try:
random_choices = random.choices
except AttributeError:
def random_choices(population, *, k=1):
return map(random.choice, itertools.repeat(population, k))
1 Key space comparison:
- with repetition: \$N^k = 66^{15} \approx 2.0 \cdot 10^{27}\$
- without repetition: \$\prod^{N}_{i=N-k+1} i = \frac{!N}{!(N - k)} = \frac{!66}{!(66 - 15)} \approx 3.5 \cdot 10^{26}\$
2 An optimal algorithm for random samples without repetition is more complex than one with repetition and either requires either \$O(k)\$ intermediate storage or \$O(k^2)\$ runtime (with k being the sample size) to keep track of previously drawn items.
Sampling method
(削除) is the wrong kind of sampling here since it draws k random samples from the given population/alphabet without repetition. Instead you should should use sample()
(削除ここまで)choices()
which allows repetition of the same items.
Normally you want as much entropy as possible in the given "space" (here: k = 15 items chosen from N = 66 Arabic digits, basic Latin letters and some punctuation). If you disallow repetitions you reduce the size of the key space (although not significantly1) and risk more (frequent) collisions at no benefit and more costly sample computation2.
Source of (pseudo-)randomness
You should also consider that the random
module’s default (pseudo-)random number generator is not normally "safe". See Gaipher’s comment for a possible safe alternative.
Avoid magic numbers, allow parameters if possible
Additionally you should avoid unexplained "magic numbers" and allow parameters (with sensible defaults) for arbitrarily chosen values.
Resulting code
def generate_unique_key(length=15):
array = # ... construct character set
return "".join(random.choices(array, k=length))
For Python versions prior to 3.6 you can provide a simple implementations of choices()
yourself:
import random
try:
random_choices = random.choices
except AttributeError:
def random_choices(population, *, k=1):
return map(random.choice, itertools.repeat(population, k))
1 Key space comparison:
- with repetition: \$N^k = 66^{15} \approx 2.0 \cdot 10^{27}\$
- without repetition: \$\prod^{N}_{i=N-k+1} i = \frac{!N}{!(N - k)} = \frac{!66}{!(66 - 15)} \approx 3.5 \cdot 10^{26}\$
2 An optimal algorithm for random samples without repetition is more complex than one with repetition and either requires \$O(k)\$ intermediate storage or \$O(k^2)\$ runtime (with k being the sample size).
Sampling method
(削除) is the wrong kind of sampling here since it draws k random samples from the given population/alphabet without repetition. Instead you should should use sample()
(削除ここまで)choices()
which allows repetition of the same items.
Normally you want as much entropy as possible in the given "space" (here: k = 15 items chosen from N = 66 Arabic digits, basic Latin letters and some punctuation). If you disallow repetitions you reduce the size of the key space (although not significantly1) and risk more (frequent) collisions at no benefit and more costly sample computation2.
Source of (pseudo-)randomness
You should also consider that the random
module’s default (pseudo-)random number generator is not normally "safe". See Gaipher’s comment for a possible safe alternative.
Avoid magic numbers, allow parameters if possible
Additionally you should avoid unexplained "magic numbers" (like 15) and allow parameters (with sensible defaults) for arbitrarily chosen values (like length
).
Resulting code
def generate_unique_key(length=15):
array = # ... construct character set
return "".join(random.choices(array, k=length))
For Python versions prior to 3.6 you can provide a simple implementations of choices()
yourself:
import random
try:
random_choices = random.choices
except AttributeError:
def random_choices(population, *, k=1):
return map(random.choice, itertools.repeat(population, k))
1 Key space comparison:
- with repetition: \$N^k = 66^{15} \approx 2.0 \cdot 10^{27}\$
- without repetition: \$\prod^{N}_{i=N-k+1} i = \frac{!N}{!(N - k)} = \frac{!66}{!(66 - 15)} \approx 3.5 \cdot 10^{26}\$
2 An optimal algorithm for random samples without repetition is more complex than one with repetition and requires either \$O(k)\$ intermediate storage or \$O(k^2)\$ runtime (with k being the sample size) to keep track of previously drawn items.
Sampling method
(削除) is the wrong kind of sampling here since it draws k random samples from the given population/alphabet without repetition. Instead you should should use sample()
(削除ここまで)choices()
which allows repetition of the same items.
Normally you want as much entropy as possible in the given "space" (here: k = 15 items chosen from N = 66 Arabic digits, basic Latin letters and some punctuation). If you disallow repetitions you reduce the size of the key space (although not significantly1) and risk more (frequent) collisions at no benefit and more costly sample computation2.
Source of (pseudo-)randomness
You should also consider that the random
module’s default (pseudo-)random number generator is not normally "safe". See Gaipher’s comment for a possible safe alternative.
Avoid magic numbers, allow parameters if possible
Additionally you should avoid unexplained "magic numbers" and allow parameters (with sensible defaults) for arbitrarily chosen values.
Resulting code
def generate_unique_key(length=15):
array = # ... construct character set
return "".join(random.choices(array, k=length))
For Python versions prior to 3.6 you can provide a simple implementations of choices()
yourself:
import random
try:
random_choices = random.choices
except AttributeError:
def random_choices(population, *, k=1):
return map(random.choice, itertools.repeat(population, k))
1 Key space comparison:
- with repetition: \$N^k = 66^{15} \approx 2.0 \cdot 10^{27}\$
- without repetition: \$\prod^{N}_{i=N-k+1} i = \frac{!N}{!(N - k)} = \frac{!66}{!(66 - 15)} \approx 3.5 \cdot 10^{26}\$
2 An optimal algorithm for random samples without repetition is more complex than one with repetition and either requires \$O(k)\$ intermediate storage or \$O(k^2)\$ runtime (with k being the sample size).
Sampling method
(削除) is the wrong kind of sampling here since it draws k random samples from the given population/alphabet without repetition. Instead you should should use sample()
(削除ここまで)choices()
which allows repetition of the same items.
Normally you want as much entropy as possible in the given "space" (here: k = 15 items chosen from N = 66 Arabic digits, basic Latin letters and some punctuation). If you disallow repetitions you reduce the size of the key space significantly1 and risk more (frequent) collisions at no benefit and more costly sample computation2.
Source of (pseudo-)randomness
You should also consider that the random
module’s default (pseudo-)random number generator is not normally "safe". See Gaipher’s comment for a possible safe alternative.
Avoid magic numbers, allow parameters if possible
Additionally you should avoid unexplained "magic numbers" and allow parameters (with sensible defaults) for arbitrarily chosen values.
Resulting code
def generate_unique_key(length=15):
array = # ... construct character set
return "".join(random.choices(array, k=length))
For Python versions prior to 3.6 you can provide a simple implementations of choices()
yourself:
import random
try:
random_choices = random.choices
except AttributeError:
def random_choices(population, *, k=1):
return map(random.choice, itertools.repeat(population, k))
1 Key space comparison:
- with repetition: \$N^k = 66^{15} \approx 2.0 \cdot 10^{27}\$
- without repetition: \$\prod^{N}_{i=N-k+1} i = \frac{!N}{!(N - k)} = \frac{!66}{!(66 - 15)} \approx 3.5 \cdot 10^{26}\$
2 An optimal algorithm for random samples without repetition is more complex than one with repetition and either requires \$O(k)\$ intermediate storage or \$O(k^2)\$ runtime (with k being the sample size).
Sampling method
(削除) is the wrong kind of sampling here since it draws k random samples from the given population/alphabet without repetition. Instead you should should use sample()
(削除ここまで)choices()
which allows repetition of the same items.
Normally you want as much entropy as possible in the given "space" (here: k = 15 items chosen from N = 66 Arabic digits, basic Latin letters and some punctuation). If you disallow repetitions you reduce the size of the key space (although not significantly1) and risk more (frequent) collisions at no benefit and more costly sample computation2.
Source of (pseudo-)randomness
You should also consider that the random
module’s default (pseudo-)random number generator is not normally "safe". See Gaipher’s comment for a possible safe alternative.
Avoid magic numbers, allow parameters if possible
Additionally you should avoid unexplained "magic numbers" and allow parameters (with sensible defaults) for arbitrarily chosen values.
Resulting code
def generate_unique_key(length=15):
array = # ... construct character set
return "".join(random.choices(array, k=length))
For Python versions prior to 3.6 you can provide a simple implementations of choices()
yourself:
import random
try:
random_choices = random.choices
except AttributeError:
def random_choices(population, *, k=1):
return map(random.choice, itertools.repeat(population, k))
1 Key space comparison:
- with repetition: \$N^k = 66^{15} \approx 2.0 \cdot 10^{27}\$
- without repetition: \$\prod^{N}_{i=N-k+1} i = \frac{!N}{!(N - k)} = \frac{!66}{!(66 - 15)} \approx 3.5 \cdot 10^{26}\$
2 An optimal algorithm for random samples without repetition is more complex than one with repetition and either requires \$O(k)\$ intermediate storage or \$O(k^2)\$ runtime (with k being the sample size).