1

I have tried to understand this by looking in previous threads but I still don't understand why I get this error for only one of two variables in the following piece of code (the code sucks I know):

alfaphet=('abcdefghijklmnopqrstuvxyz')
cryptalfaphet=('defghjiklmnopqrstuvxyzabc')
spaceNumber=[]
textCopy=[]


def crypt():
    textCopy=[]
    print('print the text that you want to encrypt:')
    text=input()
    for i in range(len(text)):
        for j in range(len(alfaphet)):
            if text[i]==alfaphet[j]:
                textCopy.append(cryptalfaphet[j])
        if text[i]==' ':
        spaceNumber.append(i)
    for i in range(len(spaceNumber)):
        for j in range(len(text)):
            if list(range(len(text)))[j]==int(spaceNumber[i]):
                textCopy.insert(j, ' ')
    textCopy=''.join(textCopy)
    print(textCopy)

crypt()

This code works fine, but if I remove the

textCopy=[] 

asignment from the beginning of the def-block, I get an error like this:

Traceback (most recent call last):
File "C:/Python33/dekrypt.py", line 26, in <module>
crypt()
File "C:/Python33/dekrypt.py", line 13, in crypt
textCopy.append(cryptalfaphet[j])
UnboundLocalError: local variable 'textCopy' referenced before assignment

My question is why this doesn't happen with the spaceNumber variable. spaceNumber is as far I can see also referenced before asignment with the

spaceNumber.append(i)

asignment? It is referenced before the def-block, but so was the textCopy vaiable right? What is the difference, they're both empty lists from the beginning and I use the .append() method on both, but Python seems to treat them differently!?

  • see this [post](http://stackoverflow.com/questions/10851906/python-3-unboundlocalerror-local-variable-referenced-before-assignment?rq=1) – Salvatore Avanzo Jul 10 '14 at 05:34
  • It's not about the `append` calls. It's about the `textCopy = ''.join(textCopy)` near the end, and the lack of such an assignment for `spaceNumber`. –  Jul 10 '14 at 05:36
  • possible duplicate of [local variable referenced before assignment in python when i set it global](http://stackoverflow.com/questions/21314384/local-variable-referenced-before-assignment-in-python-when-i-set-it-global) – shx2 Jul 10 '14 at 05:43
  • I think I understand what people are saying in the different posts, you have to set at variable as global or assign a value to it before using it in a local scope. But it don't seem as if I have to do this with the "spaceNumber" variable. Why? – pineappleexpress Jul 10 '14 at 06:26
  • @pineappleexpress You don't need `global` or assignment to **use** a global variable. Only if you *assign* to it *anywhere* in the function, you lose access to the global variable of the same name and have to either give the new local variable a value (`textCopy = []`) or explicitly say you want access to the global variable (`global textCopy`). –  Jul 10 '14 at 06:58
  • @delnan Ok thanks, that was a good point! However, I do assign to the variable "spaceNumber", but I still don't need to create a new local variable of it. Why? – pineappleexpress Jul 10 '14 at 07:08
  • @pineappleexpress Where do you assign to spaceNumber? (The one at the top isn't relevant, it's outside the function and it makes the variable exist in the first place). Again, a method call like `.append` is not an assignment even when it changes the list. –  Jul 10 '14 at 07:19
  • @delnan Sorry I'm so slow! You said I don't need "global" or assignment to use a global variable in the function, but how come I have to assign [] to textCopy in the beginning of the def-block then? I already have a global variable of it. If I remove the textCopy=[] asignment from the def-block I get an error. So I need to have an assignment for "textCopy" in the def-block. I don't need to assign [] to "spaceNumber" in the def-block to use it in the function. It seems like it is enough if I assign to it outside the function. This is as I said not the case with the "textCopy" variable. Why? – pineappleexpress Jul 10 '14 at 07:48
  • @delnan Both "textCopy" and "spaceNumber" are subjected to the same method .append(). And according to the error message I get this is the problem; it says I haven't assigned to textCopy UNLESS I assign to textCopy in the def-block. But I never get an error saying the same thing about "spaceNumber" eventhough I never assign to it inside the def-block. – pineappleexpress Jul 10 '14 at 07:52
  • Python looks at the whole function. For every variable `x` used there, it checks if `x` is assigned to *anywhere in this function*. If so, it's (by default, `global` overrides this) considered a local variable; otherwise it's treated as global. Because of the `textCopy = ''.join(textCopy)` line, the uses of `textCopy` at the start are also uses of a local variable... which doesn't exist yet (in contrast to the *global* `textCopy` which exists but *isn't used*). By the same rule, because there is no `spaceNumber = ...` anywhere *in this function*, uses of `spaceNumber` use the global variable. –  Jul 10 '14 at 07:54
  • @delnan OMG THANKYOU SO MUCH FOR EXPLAINING THAT SO WELL!!! ;D I totally get it now! This made my day. – pineappleexpress Jul 10 '14 at 08:02

1 Answers1

0

You can avoid this error by adding the following line at beginning of your function

def crypt():
    global textCopy
    ...

however, this isn't a python best practice. See this post for further details.

Community
  • 1
  • 1
Salvatore Avanzo
  • 2,656
  • 1
  • 21
  • 30
  • But how come I don't need to set "spaceNumber" as a global then? – pineappleexpress Jul 10 '14 at 06:24
  • delman has just answered to this question in his comment: you don't assign spaceNumber anywhere while you use an assignment operator for textCopy then you lose it as global variable. See also this [tutorial](http://www.python-course.eu/global_vs_local_variables.php) – Salvatore Avanzo Jul 10 '14 at 07:25