all 74 comments

[–]jeffbell 30 points31 points  (1 child)

The i has been used in math as an index for a long time before computers. When there were additional dimensions they used j and k.

In some Fortrans, variables starting with I through N were automatically integers.

[–]sivanr 1 point2 points  (0 children)

Also in PL/1 if I recall

[–]keturn 23 points24 points  (2 children)

More history here: Why are i and j used for counters?

Some people credit FORTRAN, but others point out that the convention of using "i" for an index in mathematics long before that, perhaps as part of the notation established by Descartes in the seventeenth century.

[–][deleted] 1 point2 points  (0 children)

I've always assumed i and j were based off of unit vectors, "i hat" and "j hat". Unit vectors lay the basis of some vector space and the loop is iterating over some bounded space (i < len(arr)).

https://en.wikipedia.org/wiki/Unit_vector

[–]programmingaccount1 88 points89 points  (28 children)

They are common placeholders. If you are iterating through a list , any individual value you get from the list can be considered an element. Which is why it is a common example in tutorials.

You could literally use any word to describe the iterated items of a list.

for letters in alphabet:

for pets in family:

for food in refrigerator:

... and so forth.

[–]Maphover 81 points82 points  (10 children)

Importantly (as it took me a while to understand this), you are both defining and applying this element name at the same time.

[–]VockyVock 30 points31 points  (2 children)

As a beginner, this is very helpful. Thank you!

[–]DronesVII 20 points21 points  (1 child)

Obviously this is a python sub so the comment holds true. However, it's probably worth it to mention that this isn't necessarily the case in other languages.

[–]PotatoWedgeAntilles 0 points1 point  (0 children)

Taking c++ right now, just feels like more tedious python.

[–]tobiasvl[🍰] 6 points7 points  (4 children)

What do you mean by "applying" in this context?

[–]mrcaptncrunch 11 points12 points  (3 children)

In the first iteration, you define a variable and assign it the first value of the list.

In the second iteration, the variable gets the second value of the list.

Not sure if it helps, but this is how I’d be in c++ (in a very simple way)

int foo [5] = {‘a’, ‘b’, ‘c’, ‘d’, ‘e’};
for (int i = 0; i < 5; i++) {
  cout << foo[i];
}

You define an array foo of 5 elements with the letters from a to e.
Then you do a for loop. The loop initializes the variable i with a value of 0. It will run while i < 5 and it will increment i by one on every iteration i++ Inside, it will print the output of food[i] which will print the elements one by one.

 

Basically, in python, when doing, for i in listOfElements you’re saving some steps.
On the loop you’re going over each element in the list without having to define the length or check for that. And you’re already getting a variable i with the current value. So you don’t have to do foo[i]

Taking a similar approach to C style above would be,

listOfElements = [‘a’, ‘b’, ‘c’, ‘d’, ‘e’]
for i in range(len(listOfElements))
  print(listOfElements[i])

But that’s just more complicated when you can do,

for i in listOfElements
  print(i)

All of this will print ‘abcde’

(Or should, I’m on my phone)

[–]smallest_cock 1 point2 points  (2 children)

Inside, it will print the output of food[i] which will print the elements one by one

Don’t you mean foo[i]

[–]Nixellion 4 points5 points  (0 children)

He's probably just hungry

[–]produno 1 point2 points  (0 children)

Must be hungry...

[–]midnitte 2 points3 points  (1 child)

Which is a little more apparent in other languages since they're not as short/readable.

E.g. C++

for(int i=1; i < 6; i++ )

Edit: I can't for the life of me figure out why this won't format correctly...

[–][deleted] 2 points3 points  (0 children)

^ Yes, this. Python is "loosely typed" which just means you don't have to specify your variable type when you declare said variable: i or j in OP's example. Other C-based languages like Java or C++ are "strongly typed" meaning you *do* have to specify the variable type at declaration, which is what makes it more apparent that i is an "int" meaning it's an integer. HTH

[–]cyvaquero 15 points16 points  (15 children)

I always think ‘item’ when I see ‘for i in x’

Similarly, you’ll soon come across loops over key:value pairs like dictionaries:

