1

I am really new to python, so this might be really easy.
I want to print two strings defined in a class as static members with a class method that yields each string. This is a simplified version of what I am trying to do:

#!/usr/bin/python

import sys


class test:
    str1 = "Hello"
    str2 = "World\n" #"\n" is needed for the example

    def printMe(self):
        yield test.str1
        yield test.str2

hello = test()

print "Testing initiated:"
sys.stdout.write(hello.printMe())
sys.stdout.write(hello.printMe())

This is the output:

sys.stdout.write(hello.printMe()) TypeError: expected a character
buffer object

Chris
  • 3,619
  • 8
  • 44
  • 64
  • 2
    Why are you using `sys.stdout.write`? Can't you use `print`? – Alvaro Fuentes Dec 20 '13 at 21:15
  • You may also want to put a `while True:` at the top of `printMe` if you could be printing the values over and over. As it is now, the function will be exhausted after two prints, and you'll get a `StopIteration` condition if you try to print further. – ely Dec 20 '13 at 21:19
  • @xndrme: I wanted to avoid the new line at the end that print injects – Chris Dec 20 '13 at 21:19
  • @Chris you can avoid that using `end=''` in `print` check the edit of my answer – Alvaro Fuentes Dec 20 '13 at 21:24

5 Answers5

1

You should do something like this

for line in hello.printMe():
    print line

But really there are a lot of easier ways than using yield statements.

aplassard
  • 759
  • 3
  • 10
1

You are attempting to use a generator function, read about the yield keyword here

import sys


class Test: 
    def __init__(self): # it's possible to initialise these attributes in the __init__ method, so they are created on class instantiation(when you did hello = Test())
        self.str1 = "Hello"
        self.str2 = "World\n" #"\n" is needed for the example

    def printMe(self):
        for i in [self.str1, self.str2]:
            yield i 


app = Test()

print "Testing initiated:"

for i in app.printMe():
    print i # is there a reason why you can't use print?

If however you want to print the lines one at a time, at specific points in the code, like in your loop you mentioned in the comment:

gen = app.printMe()

then every time you want to print:

gen.next() 

this triggers the next yield statement. The generator function effectively 'holds'/remembers it's place until you call next again, until all the yield statements have been yielded.

Community
  • 1
  • 1
Totem
  • 7,189
  • 5
  • 39
  • 66
  • I was just in a rush that's why I didn't capitalize the first letter of a class. So you create a tupple to be used in the range of the for-loop, right? But what if I don't want to print the two strings in once, but after another iteration of a loop (that the print is inside)? – Chris Dec 20 '13 at 21:30
  • actually, you could use the two yield statements that you had above. But the list I have there(not a tuple) works too. – Totem Dec 20 '13 at 21:31
  • Yes a list, sorry for the mistake, I've just started learning python. (I've extended my above commend) – Chris Dec 20 '13 at 21:32
0

You can do this, but I'm using print, hope this helps you:

class test:
    str1 = "Hello"
    str2 = "World\n" #"\n" is needed for the example

    def printMe(self):
        yield test.str1
        yield test.str2

hello = test()

print "Testing initiated:"
out = hello.printMe()
print(out.next(),end=' ')
print(out.next(),end=' ')
Alvaro Fuentes
  • 16,937
  • 4
  • 56
  • 68
0

using yield turns your function into a generator. If this is really what you want, you will need to iterate over the generator to get the values:

gen = hello.printMe()
sys.stdout.write(gen.next())
sys.stdout.write(gen.next())

or better:

for prop in hello.printMe():
    sys.stdout.write(prop)
bj0
  • 7,893
  • 5
  • 38
  • 49
0

Your printMe method is a generator function, which returns an iterable. You need to iterate over it to get the results :

for item in hello.printMe():
    print item
bruno desthuilliers
  • 75,974
  • 6
  • 88
  • 118