Function to return subword of a camelcase string Given a camelcase string and an index, return the subword of the string that includes that index, e.g.:

find_word('CamelCaseString', 6) -&gt; 'Case'
find_word('ACamelCaseString', 0) -&gt; 'A'


My code:

def find_word(s, index):
    for i in range(index, 0, -1):
        if s[i].isupper():
            left = i
            break
    else:
        left = 0

    for i in range(index, len(s)-1):
        if s[i].islower() and s[i+1].isupper() or s[i:i+2].isupper():
            right = i
            break
    else:
        right = len(s) - 1

    return s[left:right+1]


Can this be made more concise/efficient?
Review


Add docstrings and tests... or both in the form of doctests!

def find_word(s, index):
    """
    Finds the CamalCased word surrounding the givin index in the string

    &gt;&gt;&gt; find_word('CamelCaseString', 6)
    'Case'
    &gt;&gt;&gt; find_word('ACamelCaseString', 0)
    'A'
    """

    ...

Loop like a native.

Instead of going over the indexes we can loop over the item directly


range(index, 0, -1)



We can loop over the item and index at the same time using enumerate

for i, s in enumerate(string[index:0:-1])


However this would be slower since it will create a new string object with every slice.
If we can be sure that the givin string is a CamalCase string

Then we can drop some of your second if statement


if s[i].islower() and s[i+1].isupper() or s[i:i+2].isupper():



Would be 

 if s[i+1].isupper():

Actually your code (from a performance aspect) is quite good

We could however use a while loop to increment both side at once, for a little performance gain.


(slower, yet more readable) Alternative

A different approach to finding CamalCase words can be done with regex,

We can find all CamalCase words with the following regex: r"([A-Z][a-z]*)"

And we can use re.finditer to create a generator for our matches and loop over them, and return when our index is in between the end and the start.

import re

def find_word_2(string, index):
    for match in re.finditer(r"([A-Z][a-z]*)", string):
        if match.start() &lt;= index &lt; match.end():
            return match.group()


NOTE This yields more readable code, but it should be alot slower for large inputs.