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
David Plans
2,756 PointsSillycase code challenge slicing
This challenges says:
The first half of the string, rounded with round(), should be lowercased.
The second half should be uppercased.
E.g. "Treehouse" should come back as "treeHOUSE"
Whilst trying things out using len() method to get 'half' the string, I tried:
def sillycase(mystring):
return ((mystring[:(len(mystring)/2)]).lower(), (mystring[(len(mystring)/2):]).upper())
...in an emacs buffer, which I then threw at iPython. However (I'm a n00b), looks like this emacs' ipython is running python 2.7...which forgives me using len within a slice index:
In [1]: def sillycase(mystring):
...: return ((mystring[:(len(mystring)/2)]).lower(), (mystring[(len(mystring)/2):]).upper())
...:
In [2]: sillycase('Treehouse')
Out[2]: ('tree', 'HOUSE')
In [3]:
In python 3 ipython, however, I get:
In [1]: def sillycase(mystring):
...: return ((mystring[:(len(mystring)/2)]).lower(), (mystring[(len(mystring)/2):]).upper())
...:
In [2]: sillycase('Treehouse')
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-2-805e5628247d> in <module>()
----> 1 sillycase('Treehouse')
<ipython-input-1-8c23603c5368> in sillycase(mystring)
1 def sillycase(mystring):
----> 2 return ((mystring[:(len(mystring)/2)]).lower(), (mystring[(len(mystring)/2):]).upper())
3
TypeError: slice indices must be integers or None or have an __index__ method
(which is of course what the workspace editor within the challenge says, too) ....I've been caught out by this before (differences between 3 and 2.7), and I'm sorry to complicate things (I'm just trying to learn a little vim and emacs whilst learning python), but does this mean python 3 is more strict about what you can pass as an index to a slice?
I also realize I've ignored the actual instructions in that I'm not using round(), but trying to round() the output of len(mystring) I get:
'int' object has no attribute 'round'
...and obviously casting to float doing (float(len(string)).round()) complains that:
'float object has no attribute 'round'
I'm missing something simple here, and complicating things way too much...right?
[UPDATE]
Studying this thread in StackOverflow, which points out that the division operator has been changed in Python3, I can now make this work:
def sillycase(mystring):
return ((mystring[:(len(mystring)//2)]).round().lower() +
(mystring[(len(mystring)//2):]).round().upper())
in that I get the right result from iPython3:
In [1]: run SillyCase.py
In [2]: sillycase('Treehouse')
Out[2]: 'treeHOUSE'
...but I'm still missing out how to use round() properly in there, because the workspace complains:
Bummer! Your function didn't return the right output. Got 'kenNETH', expected 'kennETH'.
and trying to use round() within the slice gives me int/float errors:
AttributeError: 'str' object has no attribute 'round'
5 Answers
Kenneth Love
Treehouse Guest TeacherNothing has to be added to the halves to solve this challenge. You're having to add 1 because you're using integer division instead of rounding the result of the division.
Look at this accepted solution:
def sillycase(string):
half = round(len(string)/2)
return string[:half].lower() + string[half:].upper()
When we do round(len(string)/2), we get an integer, which is required for slices. But we get it rounded as it should be. If I did round(len(string)//2), I'd get an integer from the integer division (//) which would then not be rounded to anything new. In that case, yes, I'd have to add one. But what if the result of real division was 2.25? The // would give back 2, which I'd then add 1 to and I'd have the wrong number.
Jeff Busch
19,287 PointsHi David,
With the help of this post I passed the code challenge.
Jeff
def sillycase(theWord):
return theWord[:round(len(theWord) / 2.0)].lower() + theWord[round(len(theWord) / 2.0):].upper()
David Plans
2,756 PointsThanks, Jeff! I hadn't search far back enough to find that post...weird though that the case for round() means that in python3, to pass the challenge on 'Kenneth', you have to +1 the rounded number otherwise you still get:
Bummer! Your function didn't return the right output. Got 'kenNETH', expected 'kennETH'.
...with your code.
Instead, this:
def sillycase(mystring):
return ((mystring[:round(len(mystring)//2.0 + 1)]).lower() +
(mystring[round(len(mystring)//2.0 + 1):]).upper())
...actually passes the challenge. I don't get it though, because isn't Python3 supposed to sound 3.5 up to 4 and therefore get the half in the seven letters of 'Kenneth' to be all the way up to second 'n'?
Jeff Busch
19,287 PointsYou don't really have to do much searching. I just copy and paste the code challenge question into google and the top selections are usually from the Treehouse forum.
Chris Grazioli
31,225 Points@Kenneth Love I went another way but I tested it using pythontutor.com which uses python 2.7 apparently there is some issue with the type in the grader
def sillycase(string):
if len(string)%2 !=0:
front_count = (len(string)-1)/2
else:
front_count=len(string)/2
return string[0:front_count].lower()+string[front_count:].upper()
it runs fine online in python 2.7 but then the treehouse grader shoots back: BUMMER: TypeError: slice indices must be integers or None or have an index method
Kenneth Love
Treehouse Guest TeacherI've updated the prompt and hints. Division is one of the things that changed between legacy Python and modern Python.
Chris Grazioli
31,225 PointsSo, following that logic I type-casted (am I even saying that right) by wrapping the "int()" around 'front_count'
def sillycase(string):
if len(string)%2 !=0:
front_count = (len(string)-1)/2
else:
front_count=len(string)/2
return string[0:int(front_count)].lower()+string[int(front_count):].upper()
Kenneth Love Can you maybe explain what is going on there with the grader, what is the difference with the python 2 & 3, does the math in 3 automatically put out a float or something? I vaguely recall maybe seeing something about that somewhere.
Kenneth Love
Treehouse Guest TeacherYes, 3 gives you a float while 2 always gave an int unless you divided with a float.
You're doing too much work in your function. You don't need to subtract anything or check the length.
Kaisa Boro
1,310 Pointsdef sillycase(string): return string[:int(len(string)/2)].lower() + string[int(len(string)/2):].upper()
Daniel JAHENY
1,912 PointsMy code isn't very elegant but it did the trick:
def sillycase(s): l = list(s) lower_case = s[:len(s)//2] upper_case = s[len(s)//2:] low = lower_case.lower() up = upper_case.upper() result = low + up return(result)
David Plans
2,756 PointsDavid Plans
2,756 PointsThanks Kenneth! I guess I got all tangled up on floor versus integer division...but also I was using round() at
((mystring[:(len(mystring)//2)]).round().lower()which is clearly wrong, asround(len(string)/2)is the right way to go...I think I've understood the problem now, but I found it difficult to understand default behaviour of integer versus floor division (especially when I found the behaviour changed from version to version).
Thanks all!
Kenneth Love
Treehouse Guest TeacherKenneth Love
Treehouse Guest TeacherDavid Plans completely understandable! Thankfully, we only deal with Python 3 here at Treehouse. That means
/will always give you a float, and//will always give you an integer. Integer division is really the same as floor division becausemath.floor(5/2)and5 // 2will both give you2as the answer.Personally, I find this behavior really annoying. I rarely want floor division and if I do want it, I'll ask for it explicitly.
David Plans
2,756 PointsDavid Plans
2,756 PointsThanks, Kenneth!
Really starting to get it. For reference, in case other people follow Jeff Busch's advice and Google for this code challenge, here's an interesting post by Guido Van Rossum on his 'history of Python' blog which explains the decisions behind the integer division changes in Python, and also points at the right PEP
Chris Grazioli
31,225 PointsChris Grazioli
31,225 PointsThe problem says DONT worry about rounding? yet here we are using "round()" What the heck are you guys trying to do to me. I see problems like this, with statements like that, too many times in a day...and they're gonna find me face down at my desk with blood running from my ears and nose.
Kenneth Love
Treehouse Guest TeacherKenneth Love
Treehouse Guest TeacherChris Grazioli this thread is 2 years old and predates the current version of the course. Probably not completely accurate anymore :D
Haf Me
145 PointsHaf Me
145 PointsWhy doesn't it work when i use int() instead of len()?