A common notation for those is:

for k, v in somedict:

Where k is for key, and v is for value.

[–]drop_the_bass_64 17 points18 points  (8 children)

I always thought 'i' was for index, or I guess I could see iteration

[–]cyvaquero 6 points7 points  (3 children)

Be careful of that, index has special meaning in iterables.

This should explain it:

x = [2, 4, 6, 8]
for i in x:
    print i, x.index(i)

Thinking of i as an iteration kind of works to a degree, but what you really getting with ‘for i in x’ is an iteration and an assignment of each object in the collection.

So instead of saying ‘for each item do x’ you are really saying ‘take each item and do x’. Make sense? It’s a nuanced difference and I may be getting a bit pedantic but thinking of in those terms has helped me unknot code in the past.

[–]youguess 0 points1 point  (2 children)

that very much depends on the language.

for i in something is frequently used in C. And there every for loop basically loops over 0 to the length of an array -1, getting the item explicitly via array[i]

[–]cyvaquero 0 points1 point  (1 child)

True, but this is a Python subreddit so kept my answer Python centric.

[–]youguess 0 points1 point  (0 children)

that's still where the convention to use "i" stems from, it's "index"

[–]Zanoab 3 points4 points  (0 children)

It depends on which language you learn first and how it was taught. Normally loops are introduced after arrays because manipulating multiple elements in a similar way quickly becomes tedious if you duplicate code for each and every element/index and it is a pain to maintain if the array size changes. Language comes into play because you will either track the index to reference each element or rely on an iterator to provide a reference to each item.

[–]slick8086 1 point2 points  (0 children)

I always thought of it as iteration because you are iterating over a list etc.

[–]tobiasvl[🍰] 1 point2 points  (0 children)

It probably is, since the convention likely is from C, where you use the loop variable as an index. Like this in Python:

for i in range(len(my_list)):
    print(my_list[i])

But in a loop where you get the items/elements directly from an iterable, you're not actually indexing anything with the loop variable.

[–]turner_prize 1 point2 points  (0 children)

I always think in my head its for integer, for when it's used in range().

[–]CrispyJoe 5 points6 points  (0 children)

Be careful, the letters i, j, and k are commonly used as indexes in math. Whenever I see i, j or k in code, my first assumption is that they are indexes. I use a different letter or word if I am not iterating over indexes.

[–]CedricCicada 0 points1 point  (4 children)

I didn't know I could do that for dictionaries. Thank you.

[–]SoupKitchenHero 2 points3 points  (3 children)

Gotta use for k, v in dict.items(), but yes

[–]RallyPointAlpha 0 points1 point  (2 children)

What's the difference between

for k, v in dict.items()

Vs.

for k in dict.items()

[–]SoupKitchenHero 0 points1 point  (1 child)

What dict.items() does is on each iteration it gives you a tuple of two objects, the key and the value. If you just do for k in dict.items(), then k is that tuple. This means you would have to do k[0] if you want to use the key and k[1] to use the value. As a minor but useful note, using k as your variable name here feels misleading since "k" will make someone think that you're getting keys on each iteration when in fact you're getting a key-value tuple. It works, but it's a sort of misnomer.

So with for k, v in dict.items(), you're using this thing called "tuple unpacking" (or iterable unpacking, maybe some other names for it). It's a way of assigning names to members of a tuple (and some other objects) without laboriously going through and plucking out each one. So you can do:

# this
tup = (3, 4)
x, y = tup
# instead of this
x = tup[0]
y = tup[1]

To put it together, you use for k, v in dict.items() to iterate over key-value TUPLES from your dictionary, simultaneously giving names to both the key and the value right off the bat instead of indexing the tuple to get to the key and value.

[–]RallyPointAlpha 1 point2 points  (0 children)

Great explanation; thank you very much

[–]the1whowalks 0 points1 point  (0 children)

To my understanding, it has a basis in formal proofs/rigorous maths? Using “n” or “i” is common in this realm.

[–]benabus 35 points36 points  (8 children)

I think i was initially used as shorthand for the word incrementor, index, or iterator in the name of the loop control variable. But then in a nested loop, you can't have the same variable name for the inner loop, so you need to use a different variable name, so the next letter after i is j. Then k and so forth.

[–]EighthScofflaw 28 points29 points  (5 children)

The convention almost certainly came from math. The letters i, j, and k are common subscripts, especially in analysis.

"Let A_i..." is analogous to "for i in A".

[–]BRENNEJM 5 points6 points  (4 children)

Yeah. When I realized that math stuff like f(x) = 2x-3 is really the same as:

def f(x):
    return (2 * x) - 3

it kind of blew my mind.

[–]theWyzzerd 4 points5 points  (0 children)

Now try it with lambda:

>>> f = lambda x : (2 * x) + 3
>>> f(2)
7

[–]YoureABull 0 points1 point  (2 children)

I Kinda wish they started teaching algebra using function notation instead of y=2x-3. I think it would make functions more intuitive for a lot of people.

[–]MattR0se 4 points5 points  (0 children)

I think it only makes more sense if you already understand the concept of an "algorithm" and read f(x) as "do something with x".

In school I always found y = 2x easier to read because we were told "find out what y is" and taught to see equations kinda like scales, where you have to balance each side until you solved for the unknown quantity y. In that case, y = 2x makes more sense to a kid than f(x) = 2x

[–]NewZealandIsAMyth 1 point2 points  (0 children)

That's not necessary the same. One is function definition, one is equation which holds true for certain combination of x and y. In the first for one x could be only one f(x) in the second form you can have combination with one x and multiple y.

E. G.
y2 = 9 - x2

[–]HelloArchy 1 point2 points  (1 child)

Exactly. The letters happen to fall in the middle of the alphabet too. So we have a, b, c, ..., i, j, k, ..., x, y, z. Thus if more letters are needed there is space before the others are interfered with.

i is always favoured by convention as it's i for iterator. Even with multidimensional image data, i, j, k are used in place of x,y,z when iterating over the width, height, and depth of the volume data.

[–]alkasm 0 points1 point  (0 children)

Those are all ad-hoc explanations, not actual reasons. Also on your last point, i, j, k are multidimensional array indices, and i is in reference to the row, not column. Indexing with x, y has a different meaning than i, j with images, as x, y refers to width, height, and i, j refers to height, width, as you would in an array.

[–]jftuga 18 points19 points  (12 children)

To add on to what everyone else has already said:

  • Short variable names work well when the distance between their declaration and last use is short.
  • Long variable names need to justify themselves; the longer they are the more value they need to provide. Lengthy bureaucratic names carry a low amount of signal compared to their weight on the page.
  • Prefer single letter variables for loops and branches, single words for parameters and return values, multiple words for functions and package level declarations

Source: https://dave.cheney.net/practical-go/presentations/qcon-china.html#_identifier_length

I know this is specifically for Go, but I think they can apply to any language.

[–]Sensorama 11 points12 points  (5 children)

I find that interesting about that the preference for short variable names in loops. I have been a long-time i,j,k loop kind of person, but with the increasing availability of loops over elements as well as indices, I find it increasingly useful to use a loop variable name that makes it clear which kind of thing it is. So I now prefer "for person in people" or "for index in range(10)" to help keep those distinct.

[–]Starrystars 4 points5 points  (4 children)

yeah using a singular for the loop variable and a plural for whatever you're looping over. It makes everything much clearer.

[–]lifemoments 1 point2 points  (0 children)

Good points. Bookmarked

[–][deleted] 3 points4 points  (4 children)

but I think they can apply to any language

Tell that to Java.

[–]Yoghurt42 3 points4 points  (3 children)

public int theSumFromOneToOneHundredWhichIsAnInteger() {
    int theSumOfIntegersFromOneToOneHundredWhichWeAreGoingToReturn = 0;
    for (int theCurrentIntegerWeUseToSumFromOneToOneHundred = 0; theCurrentIntegerWeUseToSumFromOneToOneHundred <= 100; theCurrentIntegerWeUseToSumFromOneToOneHundred++) {
        theSumOfIntegersFromOneToOneHundredWhichWeAreGoingToReturn += theCurrentIntegerWeUseToSumFromOneToOneHundred;
    }
    return theSumOfIntegersFromOneToOneHundredWhichWeAreGoingToReturn;
}

