FAQ
Hello, I've written two classes. One class describes experts: experts
has a unique ID and a name. An expert knows topics and other experts. A
topic is described by my other class and includes a unique ID and a
name. Now I have a problem with the __str__ method in my Expert class:

def __str__(self):
output = '%s:%s' % (self.expert_id, self.name)
output += '\nKnown topics: %s' % (', '.join(str(self.topics)))
# print 'Known experts: '
# for e in self.known_experts:
# print '%s:%s' % (e.expert_id, e.name)
return output

self.topics is a list of objects of type Topic.
self.known_experts is a list of objects of type Expert, specifically the
experts known by the given expert.

When I print an object of type Expert, the output is not what I want. If
the expert knows only one topic, say polemics, the output is:
e2:Carla
Known topics: t, 5, :, P, o, l, e, m, i, c, s
If the expert knows two topics, say Polemics and The Parthenon, then the
output is:
e2:Carla
Known topics: [, <, _, _, m, a, i, n, _, _, ., T, o, p, i, c, , i, n,
s, t, a, n, c, e, , a, t, , 0, x, 0, 2, 2, 2, D, 0, 8, 0, >, ]

This is not what I want. :) I want the output like this:
e2:Carla
Known topics: t5:Polemics, t6:The Parthenon

Also, notice the code I've commented out. If I can get the join above to
work (with your help) my next question is how to present the known
experts in a comma separated list with only expert_id and name? I can't
use the normal __str__() method (the one I'm writing here) because it
prints too much information. Does that mean a join is out of the question?

Thanks for any replies!

- Fencer

Search Discussions

  • Jon rascal at Aug 9, 2009 at 5:28 pm

    def __str__(self):
    ? ? ?output = '%s:%s' % (self.expert_id, self.name)
    ? ? ?output += '\nKnown topics: %s' % (', '.join(str(self.topics)))
    You're turning your list into a string -- try this:
    ', '.join([str(x) for x in self.topics])
  • Fencer at Aug 9, 2009 at 5:42 pm

    jon rascal wrote:
    You're turning your list into a string -- try this:
    ', '.join([str(x) for x in self.topics])
    Thanks for your quick reply, unfortunately it didn't quite work for me.
    Say topics contain two topics: polemics, and the parthenon I get this
    output:
    e2:Carla
    Known topics: t5:Polemics

    only the first topic is printed. If topics only contain a single topic I
    get this error:
    Traceback (most recent call last):
    File "C:\Users\fencer\workspace\Find Expert\src\find_expert.py", line
    57, in <module>
    print experts[1]
    File "C:\Users\fencer\workspace\Find Expert\src\find_expert.py", line
    21, in __str__
    output += '\nKnown topics: %s' % (', '.join([str(x) for x in
    self.topics]))
    TypeError: iteration over non-sequence

    What did I do wrong?

    - Fencer
  • Stephen Hansen at Aug 9, 2009 at 6:06 pm

    only the first topic is printed. If topics only contain a single topic I
    get this error:
    Traceback (most recent call last):
    File "C:\Users\fencer\workspace\Find Expert\src\find_expert.py", line 57,
    in <module>
    print experts[1]
    File "C:\Users\fencer\workspace\Find Expert\src\find_expert.py", line 21,
    in __str__
    output += '\nKnown topics: %s' % (', '.join([str(x) for x in
    self.topics]))
    TypeError: iteration over non-sequence

    What did I do wrong?
    It looks like, "if topics contains only a single topic", means:

    self.topics = MyTopic

    was done at some point. What you should do is make self.topics ALWAYS be a
    list: even if it's only a list of one item.

    So you do

    self.topics.append(MyTopic)

    when you add that one topic. That way self.topics is always a list.
    Sometimes empty, sometimes containing one element, sometimes containing
    many.

    --S
    -------------- next part --------------
    An HTML attachment was scrubbed...
    URL: <http://mail.python.org/pipermail/python-list/attachments/20090809/cbc22105/attachment-0001.htm>
  • MRAB at Aug 9, 2009 at 6:10 pm

    Fencer wrote:
    jon rascal wrote:
    You're turning your list into a string -- try this:
    ', '.join([str(x) for x in self.topics])
    Thanks for your quick reply, unfortunately it didn't quite work for me.
    Say topics contain two topics: polemics, and the parthenon I get this
    output:
    e2:Carla
    Known topics: t5:Polemics

    only the first topic is printed. If topics only contain a single topic I
    get this error:
    Traceback (most recent call last):
    File "C:\Users\fencer\workspace\Find Expert\src\find_expert.py", line
    57, in <module>
    print experts[1]
    File "C:\Users\fencer\workspace\Find Expert\src\find_expert.py", line
    21, in __str__
    output += '\nKnown topics: %s' % (', '.join([str(x) for x in
    self.topics]))
    TypeError: iteration over non-sequence

    What did I do wrong?
    Try printing self.topics. It should always be a list of topics.
  • Fencer at Aug 9, 2009 at 6:56 pm

    MRAB wrote:
    Try printing self.topics. It should always be a list of topics.
    Ah, yes, that made me find a bug when I was creating the Expert objects:
    the lists of known topics were not created properly. I should have
    posted more code I suppose! Thanks for the help, this problem has now
    been solved. I guess I can't use a join to print the known experts as I
    described in my first post.

    - Fencer
  • Piet van Oostrum at Aug 9, 2009 at 8:15 pm

    Fencer (F) wrote:
    F> Also, notice the code I've commented out. If I can get the join above to
    F> work (with your help) my next question is how to present the known experts
    F> in a comma separated list with only expert_id and name? I can't use the
    F> normal __str__() method (the one I'm writing here) because it prints too
    F> much information. Does that mean a join is out of the question?
    F> MRAB wrote:
    Try printing self.topics. It should always be a list of topics.
    F> Ah, yes, that made me find a bug when I was creating the Expert objects:
    F> the lists of known topics were not created properly. I should have posted
    F> more code I suppose! Thanks for the help, this problem has now been solved.
    F> I guess I can't use a join to print the known experts as I described in my
    F> first post.
    Yes, you can. But you need an additional method that gives only the id
    and name. Like this:

    ------------------------------------------------------------------------
    class Expert:
    '''An expert'''
    def __init__(self, id, name, topics):
    self.expert_id = id
    self.name = name
    self.topics = topics
    self.known_experts = []

    def add_expert(self, expert):
    self.known_experts.append(expert)

    def __str__(self):
    output = (self.brief_str() +
    '\nKnown topics: %s' % (', '.join(map(str, self.topics))) +
    ('\nKnown experts: %s' %
    (', '.join(exp.brief_str() for exp in self.known_experts))))
    return output

    def brief_str(self):
    '''Gives a brief description of the expert: just the id and name.'''
    return '%s:%s' % (self.expert_id, self.name)

    class Topic:
    '''A topic'''
    def __init__(self, id, name):
    self.topic_id = id
    self.name = name

    def __str__(self):
    return '%s:%s' % (self.topic_id, self.name)

    topic1 = Topic('t1', 'Relativity')
    topic2 = Topic('t2', 'Math')
    topic5 = Topic('t5', 'Polemics')
    topic6 = Topic('t6', 'The Parthenon')

    expert1 = Expert('e1', 'Albert', [topic1])
    expert2 = Expert('e2', 'Leonhard', [topic2])

    expert1.add_expert(expert2)

    expert5 = Expert('e5', 'Carla', [topic5, topic6])
    expert5.add_expert(expert1)
    expert5.add_expert(expert2)

    for ex in expert1, expert2, expert5:
    print ex
    ------------------------------------------------------------------------

    (I prefer to use map instead of a list/iterator comprehension in this
    particular case. With the known_experts that isn't possible, unless
    brief_str is made into a static method)
    --
    Piet van Oostrum <piet at cs.uu.nl>
    URL: http://pietvanoostrum.com [PGP 8DAE142BE17999C4]
    Private email: piet at vanoostrum.org
  • Fencer at Aug 10, 2009 at 9:23 am
    Piet van Oostrum wrote:
    [snip]

    Thanks for your detailed reply!

    - Fencer
  • Stephen Hansen at Aug 9, 2009 at 5:37 pm
    output += '\nKnown topics: %s' % (', '.join(str(self.topics)))


    Your problem is here.

    self.topics is a list of topic instances: but you're calling str() on the
    list itself to turn the LIST itself into a string. Compare:
    x = [1,2,3]
    x
    [1, 2, 3]
    str(x)
    '[1, 2, 3]'

    Now, after str(self.topics) is done, you have one big string. A string is a
    sequence of characters (mostly). Calling ",".join(string) will do just what
    you see there-- return a string with a comma between each character.

    What you want to do, I assume, is call str() on each item in self.topics,
    and join them.

    That would be:

    output += '\nKnown topics: %s' % ( ','.join(str(item) for item in
    self.topics) )

    That's a generator expression which will do what you want, I believe.
    Provided your topic instances have a __str__ method that returns a string of
    the form "t<topic_id>:<topic_name>".

    Also, notice the code I've commented out. If I can get the join above to
    work (with your help) my next question is how to present the known experts
    in a comma separated list with only expert_id and name? I can't use the
    normal __str__() method (the one I'm writing here) because it prints too
    much information. Does that mean a join is out of the question?

    Honestly, I think you are putting too much into the Expert class's __str__
    method. I would make it do basically:

    return "%s:%s" % (self.expert_id, self.name)

    And then put the __str__ you're working on above in a different method which
    does -- more. Call it 'dump' or something. That way you CAN just use the
    normal str/__str__ from within this 'dump' and get what you want. str()
    should return that object in its stringified form. Another method is a
    better way to dump 'that object' and things 'around' it and that it 'knows'.

    But if you really must have just str(expert) and have it return the big
    chunk of information, your commented code looks about right. You'll have to
    use your knowledge of how the internal expert class works instead of relying
    on the experts just returning a str() of themselves. That's slightly bad.
    But not horrible.

    HTH,

    --S
    -------------- next part --------------
    An HTML attachment was scrubbed...
    URL: <http://mail.python.org/pipermail/python-list/attachments/20090809/748f80b8/attachment.htm>

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouppython-list @
categoriespython
postedAug 9, '09 at 5:16p
activeAug 10, '09 at 9:23a
posts9
users5
websitepython.org

People

Translate

site design / logo © 2022 Grokbase