-3

I am currently initializing variables within if else statements by .extend(). At the end of my script I am writing the variables to an excel file using xlwt. However the compiler throws the following error:

Traceback (most recent call last):
 File "C:\Python27\cascade.py", line 171, in <module>
NameError: name 'correct_screw_match' is not defined>

Currently I am also using extend as an error is thrown when using append.

for i in range (no_of_screw)
 for iterator in range (0, read_limit, 2):
  if (excel_screw_centroid[iterator]-25) <= screw_centroid[i,1] <= (excel_screw_centroid[iterator]+25):
   if (excel_screw_centroid[iterator+1]-25) <= screw_centroid[i,0] <= (excel_screw_centroid[iterator+1]+25):
    correct_screw_match.extend(i)
    detected_a_screw = 1
   else:
    incorrect_screw_match.extend(i)
    detected_a_screw = 0

I assume that the reason is, that the variables are declared within within an if else statement. This is why I initialized the variable as empty in the beginning of the script in the following way:

correct_screw_match = None

This however gives the following problem:

Traceback (most recent call last):
 File "C:\Python27\cascade.py", line 106, in <module>
AttributeError: 'NoneType' object has no attribute 'extend'

The below to links explains in a simple manner, how to declare an empty variable, and the other how to append to it within if statements. I am however unaware of why this is not possible to me in the current way.

Reference to declaring empty variables.

Reference to append to empty lists.

Community
  • 1
  • 1
Emil Nielsen
  • 195
  • 4
  • 15
  • 2
    Make it an empty list `correct_screw_match = []` - how can you `extend` a list before it exists? Python doesn't have an *"empty variable"* concept at all - the name `correct_screw_match` is a reference to a `NoneType` object, which *isn't* a `list` and *can't* be `extend`ed. It won't guess what kind of object you meant it to be. – jonrsharpe Nov 11 '14 at 14:13
  • For this purpose `append` and `extend` should give the same result. I understand you point in writing to something which does not exist, however as I am rather new to Python and I am used to C, it confuses me a bit that some things need to be declared before assigning, and some doesn't. However I am also unable to use ´append´ for some reason. – Emil Nielsen Nov 11 '14 at 14:17
  • 2
    `append` and `extend` will behave identically - `None` does not have either of those methods, any `list` has both. You should probably have a look at e.g. http://nedbatchelder.com/text/names.html to clarify what's going on here. Python is *dynamically, but strongly* typed. – jonrsharpe Nov 11 '14 at 14:41

3 Answers3

2

It's often said that "Python doesn't have variables". That's not entirely correct, but what that pithy little phrase tries to represent is that all Python variables are simply names that refer to objects. When you say

x = 3

you are not declaring a variable named x and initializing it to 3; you are simply making the name x refer to an int object whose value is 3. Likewise,

y = x

does not create a new object whose value is taken from the value of x; it simply makes y a reference to the same object that x refers to.

It is not the variable that has a method extend, it is the object that the variable refers to. Also, objects have methods, not variables. In the line

correct_screw.extend(i)

correct_screw must first reference an object with an extend method before you can call the method. In this case, you want a list object, so you must first make correct_screw refer to such an object. It's not about declaring a variable, it's about making a name refer to a usable object.

correct_screw = list()   # Using the type to create an empty list

or more concisely

correct_screw = []  # Using a list literal

Because names are created by assignment statements, and names themselves are not typed, you can ensure a name exists by assigning any value to it; the name on the left-hand side of an assignment need not (and indeed, usually does not) exist before. Any attempt to call a method using a name, though, requires that the name both exist and refer to an object of the correct type. This is why correct_screw = None does create the name correct_screw (so you don't get a NameError later), but does not make it refer to an object of the correct type for the subsequent call to extend.


Based on your usage and comments elsewhere, it seems you think that None and [] share a similar relation to undef and () in Perl, where they are somewhat interchangeable. However, Python is a strongly typed language, while Perl is not.

chepner
  • 497,756
  • 71
  • 530
  • 681
1

You should just initialise the variables (lists, presumably) with an empty value:

correct_screw_match = []

Then either use:

correct_screw_match.append(i)

...or if you must use extend:

correct_screw_match.extend([i])
declension
  • 4,110
  • 22
  • 25
  • ´correct_screw_match = None´ so this is somehow different than ´correct_screw_match = []´ Is it because the first is declared as a scalar and the latter as a list? But both are unassigned? – Emil Nielsen Nov 11 '14 at 14:22
  • `None` refers to an object of `NoneType`; `[]` is a that creates an object of type `list` (specifically, an empty list). Python doesn't have scalars (you seem to be thinking of Perl); it simply has objects, each of which has a type. The only thing `None` and an empty list have in common is that both are considered "false" when considered in a Boolean context. They are not interchangeable. – chepner Nov 11 '14 at 14:30
  • What @chepner said, really. Bottom line is: they *are* assigned, but you can't called append on `NoneType`, as it has no such method (or any of its own at all). Remember, Python has [strong typing](http://en.wikipedia.org/wiki/Strong_and_weak_typing), not weak so that `NoneType` won't change magically. – declension Nov 11 '14 at 16:41
0

It's not possible to you because you're not doing it. You are trying to call a list method on a value which is not a list, which of course won't work.

You need to set the variable to an empty list first, then call extend():

incorrect_screw_match = []
incorrect_screw_match.extend(i)

BUT, of course the above makes no sense at all, since it will clear the list every time a match is found.

Thus, the solution is to move the initialization to before the loops.

unwind
  • 391,730
  • 64
  • 469
  • 606
  • Actually I need to use ´del´ inside the loop, so having the intialization at the top of the for loop is no problem as i am using xlwt to write the contents of the list at the bottom of the for loops. – Emil Nielsen Nov 11 '14 at 14:27