segunda-feira, 24 de outubro de 2016

Vamos falar de booleanos...

Lembra-se de já termos falado em booleanos? Pois hoje vamos ver ver umas funções especialmente desenhadas para este tipo de variáveis. Vamos começar por all():
>>> all([0,1,0,3,5])
False
>>> all((0,1,0,3,5))
False
>>> all((5,1,10,3,5))
True
>>> all([])
True
>>> all([True,False,True])
False
Bem, o que temos aqui? Pense no all() como uma espécie de operador and com vários argumentos encaixados dentro de um iterável (uma lista ou um tuplo). Esta função resulta em True apenas se todos os elementos forem True (ou se o iterável estiver vazio). Claro que a definição do que é falso tem de ter tida em conta, como vimos aqui. No entanto, temos de notar uma coisa: embora uma lista vazia [] valha como False, isto não é o mesmo que all([]), que testa o conteúdo da lista e não a própria lista.
Se existe uma espécie de and para iteráveis, será que existe uma espécie de or? Claro que sim, e chama-se any():
>>> any([0,1,0,3,5])
True
>>> any((0,0,0,0,0))
False
>>> any([])
False
Como seria de esperar, o any(), resulta em False apenas se todos os elementos forem False. Bem, mas com isto tudo, existe alguma maneira de sabermos qual o valor booleano de algo sem termos de nos lembrar das regras explicitadas no outro dia? Sim, felizmente existe a função bool(), que converte o seu argumento num True ou False, dependendo do que está lá dentro:
>>> bool([])
False
>>> bool(None)
False
>>> bool(0)
False
>>> bool('')
False
>>> bool()
False
Aqui assim podemos ver o que é False em Python com mais facilidade. E por hoje é tudo! Curtinho, mas informativo!

segunda-feira, 17 de outubro de 2016

E finalmente os dicionários

Vamos então falar finalmente sobre dicionários. Estas estruturas são também parecidas com as listas, mas têm a particularidade de serem construídas por pares de chave:valor. A ideia é termos uma correspondência direta entre valores. Nada como um exemplo para ilustrar:
>>> dicio = {0:'zero', 1:'um', 'UM':1, 'ZERO':0}
>>> dicio[0]
'zero'
>>> dicio['UM']
1
Comentários: o dicionário cria-se com chavetas {}, e cada par chave:valor é separado por dois pontos :, enquanto os pares são separados por vírgula. Podemos então aceder ao valor correspondente a cada chave usando a notação dicionário[chave]. As chaves e os valores podem assumir o tipo que quisermos, seja um número inteiro ou com vírgula, uma cadeia de caracteres ou mesmo um tuplo. Mas enquanto as chaves têm que ser imutáveis, não podendo aceitar listas como tipo, os valores podem aceitar listas. Além disso, não podem existir duas chaves iguais, e se ocorrer, a chave que permanece válida é a última a ser inserida. Um exemplo funciona melhor:
>>> dicio = {0:'zero', 1:'um', 0:'ZERO'} # reparar nos dois 0!!
>>> dicio[0]
'ZERO'
Eu estou sempre a apresentar outras coisas: para fazermos um comentário em Python, basta escrever o símbolo de cardinal # e daí para a frente é tudo ignorado nessa linha. Isto também se aplica a programas em Python. E acho que o exemplo acima explica-se a si mesmo.
Também podemos alterar, adicionar e eliminar elementos num dicionário:
>>> dicio2 = {'Nome':'Chico', 'Idade':25}
>>> dicio2['Nome']
'Chico'
>>> dicio2['Nome'] = 'Francisco' # alterar o valor da chave 'Nome'
>>> dicio2['Nome']
>>> dicio2['Apelido'] = 'Santos' # adicionar uma nova chave
>>> dicio2   # ver o conteúdo do dicionário
{'Idade': 25, 'Nome': 'Francisco', 'Apelido': 'Santos'}
>>> del dicio2['Idade'] # apagar o par de chave 'Idade'
>>> dicio2
{'Nome': 'Francisco', 'Apelido': 'Santos'}
>>> del dicio2 # apagar o dicionário todo
Assim já ficamos com uma boa ideia do que se pode fazer com dicionários! De notar que não se pode fazer slicing com dicionários. Mas podemos iterá-los com um ciclo for:
dicio = {'Idade': 25, 'Nome': 'Francisco', 'Apelido': 'Santos'}
for i in dicio:
    print(i, dicio[i])
