views:

200

answers:

7

Hello,

There is a function to capitalize a string, I would like to be able to change the first character of a string to be sure it will be lowercase.

How can I do that in Python ?

+8  A: 
def first_lower(s):
   if len(s) == 0:
      return s
   else:
      return s[0].lower() + s[1:]

print first_lower("HELLO")  # Prints "hELLO"
print first_lower("")       # Doesn't crash  :-)
RichieHindle
your original answer was perfect, but `len(s) == 0` is just bizzare.
SilentGhost
@SilentGhost: It's one of a million valid ways to say what it's saying. It's related to the problem that it's there to solve - you mustn't run the code if the string is zero length, so that's explicitly what I'm testing for. I could have said `if not s:` but that doesn't represent the problem quite so well.
RichieHindle
I'd prefer `if not len(s)` personally, but that's just being nit-picky
Daenyth
@Richie: you're solving a problem that OP doesn't have and are doing it in a C-style, to add insult to injury.
SilentGhost
@SilentGhost: Am I misunderstanding you? Are you really saying that it's better to provide an answer that fires an exception when called with an empty string than an answer that works in that case?
RichieHindle
@Richie: I'm saying that this is not what OP asks, and we should trust him to be able to assemble simple if statement on his own.
SilentGhost
@SilentGhost: None of us knows how experienced the OP is. It's easy to miss corner cases when someone provides you with code that demonstrably works. I'd rather err on the side of caution than provide an answer that I know will fail in a common case.
RichieHindle
Thorough answers like these tend to educate the asker better than concise ones. Given that the asker is asking this, it is reasonable to point out the corner case. It is an extra tidbit of knowledge that the asker can take away from the answer and keep in mind when he's making similar functions in the future.
JoshD
@RichieHindle: What about the case when `s == None`? Wouldn't the first `if` condition throw and error?
Manoj Govindan
@Manoj: Well, yes, but you have to draw the line somewhere... s.capitalize() will also fail if s is None (or an integer, or a badger :-)
RichieHindle
@RichieHindle: The test for zero length strings can be omitted if one uses slicing: `s[:1].lower() + s[1:]` also works for empty strings. I agree that there is no need to handle None.
Bernd Petersohn
@RichieHindle: Better to ask forgiveness etc. You are right :)
Manoj Govindan
+2  A: 

Simplest way:

>>> mystring = 'ABCDE'
>>> mystring[0].lower() + mystring[1:]
'aBCDE'
>>> 

Update

See this answer (by @RichieHindle) for a more foolproof solution, including handling empty strings. That answer doesn't handle None though, so here is my take:

>>> def first_lower(s):
   if not s: # Added to handle case where s == None
   return 
   else:
      return s[0].lower() + s[1:]

>>> first_lower(None)
>>> first_lower("HELLO")
'hELLO'
>>> first_lower("")
>>> 
Manoj Govindan
why the downvote?
SilentGhost
Aye. I'd also like to know why this was down voted. If there is a mistake I'll be the first to want to know.
Manoj Govindan
There is a mistake - if you pass in an empty string you get None back, since you have an empty return statement. That is unintuitive and bound to lead to bugs in the calling code.
Dave Kirby
+5  A: 
s = "Bobby tables"
s = s[0].lower() + s[1:]
JoshD
+1 for Bobby tables :)
Skilldrick
`Exploits of a Mom` :)
st0le
A: 

Interestingly, none of these answers does exactly the opposite of capitalize(). For example, capitalize('abC') returns Abc rather than AbC. If you want the opposite of capitalize(), you need something like:

def uncapitalize(s):
  if len(s) > 0:
    s = s[0].lower() + s[1:].upper()
  return s
Adrian McCarthy
I don't think it's the intention of the OP
Xavier Combelle
@Xavier: You're probably right, but it's interesting that `capitalize` mucks with the rest of the string.
Adrian McCarthy
A: 

I'd write it this way:

def first_lower(s):
    if s == "":
        return s
    return s[0].lower() + s[1:]

This has the (relative) merit that it will throw an error if you inadvertently pass it something that isn't a string, like None or an empty list.

Robert Rossney
how will it raise an exception that the other solutions wouldn't? The first opportunity for an error is when you slice and all of the other ones do that anyways.
aaronasterling
Not so - the accepted answer, for instance, doesn't raise an exception if you pass it an empty list.
Robert Rossney
+1  A: 

No need to handle special cases (and I think the symmetry is more Pythonic):

def uncapitalize(s):
    return s[:1].lower() + s[1:].upper()
Don O'Donnell
+2  A: 

One-liner which handles empty strings and None:

func = lambda s: s[:1].lower() + s[1:] if s else ''

>>> func(None)
>>> ''
>>> func('')
>>> ''
>>> func('MARTINEAU')
>>> 'mARTINEAU'
martineau