0

I recently worked on a simple and basic encryption program. (skip reading the code before reading the question)

def generator():
    enckey="abcdefghijklmnopqrstuvwxyz"
    a=list(enckey)
    random.shuffle(a)
    c=''
    for i in a:
        c+=i
    c=c+a[0]
    return c


def senc(a,enckey=generator()):
    b=list(a)
    for i in range(0,len(a)):
        for j in range(0,27):
            if b[i]==enckey[j]:
                b[i]=enckey[j+1]
                break
    c=''
    for i in b:
        c+=i
    print("Encrypted text:",c,"\nEncryption Key:",enckey)

Now when I call the function senc("argument"), it generates a enckey and uses it to encrypt the supplied text. Now, since I say that enckey=generator() I expect that every time senc is executed it will re execute generator to get a key. But this did not happen.

The following is the proof:

>>> id(senc("Andy"))
Encrypted text: Arnj 
Encryption Key: htpkzwqlxcsdnregobvaimyjufh
1655676136
>>> id(senc("Candy"))
Encrypted text: Cirnj 
Encryption Key: htpkzwqlxcsdnregobvaimyjufh
1655676136

Both are at the same memory address and as seen the encryption key is same. Where did I go wrong, and why does it not call the function?

Please note that the encryption key does change for every new instance of IDLE/commandprompt, etc.

1 Answers1

2

Default arguments are evaluated only once, when the function gets defined. If you want to have a new generator each time you invoke the function without enckey parameter, you should do:

def senc(a,enckey=None):
    if enckey is None:
        enckey = generator()
    b=list(a)
    ...
Thierry Lathuille
  • 23,663
  • 10
  • 44
  • 50
  • this implies that it remembers the default value, can I get it's memory address/clear it from there? – the sigmoid infinity Nov 02 '20 at 16:29
  • 1
    @AnindyaPrithvi https://stackoverflow.com/questions/10120974/where-is-the-default-parameter-in-python-function – Barmar Nov 02 '20 at 16:31
  • @Barmar Thanks a lot :) – the sigmoid infinity Nov 02 '20 at 16:32
  • 1
    It also seems to be writable, see https://stackoverflow.com/questions/13784840/are-you-allowed-to-modify-func-defaults-defaults-in-python-3-x-in-python. But that would be an ugly and difficult to understand way to do this, while using `None` as a default is the commonly understood, traditional way to do it. – Thierry Lathuille Nov 02 '20 at 16:35