Isto vai dar:
Idade 25
Nome Francisco
Apelido Santos
Também podemos usar as funções min(), max(), len() e sorted(), e também o operador in. Vejamos como funcionam:
>>> dicio = {'Idade': 25, 'Nome': 'Francisco', 'Apelido': 'Santos'}
>>> min(dicio) # resulta na primeira chave, em ordem alfabética
'Apelido'
>>> max(dicio) # resulta na última chave, em ordem alfabética
'Nome'
>>> len(dicio)
3
>>> sorted(dicio) # ordenar as chaves alfabeticamente
['Apelido', 'Idade', 'Nome']
>>> 'Nome' in dicio # ver se 'Nome' é uma chave
True
>>> 'Santos' in dicio # ver se 'Santos' é uma chave
False
Como deve ter notado, todas estas funções se aplicam às chaves. Para aceder diretamente a valores, teremos de voltar a este tema mais tarde, depois de falarmos de programação por objetos.
Finalmente, vamos falar na função geradora de um dicionário, dict():
>>> dicio = dict(Idade=25, Nome='Francisco', Apelido='Santos')
>>> dicio
{'Apelido': 'Santos', 'Idade': 25, 'Nome': 'Francisco'}
Como se percebe, usa-se como argumento pares chave=valor separados por vírgulas, com a nota de que aqui a chave tem que ser uma cadeia de caracteres.
E pronto, para a semana há mais!

segunda-feira, 10 de outubro de 2016

Mais estruturas de dados: os tuplos

Realmente, já vamos para a 13ª contribuição para este blogue e ainda não falámos em duas estruturas de dados muito importantes em Python: os tuplos e os dicionários. Estas estruturas fazem lembrar as listas, mas têm características próprias. Vamos começar pelos tuplos. Um tuplo é como uma lista, mas os seus elementos são imutáveis. Cria-se como se cria uma lista, só que em vez de parêntesis retos [], usam-se parêntesis curvos (), embora estes sejam opcionais na sua criação:
>>> (1,2,3)
(1, 2, 3)
>>> 1,2,3
(1, 2, 3)
Tal como numa lista, podemos usar slicing para aceder a vários elementos:
>>> a=(1,2,3,4,5,6)
>>> a[1]
2
>>> a[2:4]
(3, 4)
>>> a[::2]
(1, 3, 5)
>>> a[1::2]
(2, 4, 6)
Tal como com as listas, nos tuplos podemos obter o elemento 1 (a contar a partir do elemento 0) e os elementos 2 a 4, excluindo o 4. Aqui aproveito e mostro outra maneira de fazer o slicing: com três parâmetros. Os dois primeiros continuam a ser o primeiro e o último, excluindo o último. Se não indicarmos nenhum, cobre todos os elementos, mas o terceiro parâmetro indica qual o salto entre elementos. Nos exemplos acima, salta de 2 em 2 elementos. Giro, não é? Isto também funciona com cadeias de caracteres:
>>> 'Teste de saltarelos'[::2]
'Tsed atrls'
>>> 'Teste de saltarelos'[::-1]
'soleratlas ed etseT'
>>> 'Teste de saltarelos'[::-3]
'setsdtT'
Bem, mas voltemos aos tuplos. Como já mencionei, ao contrário das listas, os tuplos são imutáveis. Assim, não podemos alterar um elemento de um tuplo, nem apagar um elemento. Só podemos adicionar elementos (que corresponde a criar um tuplo novo):
>>> a = (1,)
>>> a = a + (2,3)
>>> a
(1, 2, 3)
Algumas notas: sim, quando fazemos o tuplo de um só elemento (1,), tem de ter uma vírgula, para não se confundir com um cálculo com parêntesis. Podemos mesmo retirar os parêntesis, mas a vírgula tem de ficar.
E tal como com as listas, também podemos iterar os tuplos:
nums = (1, 4, 5, 6, 3)
for i in nums:
    print(i)
