0

Before I begin, I just wan't to clarify that I am aware that variables obviously make programming easier; this is just a question concerning the nature of how foo() is assigned to var_bar, not why.

For example, say I have a file I wish to read, I would do the following:

>>> r=open('Foobar.py')
>>> r.readline()
'Foo'
>>> r.readline()
'bar'
>>> r.readline()
'\n'

What I used to do, which didn't work, was this:

>>> open('Foobar.py').readline()
 'Foo'
>>> open('Foobar.py').readline()
 'Foo'

Back then I simply used alt+p to bring up the previous line, I was using IDLE by the way.

Anyway, Similarly, if I use count() in the itertools module, I have to assign the function count to a variable as such:

c = itertools.count(10,1)

>>> for i in range(0,50):
       next(c)
10
12
14
...

if I simply did the following:

for i in range(0,50):
    next(itertools.count(10,1))
10
10
10
10
...

Why is it then, that when I am (seemingly) using the exact same code, there are different outputs dependent on how that code is expressed (of course though, it's not the same code as something is happening behind the scenes).

I know that if list1=list2, and list2 is modified, than list1 is also modified as their aliased, in that not only is the second referring to the first, but is the first (list2 is list1 returns True), so I would expect the same behavior when the expressions that the variables c and l refer to is used in isolation.

Thanks for any help, it shall be much appreciated as this, as am sure you know, is a massive obstacle for any beginner like myself, so some reading materials in regards to, whatever this is, would be very well utilized.

Jim Jam
  • 713
  • 4
  • 10
  • 22
  • `r = open('Foobar.py')` does not assign a function to a variable - it calls a function and assigns the return value of that function to the variable. Each call to `open` gives you a new file object (it doesn't matter that they refer to the same file on disk). If, after `r = open('Foobar.py')`, you would assign `r` to another variable: `a = r`, then `a` would refer to the same file object, similar to your `list1 = list2` code. – Pieter Witvoet Nov 16 '14 at 21:54

4 Answers4

3

The term at play here is "side effect".

When you call readline, you have a return value and a side effect. The return value is the line of the file being read. The side effect is that the cursor moves to the next line. The side effect changes the file object so that each time you call readline, you get a new line. The same concept is at play with the counter iterator.

If you don't save your file to a variable, then the side effect is lost, and you basically start over when you open the file the second time. In other words, even though you're opening the same file on your operating system, you are dealing with two completely different file objects as far as python is concerned. Anything you do with the first one has nothing to do with the second.

isharacomix
  • 161
  • 3
  • Thanks very much for answering ^_^ I kina, an object is created, but saved under a variable, so the value of the object is recorded when side-effects are made to that object. What would be the key-terms to use in Google by the way? Thanks again :) – Jim Jam Nov 16 '14 at 21:48
  • Technically speaking, an *instance* of an object is created, and the side effects are applied to an instance. This is the fundamental principle underlying object-oriented programming. – isharacomix Nov 17 '14 at 03:56
1

How come a variable, that has a function assigned to it, can be used in ways that the function itself cannot?

open is a function. open('Foobar.py') isn't. It's the object returned by open it get called.

r=open('Foobar.py') makes r refering to the returned object.
r.readline() modyfies the object to which r points, so it doesn't return the same line twice.

open('Foobar.py').readline() - open call returns object, and you instantly use & modify it once, getting first line of the file. You don't store reference to the object anywhere, so it gets deleted.

GingerPlusPlus
  • 5,336
  • 1
  • 29
  • 52
0

Here's the quick explanation:

When you use this:

c = itertools.count(10)
for i in range(10):
  print next(c)

You get 10, 11, 12.... 19

But when you do this:

for i in range(10):
  print next(itertools.count(10))

You are, effectively, doing this:

for i in range(10):
  c = itertools.count(10)
  print next(c)
Dan H
  • 14,044
  • 6
  • 39
  • 32
0

What you need to understand is somthing called the yield keyword.

yield returns the a value every time the keyword is found within the body of the code. Let me give you a simple example:

>>> def a():
yield 1
yield 2
yield 3
>>> b=a()
>>> next (b)
1
>>> next (b)
2
>>> next (b)
3
>>> next (b)
Traceback (most recent call last):
  File "<pyshell#41>", line 1, in <module>
    next (b)
StopIteration

Here, if you assign the function a(), to variable b, then you also assign the value it returns. The variable holds i.e records the value, like on a notepad. If the variable is used to execute the same function, the value is kept, if the function is used in isolation, the variable is lost, and the function exits.

As an analogy, if the notepad stores a value to a note within the pad, then it can continue to do so on the same page, but imagine that all the values have to be calculated and rewritten each time a new page is used, you would thus need to store all the values on the same page.

The count method uses the yield keyword in this abstract from python's own tutorials:

def count(start=0, step=1):
# count(10) --> 10 11 12 13 14 ...
# count(2.5, 0.5) -> 2.5 3.0 3.5 ...
n = start
while True:
    yield n
    n+=step

Ref: https://docs.python.org/2/library/itertools.html#itertools.count

When yield is hit, the value is returned, much like the return function, but when the function is called again, the pointer starts where it left off, instead of going to back to the top of the code, it returns to yield, then executes the rest of the code after yield, if any, and repeat. This however is only true IF the value can be Assigned to a variable. This is not to be confused with a for loop by the way, if there is only one yield statement, then if not used in a loop, the function will continue where it left of, as in example one, until the code is 'exhausted', you could say it ran out resources.

So there, hope that helps :)

P.S check out e-satis's answer, there some things you need to understand to understand when it comes to the functions like count(), which is a generator (check out the link):

What does the "yield" keyword do in Python?

Community
  • 1
  • 1
Jim Jam
  • 713
  • 4
  • 10
  • 22