Roger,
1)
Qualquer linguagem OO que se preze tem um método padrão para transformar um objeto em string. Por exemplo, em Java, o método se chama .toString.
Mas o Guido, que criou o Python, é um gênio, e ele percebeu que na verdade é melhor ter 2 métodos para transformar um objeto em uma string:
o .str, que serve para exibir o objeto para usuário final, usada pelo comando print e pela função str
o .repr, que serve para exibir o objeto para o programador, usada
pelo console do Python e pela funçao repr
Quando queremos exibir para o usuário final, queremos deixar de fora detalhes que podem confundi-lo. Por exemplo, em Python 2.6 temos:
>>> f = 11.0/10
>>> f
1.1000000000000001
>>> print f
1.1
>>> str(f)
'1.1'
>>> repr(f)
'1.1000000000000001'
>>>
OBS: Atualmente no Python3 não temos mais estes problemas de representação.
Note que 11.0/10 em Python dá 1.1000000000000001. Este pequeno erro acontece porque existem imprecisões inevitáveis na conversão de decimal para a representação binária de números de ponto flutuante na biblioteca padrão da linguagem C, que o Python usa. Esta é a
representação interna do número, e é o que o método repr devolve.
Para exibir para o usuário, usamos print, que usa str e exibe uma aproximação para não deixar o usuário final nervoso com um erro que na verdade é bem pequeno mas visualmente parece grande.
Outro exemplo:
>>> s = u'avião'
>>> s
u'avi\xe3o'
>>> print s
avião
>>> print repr(s)
u'avi\xe3o'
>>>
Note que, ao exibir uma string Unicode, o repr coloca o prefixo u na frente, e troca qq caractere não-ASCII por uma representação hexadecimal. Mas o str mostra o resultado de um jeito mais amigável, se o terminal suportar a codificação... Portanto o repr tem a
desvantagem de mostrar uma string pouco legível, porém sempre fiel ao conteúdo, independente da codificação do terminal. Já o str tenta mostrar uma versão amigável da string, mas isso pode não ser possível em qualquer saída, devido a problemas de encoding.
A idéia, por fim, é que o repr tenta ser sempre a representação mais fiel do valor, de modo que isso seja sempre que possível verdadeiro:
>>> f
1.1000000000000001
>>> g = eval(repr(f))
>>> g == f
True
2) Seria possível, mas só e somente só, quando o unicode fosse necessário.