Как сделать функцию, которая работала бы с любыми списками?
Если следовать обшепринятой логике - номер строиться исходя из лексикографического порядка исходного массива, то все решается в одну строчку:

lt= ['abc', 'apple', 'pen', 'abc', 'pen', 'pc']
lt_num=[sorted(list(set(lt))).index(x) for x in lt]

Результат:
[0, 1, 3, 0, 3, 2]
items = ['abc', 'apple', 'pen', 'abc', 'pen', 'pc']
Вариант #1:
cache = {}
[cache.setdefault(item, len(cache)) for item in items]
Вариант #2:
from functools import lru_cache
from itertools import count

@lru_cache(maxsize=None)
def enumerate_as_seen(_, counter=count()):
    return next(counter)

list(map(enumerate_as_seen, items))