11
\$\begingroup\$

The code below generates only 10 email domains. To me, this is bruteforce programming. Is there another random integer library? Could I use something like random.seed() in C++?

What is a more elegant way to generate 100 emails names using some Python libs/APIs?

import random
domains = [ "hotmail.com", "gmail.com", "aol.com", "mail.com" , "mail.kz", "yahoo.com"]
letters = ["a", "b", "c", "d","e", "f", "g", "h", "i", "j", "k", "l"]

def get_one_random_domain(domains):
        return domains[random.randint( 0, len(domains)-1)]


def get_one_random_name(letters):
    email_name = ""
    for i in range(7):
        email_name = email_name + letters[random.randint(0,11)]
    return email_name

def generate_random_emails():

    for i in range(0,10):
         one_name = str(get_one_random_name(letters))
         one_domain = str(get_one_random_domain(domains))         
         print(one_name  + "@" + one_domain)

def main():                
    generate_random_emails()

In get_one_random_name(), how can I make this email_name string grow with random letters without using "+ "?

How can I choose letters randomly and put them together without +?

\$\endgroup\$
  • \$\begingroup\$ This question still doesn't make sense; if anything, it's a worse fit here than SO. What exactly is the problem with the standard library random module? It has a seed function, although it's not clear what you'd use it for. \$\endgroup\$ – jonrsharpe Jul 28 '14 at 21:48
  • 1
    \$\begingroup\$ By the way, if you're going to be using these in examples or anything where people might misinterpret them as legitimate email addresses, you might want to use only the domain example.com. \$\endgroup\$ – michaelb958--GoFundMonica Jul 29 '14 at 2:35
22
\$\begingroup\$

From this Stack Overflow question :

import random

foo = ['a', 'b', 'c', 'd', 'e']
print(random.choice(foo))

In your case,

def get_one_random_domain(domains):
        return domains[random.randint( 0, len(domains)-1)]

becomes :

def get_one_random_domain(domains):
        return random.choice(domains)

and maybe removes the need for a function in the first place.


Your letters list can easily be defined with a list comprehension and some manipulation of ord and chr :

>>> [chr(ord('a')+i) for i in range(12)]
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l']

As suggested in the comments, you can also use string.ascii_lowercase[:12]


Now, your get_one_random_name could be easily improved.

def get_one_random_name(letters):
    email_name = ""
    for i in range(7):
        email_name = email_name + letters[random.randint(0,11)]
    return email_name

using the previous trick, it becomes :

def get_one_random_name(letters):
    email_name = ""
    for i in range(7):
        email_name = email_name + random.choice(letters)
    return email_name

Also, here is a recommandation from PEP 8 :

For example, do not rely on CPython's efficient implementation of in-place string concatenation for statements in the form a += b or a = a + b. This optimization is fragile even in CPython (it only works for some types) and isn't present at all in implementations that don't use refcounting. In performance sensitive parts of the library, the ''.join() form should be used instead. This will ensure that concatenation occurs in linear time across various implementations.

In your case, you can easily build a list of random letters and call join.

def get_one_random_name(letters):
    return ''.join(random.choice(letters) for i in range(7))

In generate_random_emails :

  • you don't need conversions.
  • you don't need temporary variables
  • you don't need the first argument of range if it is 0.

so you get:

def generate_random_emails():
    for i in range(0,10):
         print(get_one_random_name(letters) + '@' + get_one_random_domain(domains))

Also, it might be a good idea to return a list instead of printing values to make code easier to reuse.


At this stage, the code looks like :

import random
domains = [ "hotmail.com", "gmail.com", "aol.com", "mail.com" , "mail.kz", "yahoo.com"]
letters = string.ascii_lowercase[:12] 

def get_one_random_domain(domains):
    return random.choice(domains)

def get_one_random_name(letters):
    return ''.join(random.choice(letters) for i in range(7))

def generate_random_emails():
    return [get_one_random_name(letters) + '@' + get_one_random_domain(domains) for i in range(10)]

def main():                
    print(generate_random_emails())


if __name__ == "__main__":
    main()

A good idea would be to change the function names and add arguments instead of hard coded values :

import random
domains = [ "hotmail.com", "gmail.com", "aol.com", "mail.com" , "mail.kz", "yahoo.com"]
letters = string.ascii_lowercase[:12]

def get_random_domain(domains):
    return random.choice(domains)

def get_random_name(letters, length):
    return ''.join(random.choice(letters) for i in range(length))

def generate_random_emails(nb, length):
    return [get_random_name(letters, length) + '@' + get_random_domain(domains) for i in range(nb)]

def main():
    print(generate_random_emails(10, 7))

if __name__ == "__main__":
    main()
\$\endgroup\$
  • 10
    \$\begingroup\$ amazing, this codereview site is better than stackoverflow \$\endgroup\$ – ERJAN Jul 28 '14 at 14:31
  • 1
    \$\begingroup\$ For letters, use string.ascii_lowercase[:12]. \$\endgroup\$ – ecatmur Jul 28 '14 at 17:03
  • \$\begingroup\$ Thank you! I've updated my answer to take into account your comment. I've learnt something today :) \$\endgroup\$ – SylvainD Jul 28 '14 at 17:11
  • \$\begingroup\$ @Josay, how does this last line "get_random_domain(domains) for i in range() ] work? how does python allow for loop go in the end? \$\endgroup\$ – ERJAN Jul 29 '14 at 0:25
  • \$\begingroup\$ just a note: string is missing in the import statement \$\endgroup\$ – tuned May 13 '16 at 8:29

Not the answer you're looking for? Browse other questions tagged or ask your own question.