Python3 06 - Conjuntos (Set) - slacker...
1. Conjuntos (set)
1.1. Conjuntos são Mutáveis, frozenset não
1.2. Operadores em Conjuntos
1.3. Métodos de Conjuntos
1.3. Set Comprehensions
Conjunto é uma estrutura de dados mutável, composto de uma coletânea de objetos hashable desordenados e com elementos únicos, ou seja, sem duplicatas. Conjuntos ainda suportam operações matemáticas de união, interseção, diferença e diferença simétrica.
Objetos hashable são todos aqueles que possuem o método __hash__(), o qual retorna um valor inteiro constante, ou seja, o mesmo valor por toda a vida do objeto. Objetos com o mesmo hash() são considerados idênticos quando empregados como índice. Isto ficará mais claro quando for tratado sobre a estrutura de dados dicionário. Entretanto, esta característica é indispensável para que conjuntos possam serem empregados como chaves em dicionários, como será mostrado no próximo texto.
Um conjunto pode ser criado usando chaves ou pela função set(), passando como elementos qualquer conjunto de objetos ou mesmo um iterável. Veja os comandos a seguir:
No primeiro conjunto, cesta, são adicionadas diversas frutas, mas as repetidas são excluídas do conjunto. Em seguida, são criados os dois conjuntos a e b, com as letas das strings 'São Paulo' e 'Espírito Santo'. Observe que a ordem dos elementos dos conjuntos não é a ordem de entrada, ou seja, não são ordenados. Por fim, o conjunto c utiliza uma diversidade de tipos de objetos imutáveis, como inteiros, complexo, string, um float e uma tupla. Todos estes imutáveis são hashables e, portanto, retornam um código hash único para elementos diferentes.
Embora conjuntos possam ser empregados em laços de repetição, ou seja, sejam iteráveis, eles também não possuem o método __getitem__() por não serem ordenados, como em listas e tuplas, e por isto não podem ser indexados. Uma tentativa de indexar um elemento de um conjunto gera um erro TypeError:
Conjuntos são objetos mutáveis e podem ter elementos adicionados e removidos através dos métodos add(), pop() e remove().
Explico melhor estes métodos mais adiante. Existe um tipo de conjunto que é imutável e também pode ser usado como elemento em um conjunto.
FrozenSet são conjuntos imutáveis.
Conjuntos suportam um grupo específico de operadores específicos além dos operadores convencionais de comparação e operação, mas com comportamentos um pouco distintos.
Para os exemplos a seguir, considere os conteúdos dos conjuntos a e b como sendo o conjunto de letras nas strings 'laranja' e 'marajo', respectivamente:
Segue a lista de operadores:
__and__ – mesmo que o operador &. Retorna a interseção dos conjuntos, ou seja, os elementos comuns entre os dois conjuntos,
__or__ – mesmo que o operador |. Retorna a união dos elementos contidos nos dois conjuntos,
__xor__ – o mesmo que o operador ^. Retorna a diferença simétrica entre os dois conjuntos, ou seja, os elementos do conjunto a que não estão contidos no conjunto b e os elementos de b que não estão contidos em a,
__sub__ – operador subtração, -. A operação a - b retorna os elementos de a, removidos os elementos semelhantes em b, ou seja apenas os elementos 'n' e 'l'. O contrário, b - a retornará os elementos 'o' e 'm'. Veja no exemplo abaixo:
Observe que a operação (a - b) | (b - a) é a definição de a ^ b:
__iand__, __isub__, __ixor__, __ior__ – são implementações para os operadores &=, -=, ^= e |=, respectivamente.
Tab 03: Operadores Lógicos Compostos
&= interseção igual a &= b a = a & b
-= diferença igual a -= b a = a – b
^= dif. sim. igual a ^= b a = a ^ b
|= união igual a |= b a = a | b
__rand__, __rsub__, __rxor__, __ror__ – este 'r' corresponde a 'right'. Essencialmente, implica em trocar os conjuntos de posição nas operações. Por exemplo a.__rxor__(b) = b ^ a, ao invés de a ^ b. Com exceção ao operador de subtração, todos os demais retornaram o mesmo resultado.
__eq__, __ne__, __ge__, __gt__, __le__, __lt__ – Operadores condicionais estão definidos para conjuntos, mas operam de forma diferenciada ao visto em lista e tuplas. Como conjuntos são desordenados, os operadores de igualdade e diferença comparam os conjuntos elemento a elemento, independente da ordem que os seus elementos possam ser apresentados.
Os operadores de '>' e '<' correspondem aos operadores 'contém' e 'está contido' em conjuntos.
Como b esta contido em a, as duas primeiras comparações (a > b e b < a) retornam verdadeiras, já as duas seguintes retornam falso.
Como feito até o momento, métodos específicos a construção e atributos da classe set (conjuntos) não foram abordados, deixando este debate para adiante.
Segue os métodos dos conjuntos.
add(Valor) – adiciona o elemento Valor ao conjunto.
clear() – apaga todo o conteúdo do conjunto.
copy() – cria uma cópia do conteúdo do conjunto. Como conjuntos são mutáveis, um método para fazer a sua cópia é essencial para evitar problemas como o ilustrado com as listas, no exemplo de matriz no texto anterior. Veja o exemplo:
Na primeira linha, c recebe uma cópia de a. Já d apenas aponta para o objeto de c. Ao apagar c, d também é apagado, mas o mesmo não ocorre a a, pois são objetos distintos na memória.
difference(set), intersection(set), union(set) e symmetric_difference(set) – estes métodos retornam o mesmo que os operadores -, &, | e ^, respectivamente.
difference_update(set), intersection_update(set), update(set) e symmetric_difference_update(set) – estes métodos retornam o mesmo que os operadores compostos -=, &=, |= e ^=, respectivamente. Observe que o método union_update(set) não existe, é apenas update(set).
pop() – remove um elemento arbitrário do conjunto.
remove(Valor) – remove o elemento Valor do conjunto. Se o elemento não existir, retorna o erro KeyError.
discard(Valor) – remove o elemento Valor do conjunto. A única diferença com o método remove(Valor) é que o discard(Valor) não retorna erro caso o elemento não exista.
isdisjoint(set) – retorna verdadeiro se os dois conjuntos possuem interseção nula.
issubset(set) – retorna verdadeiro se o conjunto for um subconjunto do outro.
issuperset(set) – retorna verdadeiro se o conjunto argumento (set) for um subconjunto do conjunto. É o contrário do issubset(set).
Como em listas, conjuntos também podem ser gerados usando um set comprehensions, o qual funciona com uma expressão em um laço de repetição fechado entre chaves. As sintaxes suportadas são as mesmas de listas, apenas substituindo os colchetes por chaves:
{  for  in  }
{  for  in  if  }
Duas formas diferentes de construir o mesmo conjunto das letras de 'abracadabra' maiores que c.
A grande aplicação para conjuntos é o seu emprego como chaves em outras estruturas de dados como dicionários, apresentado próximo texto, ou chaves de bancos de dados, além de aplicações matemáticas como conjuntos. Embora não o tenha utilizado muito, é aconselhável ter consciência de suas possibilidades em momento de programação.
O próximo texto será sobre dicionários, uma estrutura de dados composta, mas que pode empregar qualquer tipo de imutável como índice, além de inteiros. A lista de índices de um dicionário, como veremos, é um conjunto.