Ciao, guarda questo piccolo esempio:
1)La funzione accetterà un unico paramentro con la variabile indicata nelle parentesi tonde:
def criptaesalva(user,pwd,db):
m=md5.new(pwd)
db[user]=m.digest()
db = dbm.open("dbm", "c")
for nome in ("Marco","Gennaro","Antonio"):
criptaesalva(nome,raw_input("scegli una password"),db)
db.close()
La funzione criptaesalva prende tre parametri "user, pwd, db".
Innanzitutto:
La variabile "m" istanzia l'oggetto md5 con metodo .new (come si fa per aprire i file insomma

) e prende come parametro pwd, perchè tramite questo metodo viene criptata una stringa.
Avremmo potuto scrivere anche :
m = md5.new()
m.update(pwd)
Dopo ciò c'è db[user] che funge da dizionario: [
tt]db[NomeUtente] = "Password"[/tt]
ma la vera cosa interessante del codice (e per questo ringrazio Manzo

) è il ciclo for che richiama la funzione criptaesalva:
Per un valore che vedi in ("Marco","Gennaro","Antonio"):
chiama la funzione criptaesalva con parametri(nome, raw_input(".."), db),
dove nome corrisponde ai tre valori che si trovano nel ciclo for (Marco, Gennaro, Antonio)
e dove pwd viene sostituito con l'istruzione raw_input(senza bisogno che venisse dichiarata 2 volte)
e db serve a inserire nomi utenti e password nel DB
Spero di essere stato chiaro

Per quanto riguarda il return, questo serve a ritornare un valore all'interno di una funzione.
Teoricamente puoi usare anche l'istruzione print, però quando richiami la funzione non puoi dare print funzione(..... , ....), altrimenti ti dà un bel None finale