0

I have something like this:

for line in handle:
    line = line.rstrip()
    if not line.startswith('From') : continue
    words = line.split()
    if words[0] != 'From' : continue
    email=words[1]
    print email

and I want the email result to be available outside the for loop also. How?

Tim Pietzcker
  • 328,213
  • 58
  • 503
  • 561
godRA66
  • 357
  • 1
  • 3
  • 7

3 Answers3

3

You are in luck, python scoping is some of the best, you'll find that email is available outside of the scope of the for loop as python scoping rules state the following:

Quoting from Rizwan Kassim's answer:

LEGB Rule.

L. Local. (Names assigned in any way within a function (def or lambda)), and not declared global in that function.

E. Enclosing function locals. (Name in the local scope of any and all enclosing functions (def or lambda), form inner to outer.

G. Global (module). Names assigned at the top-level of a module file, or declared global in a def within the file.

B. Built-in (Python). Names preassigned in the built-in names module : open,range,SyntaxError,...

of which the for keyword is not a member of any. Any variables declared within the for loop will be scoped to their outermost scope. In this case the enclosing function.

def some_func():
    for line in handle:
        line = line.rstrip()
        if not line.startswith('From') : continue
        words = line.split()
        if words[0] != 'From' : continue
        email=words[1]

    print email

Will print the value of email.

Community
  • 1
  • 1
Mike McMahon
  • 7,096
  • 3
  • 30
  • 42
0

If you want to store all emails and access all of them outside the loop, consider using a list like this:

emailsList = []
for line in handle:
    line = line.rstrip()
    if not line.startswith('From') : continue
    words = line.split()
    if words[0] != 'From' : continue
    email=words[1]
    print email
    emailsList.append (email)
print emailsList

and access each element of the list by its index, like:

print emailsList [0]
user823743
  • 2,152
  • 3
  • 21
  • 31
0

Mike McMahon's answer is correct that the value assigned to the email variable will be available outside the loop. However, The function he shows is rather fragile. If your file doesn't have any lines that start with "From", the variable will never be assigned and you'll get an exception when you try to print it. Furthermore, if multiple lines meet the conditions (e.g. starting with "From"), you'll only see the last one. If you want the first, you'll need to change things up.

Here's a better structure:

emails = []
for line in handle:
    line = line.rstrip()
    if line.startswith('From'):
        words = line.split()
        if words[0] == 'From':
            emails.append(words[1])

I find the nested if blocks easier to understand than the repeated continue statements, though this is something of a stylistic choice. This version makes a list of all the values it finds. The list may be empty (if there are no lines that start with From, or it may have one or more results.

If you want the first result only, and not finding any is an error, here's another approach:

for line in handle:
    line = line.rstrip()
    if line.startswith('From'):
        words = line.split()
        if words[0] == 'From':
            emails = words[1]
            break
else:
    raise ValueError("No 'From' line found!")

# you can use the email variable here!

An else block attached to a for loop is run only if the loop runs to completion. If a break statement is hit in the loop body, the else block will be skipped. It can be very useful in situations like this, where you are looking for the first match, and not finding one is an error.

Blckknght
  • 100,903
  • 11
  • 120
  • 169