First non-repeating letter The problem:  find and return the first nonrepeating character in a string, if the string does not have a nonrepeating character return an empty string. For purposes of finding the nonrepeating character it's case insensitive so 't' and 'T' appearing in the string would imply that that 't' and 'T' are not candidates for a nonrepeating character.  When you return the character you must return it as its original case.

My Solution:

def non_repeat(_str):
    counts = {}
    for pos, letter in enumerate(_str.lower()):
        if letter not in counts:
                counts[letter] = (0, pos)
        incr_val = counts[letter][0] + 1
        counts[letter] = (incr_val, pos)
    for letter in _str.lower():
        if counts[letter][0] == 1:
            return _str[counts[letter][1]]
    return ''


How can I improve the readability of my solution?  In particular, I don't like:


counts[letter][0] because the 0 index is a bit ambiguous.
calculating the incremented value as another line, incr_val; it'd be nice to do the incrementing and updating of the dict in one line.  


Anything else you could make more readable? I should add that I'm aware of collections.​Counter; for this solution I'd like to avoid using it.
IMHO looping twice over the input string is not acceptable for multiple reasons


the string is of unknown size
you invalidate your code for generators


While this might not be necessary for your project you should learn to think like that. So a single pass algorithm should collect all necessary data to answer the question (e. g. the letter in original case).

import sys
assert sys.version_info &gt;= (3, 6)

def non_repeat(s):
    repeated = set()
    candidates = dict()
    for original_case in s:
        lower_case = original_case.lower()
        if lower_case not in repeated:
            if lower_case not in candidates:
                candidates[lower_case] = original_case
            else:
                repeated.add(lower_case)
                del candidates[lower_case]

    if candidates:
        return next(iter(candidates.values()))
    else:
        return ''


This code makes use of the insertion order of a dict which is already implemented in 3.6 and guaranteed in 3.7.



Edit: generator example

Say you want to check a big file that does not fit into memory (for brevity I assume a line fits into memory). Yor write a little character generator and run your algorithm on the generator.

def char_gen(f):
    for line in f:
        for c in line.strip():
            yield c

with open('bigfile.txt') as f:
    print(non_repeat(char_gen(f)))


also you might use the algorithm on a generator expression

print(non_repeat(c for c in "aabbcd" if c != 'c'))