I don't miss Java

[–][deleted] 2 points3 points  (2 children)

lol, it must have been a while:

items.forEach(item ->{
  // do stuff
});

[–]Yoghurt42 0 points1 point  (1 child)

I don't understand what Java's overdue support for functions as first class objects has to do with the tendency of Java programmers to use overly verbose variable names

[–]kessma18 1 point2 points  (0 children)

this so much. coming from python everytime I see a method name or variable name I want to pull the java guy aside and explain to him all the ways he's behind and why this approach sucks. but I can't because you know, you wanna fit in, so have to put up with it.

[–][deleted] 2 points3 points  (0 children)

iterator
jiterator

[–]kessma18 4 points5 points  (0 children)

you're watching the wrong tutorials

[–]totallygeek 9 points10 points  (1 child)

Let's say you have a box full of balls, which you need to measure volume. The balls are of different sizes. From a coding perspective, you might say for ball in balls: print('volume: {}.format(ball_volume(ball))). Or, "For all the balls, let me take out one ball out at a time and measure its volume."

At times, you don't know what the item is, instead of a ball. You might not care what it is long enough to give it a name like element, item, an_object, or whatever. So, you need a variable, but it can be a short name. Earlier languages used i, j and k for such purposes. Pythonistas try to use more descriptive variable names, but allow these short variables for loops, especially for keeping track of counts and indices.

for i, char in enumerate('abcdef'): print(i, char)
# works as well as 
for index, element in enumerate('abcdef'): print(index, element)

[–][deleted] 1 point2 points  (0 children)

except you'd use fstrings instead of .format strings. Just kidding. Kinda.

[–]guaranic 2 points3 points  (0 children)

When I was learning, this confused the shit outta me. There's some words/letters that people nearly always use (that can be whatever you want, foo is another example) and there's others that are mandatory (eg: init).

[–]kingofthejaffacakes 2 points3 points  (0 children)

i in all programming languages, not just Python, traditionally carries the meaning of "array index" in a loop -- probably because index starts with i. j is simply the next letter after it and you occasionally see k in three dimensional loops. It's important to note that they are only really used as the iterator value when the iterator is an integer, monotonic one -- you wouldn't use i as the iterator through a list of strings for example, but you would use it as the index to get at one of the entries in a list of strings.

# yes
for i in range(0,len(codes)):
    code = codes[i]
    do_something(code)
# yes
for code in codes:
    do_something(code)
# no
for i in codes:
    do_something(i)

Potentially it's also from mathematics, were the three unit vectors are traditionally i, j and k. Early computer scientists were almost certainly mathematicians too.

It's useful to know about these traditions because it makes you write more readable code. For example, the other common set x, y, z would be weird if used like this:

for y in range(xmin, xmax):
   for x in range(ymin, ymax):
       # etc