Vai resultar em:
1
4
5
6
3
Em comum com as listas, os tuplos também aceitam as funções max(), min(), sum(), len(), reversed() e o operador in, que funcionam exatamente da mesma maneira. Também podemos aplicar a função sorted() num tuplo, mas o resultado é uma lista. E também temos uma função que cria tuplos, que incrivelmente se chama tuple():
>>> tuple(reversed([6,4,2,7,9]))
(9, 7, 2, 4, 6)
Esta função, tal como a sua análoga list(), também tem outras aplicações, ilustradas a seguir:
>>> tuple('Python')
('P', 'y', 't', 'h', 'o', 'n')
>>> tuple(range(6))
(0, 1, 2, 3, 4, 5)
Voltando atrás à atribuição de variáveis, vemos agora que a atribuição de várias variáveis separadas por vírgulas (um,dois,tres = 1,2,3) não é mais do que usar um tuplo para este fim...
Finalmente, porquê este nome de 'tuplo'? Bem, se pensarmos nos nomes 'duplo', 'triplo', 'quádruplo'... 'múltiplo', vemos que foi daí que veio. As coisas que vamos aprendendo...

segunda-feira, 3 de outubro de 2016

Voltemos aos ciclos

Olá de novo. É altura de voltarmos aos ciclos, seja através de for, seja através de outro tipo de ciclos que vamos já ver. Já mencionei que se usa muito o comando for com a função range(). Vamos ver um programa de exemplo em que apresentamos o comando continue:
for i in range(10):
    if i%2 == 0:
        print(i,'é par!')
        continue
    print(i,'é impar!')
Se tiver experimentado executar este pequeno programa, verá que o resultado é:
0 é par!
1 é impar!
2 é par!
3 é impar!
4 é par!
5 é impar!
6 é par!
7 é impar!
8 é par!
9 é impar!
O que é relevante aqui é que, sempre que se chega a um comando continue dentro de um ciclo for, o ciclo é interrompido e passa automaticamente para a iteração seguinte, ignorando os comandos abaixo de continue. Vamos ver agora o que faz o comando break:
for i in range(10):
    if i > 4:
        print('Estou farto de números!')
        break
    print(i)
Isto vai resultar em:
0
1
2
3
4
Estou farto de números!
Podemos ver que o comando break dentro de um ciclo for vai fazer com que se salte para fora do ciclo. Ainda há mais um comando que podemos incluir:
lim = int(input('Dá-me um número: '))
for i in range(10):
    if i > lim:
        print('Estou farto de números!')
        break
    print(i)
else:
    print('Chegámos mesmo ao fim!')
Este programa vai pedir um número, e se esse número for menor que 9, vai "fartar-se de números", caso contrário vai "chegar mesmo ao fim". Isto é, o else no final do ciclo for só é executado se as iterações do ciclo chegarem ao fim. Curioso, não é?
Mas vale a pena mencionar que existe um outro tipo de ciclo, o que usa o comando while. Neste tipo de ciclos, enquanto a condição em frente a while for verdadeira, o ciclo repete-se infinitamente (o que pode ser verdadeiramente perigoso!):
r = ''
while r != 'por favor':
    r = input('Pede para sair com modos... ')
    if r=='':
        continue
    elif r=='deixa-me!':
        print('Vá, não te irrites!...')
        break
else:
    print('Muito bem educado!')
Ora aqui está um programa que serve para mostrar que todos os comandos acima também se aplicam aos ciclos while. Se experimentar este programa, vai ver que só consegue sair se escrever uma de duas frases: 'por favor' ou 'deixa-me!'. Se não escrever nada, ele usa o continue e pede logo para escrever de novo. Se escrever 'deixa-me!' consegue sair pelo break, e se escrever 'por favor', sai do ciclo através do else. Simples, não é? Mas repito, cuidado com ciclos infinitos!