Package: namednumber
NamedNumberpip install namednumberNamed number is a simple package which generates unique names which correspond one-to-one with numbers.NamedNumbersubclassesint, making it versatile and easy to use. This can be used to generate fun names that are easy to rember for
log records, database entries, products, temporary passwords, etc.Getting StartedbasicwhycustomCommand LineShufflinglimitationsencryption placeholderStylizingGetting startedbasicCreate an integer with a seemingly randomly shuffled name associated with itfromnamednumberimportNamedNumberx=NamedNumber(50)print(f"{x=}")# x=<destructive rhino (50)>print(str(x))# destructive rhinoMapping is one to one and reversible so you can also look up a number by its nameprint(int(NamedNumber("destructive rhino")))# 50whyfunjust becausegenerate easy to remember names for files, records, parts, etc.flexible pigis easier to remember than116994use for auto-generated temporary passwords or two-step verificationmathDo math on it and get results in the same named format (see fancy_number.py for how this works)print(f"{x+1=}")# x+1=<crucial impala (51)>x*=2print(f"{x=}")# x=<huge crocodile (100)>custom formatSpecify your own format using common wordsets and character setsy=NamedNumber(422,"Bob saw%4%%adjective% %plural_animals% which were all%color%")print(f"{y=}")# <Bob saw 3 impressive wombats which were all maroon (422)>custom wordlistsSpecify your own custom wordlistsz=NamedNumber(30,"%emotion%_%animal%",emotion=['happy','sad','angry','hungry'])print(f"{z=}")# z=<happy_rabbit (30)>saved formatSave name formats and use them to generate numbersfromnamednumberimportRandomizedNameFmtfmt=RandomizedNameFmt("%emotion% %animal% %hex#5%",emotion=['happy','sad','angry','hungry'])print(f"{fmt(0)=}")# fmt(0)=<sad skunk 3113e (0)>print(f"{fmt[1]=}")# fmt[1]=<happy woodchuck a48ef (1)>print(f"{fmt[2:10:3]=}")# fmt[2:10:3]=[<hungry kookaburra 3ec9f (2)>, <hungry iguana 841c4 (5)>, <sad shark 11041 (8)>]moderately interestingSee the individual values of the componentsprint(dict(x))# {'huge': 151, 'crocodile': 29}Command Linegenerate a random numbernamednumberconvert a numbernamednumber 51or multiplenamednumber 51 52namednumber :5namednumber 10:15namednumber 20:40:7specify formatnamednumber :4 --fmt="%emotion% %pet%" --emotion=["happy","sad","angry","hungry"] --pet=["puppy","kitten","turtle","lizard"]specify --shuffle (default) or --incnamednumber :8 --fmt="%emotion% %pet%"  --inc --emotion=["happy","sad","angry","hungry"] --pet=["puppy","kitten","turtle","lizard"]specify seednamednumber 50 --seed=321ShufflingproblemThe default functionality of theNameFmtobject is to use the first wordlist as the high bit, second as next highest,
etc. and to convert a number to a list of indices for the bases. Therefore, it will by default produce ordered  incrementing results.fromnamednumberimportNameFmtfmt=NameFmt(fmt="%first% %second%",first=["red","green","blue"],second=["car","bike"])print(fmt[:])# [<red car (0)>, <red bike (1)>, <green car (2)>, <green bike (3)>, <blue car (4)>, <blue bike (5)>]solutionIn some cases this is the desired result, but in other cases it is not. Therefore, we need some reversible way of
scrambling the numbers, so that we instead get this.fmt=RandomizedNameFmt(fmt="%first% %second%",first=["red","green","blue"],second=["car","bike"])print(fmt[:])# [<blue car (0)>, <green bike (1)>, <red car (2)>, <green car (3)>, <red bike (4)>, <blue bike (5)>]One easy way to do this is to create a one-to-one mapping is to create a shuffled list of numbers and use theindex <-> valuemapping. This works well for small wordsets but scales poorly as it requires you to precompute
the large shuffled list and then store it in memory or some form of a memory-mapped file.limitationsRandomizedNameFmtworks usingnp.random.permutation, but it can bevery slow to initialize if used with sets of length > (1<<23).
Therefore, due to memory and performance concerns,max_size_allowed = 1 << 23. UseRandomizedNameFmt.plot_performanceto plot
initialization time for varying sized optionsets.encryption placeholderWe don't yet have a great solution, but we have left a few functions which can be overwritten to use whatever shuffling algorithm you desire.classMyNameFmt(NameFmt):definit_cipher(self):# setup herepassdefencrypt(self,i):return(7*i+23)%self.max_numberdefdecrypt(self,i):returnint((i-23%self.max_number)/7)my_fmt=MyNameFmt()my_fmt.plot_encryption(50)print(my_fmt[:5])# [<all chimpanzee (0)>, <all doe (1)>, <all fish (2)>, <all goat (3)>, <all horse (4)>]StylizingTo allow for additional fine-tuning of the string, we have also included placeholders for stylizing and de-stylizing the names.classsPoNGEboBNameFmt(RandomizedNameFmt):defreformat(self,name):NAME=name.upper()n=int(len(name)/2+1)upper=self.rng.permutation([0]*n+[1]*n)return"".join([NAME[i]ifupper[i]elsename[i]foriinrange(len(name))])defdeformat(self,name):returnname.lower()s_fmt=sPoNGEboBNameFmt()print(s_fmt[:5])# [<CLean GOat (0)>, <SuBjecTIve BaT (1)>, <inVALuAbLE boNObo (2)>, <TiGht groUnDHOG (3)>, <BroWn yAK (4)>]Optionswordlistsload your own wordlist from file using theWordlistclass..json,.ymlare supported. for.txtfiles or other formats it is assumed that there is one word per line.fromoptionsimportWordlistfromname_fmtimportRandomizedNameFmtw=Wordlist("wordlists/128_singular_animals.txt")r=RandomizedNameFmt("%animal%",animal=w)pre-existing listswordsetsprint(list(options.wordsets.keys()))# ['colors_16', 'singular_animals_128', 'plural_animals_128', 'rgb_24bit', 'singular_nouns_1k', 'plural_nouns_1k',# 'adjectives_1k']charsetsprint(list(options.charsets.keys()))# ['binary', 'octadecimal', 'decimal', 'hexadecimal', 'lowercase', 'uppercase', 'punctuation', 'whitespace',# 'ascii_128', 'ascii_128_unescaped', 'ascii_256', 'ascii_256_unescaped', 'ascii_512', 'ascii_512_unescaped',# 'ascii_1028', 'ascii_1028_unescaped', 'greek_lowercase', 'greek_uppercase', 'vowels_lowercase',# 'vowels_uppercase', 'vowels', 'consonants_lowercase', 'consonants_uppercase', 'consonants', 'alphabet',# 'alphanumeric_lowercase', 'alphanumeric_uppercase', 'alphanumeric', 'greek_alphabet']wordset aliasesprint(list(options.wordset_aliases.keys()))# ['colors', 'color', 'plural_animal', 'plural_animals', 'animals', 'singular_animal', 'animal', 'plural_nouns',# 'plural_noun', 'singular_nouns', 'singular_noun', 'noun', 'adjectives', 'adjective']charset aliasesprint(list(options.charset_aliases.keys()))# ['ascii_lowercase', 'az', 'ascii_uppercase', 'AZ', 'ALPHABET', 'aZ', 'english_alphabet', 'az9', 'AZ9', 'aZ9',# '09', 'digits', 'digit', '07', 'octdigits', 'octdigit', 'hexdigits', 'hexdigit', 'hex', 'hs', 'bin', 'bs',# 'printable', 'greek', 'GREEK', 'VOWELS', 'VOWEL', 'CONSONANTS', 'CONSONANT', 'vowel', 'consonant']examplefmt=NameFmt("%greek#7% %hex#4%")print([fmt.random_named_number()for_inrange(5)])# [<λΥΞΓιΕΑ 82 (34166216153218)>, <πκΟΧβΣγ 3c (47605451108924)>, <ΟξημΓψΞ 47 (119835652408647)>, <Ιψεσζωπ 78 (101633973378936)>, <τΞζΕκυΨ 9b (58779657092763)>]