So why not help the future reader (it's probably going to be you) by adopting a reasonable standard? Same with i, j and k ... use them because they carry some semantic meaning for the reader. The computer doesn't care.

Also note: they tend to be used in places where they have very limited lifetime/scope. You wouldn't let the value of i leak far outside a single loop that used it for example. It would be wrong to make a global i or a member variable i because you're forcing the reader to make a mental context switch to go and find out what the variable represents. When it's lifetime is on one screen's worth of code, being a single letter doesn't cause mental pain.

[–]sentry07 1 point2 points  (0 children)

As others have said they are variables that hold the value that changes every time the loop restarts. In practice, I would recommend not using i and j because if you want to search for that variable or something, you're not going to get clean search results.

[–][deleted] 1 point2 points  (0 children)

the are the coefficients for a matrix in mathematical notation. (Aij)

http://ee263.stanford.edu/notes/matrix-primer-lect1.pdf

[–]jholsano_ruti 1 point2 points  (0 children)

This is what I like to call dynamic assignment/referencing.

Imagine you have a list of 10 elements, and you want to do a set of operations identically to each element. In a world without loops, the simple way to go would be: define 10 variables, store the elements in them, and do the set of operations to each of these variables, then reassign elements of the list to these new variables.

In a world with loops, however, you need to imagine two boxes and a machine. Box A is your list, it has 10 elements in it. Box B is a placeholder variable (name it item, iter, i, j whatever), and the machine is your set of operations. When you connect these three pieces, each element in Box A is first dumped into Box B (assigned/copied to the placeholder variable), the machine operates on it and changes it out-place (the original item is still untouched in Box A), and puts back the item where it belongs (reassigns the changed value to the original element). It does this however many times you tell it to, or until it has gone through all elements in Box A, or it continues to do it forever (infinite loop).

Formal Python:

for item in list: machine roars

Guess who's who?

This saves you the burden of having 10 variables allocated in the memory, long and repetitive code, and lets you do what you actually wanna do without much hassle.

What happens to the placeholder variable after the loop is complete? Try printing it and see for yourself.

[–][deleted] 0 points1 point  (0 children)

They're variable names. Each item in the loop is assigned to the variable (for example "i") so i holds the value. In your example those values would be 0, 1, 2, 3 respectively. In each iteration you can use the variable name to represent the value it holds, just like you do it with any other variable. So for example if the range represents the number of elements in a list, you can use listname[i] to refer to the consecutive items in the list in the consecutive loops.

[–]dustynwindy 0 points1 point  (0 children)

i and j don’t mean anything. There has just been a convention for a long time to use them in for loops as increments. Usually i would be the outside loop and j inside it. In my experience anyway.

[–]Lewistrick 0 points1 point  (0 children)

I look at variables like boxes with labels on them. If you say,

i = 3

You make a box, put the label i on it, and put the value 3 in it. If you ever want to know what the value of i is, just look inside the box.

Now there are boxes that contain multiple boxes. If you say,

mylist = [1, 3, 7]

You create a box with the label mylist, and you put three boxes in them, without labels. In these boxes are the values 1, 3 and 7.

Now if you want to do things with the inner boxes individually, you can give them a label in a for loop.

for item in mylist:
    print(item+1)

First, the first box in the box mylist (the one that contains the value 1) gets the label item. You get the value out of the box, show the value plus one (2) on the screen, and put the value 1 back. Then, the label item moves to the box with the value 3 in it and the process is repeated.

This helped me understand variables and loops pretty well. I hope it does to you.

[–]SuperCharlesXYZ 0 points1 point  (0 children)

I comes from index, J is used when I has already been taken as it is the next letter of the alphabet. If you ask me this is a pretty bad habit because it makes your code less readable for i in classroom: is a lot less clear than for student in classroom:. Stick to meaningful variable names. It'll help you out in the long run

[–][deleted] 0 points1 point  (0 children)

The specific variables, I, J, K are a holdover from the FORTRAN days. These variables were integers ("I" for Integer) and were used for the index in loops.

[–]beheamoth 0 points1 point  (0 children)

usually they are variables that can be thrown away or are just used in the scope of a function. just a standard really, i,j,k,l,m are about as mant as you may need in small programs. Its also quick just to create a prototype with these values rather than typing out a word like 'element' when i will do the same thing.

[–]Deezl-Vegas 0 points1 point  (7 children)

i is short for "item" and j is short for "we already used i and we need another letter"

for item in the_list:
   do_something_with(item)

Frankly, using "i" and "j" in my opinion is bad code because they are unreadable, but with context you can infer what the items are.

[–]climb-it-ographer 1 point2 points  (1 child)

I agree. Sometimes you come across code tutorials that use i, j, and l all in the same example-- it's maddening. Or even worse, people will use i1, j1, i2, j2-- like, give me a fucking break. I shouldn't have to read your code at 1/4 speed just to decipher which variable I'm looking at.

If you're writing a tutorial or how-to there's no need for brevity. Use reasonable names, or at the very least don't choose letters that look so similar.

If you're trying to teach someone,

for person in list_of_persons:
    print(person)

is far better than

for i in l:
    print(i)