Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python

Object-Oriented Python (2) Code Challenge 'Construction Zone' (re: @classmethod)

In Object-Oriented Python (2) Code Challenge 'Construction Zone', regarding creating a class method, I am not able to pass. However, when I test my code, it seems to be functional -- so I am either missing a test case or fundamentally misunderstood the code challenge. My code is below. Please help and advise, thanks!

Here is the question:

Let's practice using @classmethod! Create a class method in Letter named from_string that takes a string like "dash-dot" and creates an instance with the correct pattern (['_', '.']).

Here is the URL:

class Letter:
    def __init__(self, pattern=None):
        self.pattern = pattern

    def __iter__(self):
        yield from self.pattern

    def __str__(self):
        output = []
        for blip in self:
            if blip == '.':
                output.append('dot')
            else:
                output.append('dash')
        return '-'.join(output)

    @classmethod
    def from_string(cls, string):
        stringList = string.split('-')
        patternList = []
        for blip in stringList:
            if (blip.lower() == 'dash'):
                patternList.append('_')
            elif (blip.lower() == 'dot'):
                patternList.append('.')
            else:
                pass
        return cls(Letter(pattern = patternList))


class S(Letter):
    def __init__(self):
         pattern = ['.', '.', '.']
         super().__init__(pattern)

7 Answers

Steven Parker
Steven Parker
231,275 Points

Your return value is overly complicated.

The class argument of the method (cls) is most likely to be "Letter", so your return value is essentially "Letter(Letter(pattern = patternList))". I'm not sure how you were testing it, but I wouldn't expect that to work.

But all you need to return is an instance initialized with your patternList, which is much simpler:

        return cls(patternList)

Interestingly enough, I could still get the correct outputs when using the other methods in the class, e.g.:

dd = Letter.from_string("dash-dot")
print(dd)
for blip in dd:
    print(blip)

However these revealed I did have a class within a class (I guess):

print(type(dd))  # returns class
print(type(dd.pattern))  # also returns class  # should be list
print(dd.pattern) # is like calling print(dd)  # should be ['_','.']

However, I guess I somehow had a class in the class ... thanks for the help, all cleared up!

J llama
J llama
12,631 Points

They do a terrible job of teaching oop. other tutorials are fine but man is this oop is awful. customer service rep is not very good either as they won't respond to my emails

Steven Parker
Steven Parker
231,275 Points

Are you using the address on the Support page? But they primarily handle actual bugs, for knowledge questions they will likely direct you here to the forum.

Grant Murphy
Grant Murphy
10,072 Points

I agree I was tracking really well with the course but this oop section, especially the code challenges are difficult due to being too abstract I think.

OOP section is just too long, probably you got distracted. As a student, I recommend you to go back to the classes that you didn't understand and always take notes.

Jimmy Holway
Jimmy Holway
10,703 Points

I have basically the same issue and went about solving it in a very similar way.

What I found was that Letter.from_string('dash-dot-dash') will at some point read this string and fill a new list with the correct characters (['_','.','_']) but when the result is printed, it's converted back by the __str__ method.

Here is my code:

class Letter:
    def __init__(self, pattern=None):
        self.pattern = pattern

    def __iter__(self):
        yield from self.pattern

    def __str__(self):
        output = []
        for blip in self:
            if blip == '.':
                output.append('doot')
            else:
                output.append('dash')
        return '-'.join(output)

    @classmethod
    def from_string(cls, str):
        split_str = str.split('-')
        list = []
        for e in split_str:
            if e == 'dash':
                list.append('_')
            else:
                list.append('.')
        return cls(list)

class S(Letter):
    def __init__(self):
         pattern = ['.', '.', '.']
         super().__init__(pattern)

b = Letter.from_string('dash-dot-dash')

I checked to make sure the __str__class was actually converting it back by misspelling dot to doot:

>>> b = Letter.from_string('dash-dot-dash')
>>> print(b)
dash-doot-dash

I used this python visualizer to discover this.

If I don't understand why this is happening I'll flip out so if anyone has a suggestion on why this is happening I would be super appreciative!

Steven Parker
Steven Parker
231,275 Points

Like you said, the __str__ method is invoked automatically to convert the object into a string for printing.

What part are you confused about?

Erika Suzuki
Erika Suzuki
20,299 Points

Much safer with if-elif-else though.

Python 3.5 in pycharm returns dash-dot, but challenge was ok. What's wrong with this?

class Letter:
    def __init__(self, pattern=None):
        self.pattern = pattern

    def __iter__(self):
        yield from self.pattern

    def __str__(self):
        output = []
        for blip in self:
            if blip == '.':
                output.append('dot')
            else:
                output.append('dash')
        return '-'.join(output)

    @classmethod
    def from_string(cls, string):
        new_list = []
        my_list = string.split("-")

        for item in my_list:
            if item == 'dot':
                new_list.append('.')
            elif item == "dash":
                new_list.append("-")

        return cls(new_list)


class S(Letter):
    def __init__(self):
        pattern = ['.', '.', '.']
        super().__init__(pattern)


print(Letter.from_string("dash-dot"))
``
Steven Parker
Steven Parker
231,275 Points

For future issues, always start a fresh question instead of adding one as an "answer" to another question.

But I see where this code is representing a dash using a hyphen ("-"), but the challenge instructions say to represent dash with an underscore ("_") instead.

Cristian Figueiredo dos Santos
Cristian Figueiredo dos Santos
6,892 Points

Steven Parker is right, you have to change new_list.append("-") by new_list.append("_") instead. That was my mistake and I guess it's yours too

Steven Soekha
Steven Soekha
10,513 Points

You don't have to use the "()" when making a "if-statement", not in Python!

Erika Suzuki
Erika Suzuki
20,299 Points

Though I agree with your comment, it should be posted as a reply under the OP's question. :P

I can get my class method to work in workspaces but I can't pass the Code Challenge. Perhaps I don't understand exactly what Kenneth Love was expecting as the result. Any suggestions will be appreciated. I don't have much more hair to loose!

@classmethod
def from_string(cls, string):
    stringList = string.split('-')
    output = []
    for blip in output:
        if (blip.lower() == 'dash'):
            output.append('_')
        elif (blip.lower() == 'dot'):
            output.append('.')
        else:
            pass
    newCls = cls(output)
    return newCls
Steven Parker
Steven Parker
231,275 Points

You split the incoming argument into "stringList", but then never use it. You probably intended to use it as the loop iterator, but the code currently tries to loop using the newly-created empty list output.

For future questions, always start a fresh post. "Piggybacking" on old questions does not have the best chance of a variety of responses.

Jimmy Holway
Jimmy Holway
10,703 Points

It seems I posted this code thinking it wouldn't pass without trying it first. Oops.