0

I am using enums and string.join() method to form a help string in Python:

I have the following code segment:

from enum import Enum

class Estimators(Enum):
    rsac = 1
    msac = 2

Now, I create a help string as follows:

est_help = 'Valid options are: [' + (str(i.name) + ', ' for i in Estimators) + ']'

This throws a TypeError exception as:

TypeError: cannot concatenate 'str' and 'generator' objects

I was wondering what I am doing wrong. The i.name is of string type.

5
  • 7
    (str(i.name) + ', ' for i in RobustEstimators) is a generator, so you can't add it to a string, exactly as the error message tells you. Did you mean ', '.join(...)? Commented Oct 1, 2015 at 13:29
  • Maybe you need est_help = 'Valid options are: [' + str(i.name) + ', ' for i in RobustEstimators + ']'? Commented Oct 1, 2015 at 13:33
  • @KevinGuan how do you imagine that would help? Commented Oct 1, 2015 at 13:35
  • @jonrsharpe Oops, I didn't see the + ']', I thought that it's a list comprehension. Sorry for this :P Commented Oct 1, 2015 at 13:38
  • Ah yes, I see. I should have used the join method. Commented Oct 1, 2015 at 13:48

4 Answers 4

3

The error message tells you what you are doing wrong - attempting to concatenate a string and a generator. What you want to do is to make a list using list comprehension based on the generator, then use that

est_help = 'Valid options are: [{}]'.format( ', '.join( i.name for i in Estimators))

Let's decompose this into individual steps:

  1. Create the list [rsac,msac]: est_list = [str(i.name) for i in Estimators]
  2. Create a string with the list elements separated by a comma 'rsac, msac': est_str = ', '.join( est_list )
  3. Insert the string into your text template: est_help = 'Valid options are: [{}]'.format( est_str ), and get the resulting string Valid options are: [rsac, msac]'

edit: modified code incorporating suggestions from comments

est_help = 'Valid options are: [{}]'.format( ', '.join( i.name for i in Estimators ) )
Sign up to request clarification or add additional context in comments.

1 Comment

You can save some line noise by using a generator expression instead of a list comprehension - just drop the [] inside the call to join. Also, carried over from the OP but still worth mentioning, i.name is already a string, so you can drop the str call for ', '.join(i.name for i in Estimators).
2

You can join Estimators' members:

'Valid options are: [%s]' % ', '.join(Estimators.__members__)

Comments

1

Solution

est_help = 'Valid options are: [' + ",".join(str(i) for i in Estimators) + ']'

1 Comment

It would be helpful if you could explain for the OP (and future visitors) how/why this code works, or how to get to it from the position in the question, rather than just saying "here's the code".
0

Since none of the posts mentioned yet work for me(I always get 'type' object is not iterable, @lvc figured it out, I had the enum from PyPI which doesn't have the iterator function built in) here is my solution to the problem

from enum import Enum

class Estimators(Enum):
    rsac = 1
    msac = 2

e = Estimators
attributes = [attr for attr in vars(e) if not attr.startswith('__')]

est_help = 'Valid options are: ' + str(attributes).replace('\'','')

print est_help

I get the members of the class using vars since they are stored in dictionary format and then filter out all the members that start with __ and then since the elements of the list show up as strings with ' I replace those with an empty string.

Some of the code can be reduced if I combine my solution with @SigveKolbeinson's answer like so

est_help = 'Valid options are: [{}]'.format( ', '.join( [str(i) for i in vars(Estimators) if not i.startswith('__')]))

2 Comments

The difference is probably that you are using the enum package off PyPI. You can get the backported stdlib version with the enum34 package, and the versions iterating Estimators directly do work in it.
@lvc that was it. Thanks, I didn't know about that.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.