Gareth has a lot of good points, though I disagree about raising an error.
str.find doesn't raise an error when it doesn't find the search term, it returns -1. Errors aren't always the best way to signal absence or failure. In your case, returning a boolean is a datatype mismatch. If you're going to return a different type, return
None, to indicate no result. Alternatively, return
''. Which is a string type, but empty. And of length zero, so when turned to a boolean it would be False anyway. eg.
if unique_char("banbanana"): would be evaluated as
Also note you don't need to put brackets around the value that you return,
return False works fine.
This may be irrelevant for your use case but one problem with this approach is that you're processing the whole string before you start looking for unique characters. Instead, why not check each string as it comes.
So, you'd want a set to store characters found to be duplicates. Then you just want to loop over the string, testing first for previously found duplicates, then checking if the new character is a duplicate. You can save time by ignoring all characters before the current one, as you've already found all of them to have duplicates. So this is how it could look:
"""Return the first non-repeated character in the string s.
Returns an empty string if no character is found"""
dupes = set()
for i, c in enumerate(s):
if c in dupes:
# Only search the characters ahead of this point
if c in s[i + 1:]: