Exercício 02: Introduçao aos conceitos e Ferramentas

1. Python

  • Tipos

Python é uma linguagem dinamicamene tipada, que não precisa de declaração prévia de variáveis.

Ela oferece suporte aos tipos numéricos básicos:
  • Inteiro (int)
  • Booleanos (bool)
  • Ponto Flutuante (float)
  • Complexo (complex)
 1 # Tipos numéricos
 2 print "Tipos Numéricos\n"
 3 
 4 a = 5     # variavel do tipo int
 5 b = 1.5   # variavel do tipo float
 6 print "a = "+ str(a) + "   b = " + str(b)
 7 
 8 a = a/b   # operandos diferentes resultaram na conversão de tipo de int para float
 9 print "Depois da operação a/b, a = " + str(a) +"\n"
10 
11 d = (2 + 3j)    # uma das formas de instanciar uma variavel complexa
12 e = complex(2, 3)    # outra forma de instanciar uma variavel complexa
13 print "d = " + str(d) + ", e = "+ str(e) + ". Logo, d=e é "+ str(d==e)
14 print "Parte real de 'd': " + str(d.real)
15 print "Parte imaginária de 'd': " +str(d.imag)
Tipos Numéricos

a = 5   b = 1.5
Depois da operação a/b, a = 3.33333333333

d = (2+3j), e = (2+3j). Logo, d=e é True
Parte real de 'd': 2.0
Parte imaginária de 'd': 3.0

Python também possui suporte a tipos de alto nível pré-determinados, sendo eles: string, tupla, lista, dicionário, arquivo e classe.

Abaixo, é descrito cada um desses tipos de alto nível separadamente

  • String

    É uma sequência imutável de caracteres que não possui um limite de tamanho. Ela é delimitada com o uso de aspas simples, duplas ou triplas. E é possível acessar partes de uma string, uma vez que elas são indexáveis.

    No código abaixo, é feita uma tentativa de modificação da string. Mas, como esse tipo é imutável, será gerado uma exceção.

 1 # Tipo de alto nivel: String
 2 print "Tipo de alto nivel: String \n"
 3 aux = "Fernanda"
 4 print "String inicial: "+ aux + "\n"
 5 print '''aux[7]='''+aux[7] + ''' aux[-1]='''+aux[-1]    # string é um tipo indexavel em dois sentidos
 6 print "aux[3:8] = " + aux[3:8]   # é possivel acessar parte de uma string
 7 
 8 print "\nTentativa de modificação da string: "     # string é imutável
 9 try:
10     aux[7] = 'o'
11 except:
12     print "Erro: String é imutável"
13     print sys.exc_info()[0]
14     print ""
15 
16 print "String final: " + aux
Tipo de alto nivel: String 

String inicial: Fernanda

aux[7]=a aux[-1]=a
aux[3:8] = nanda

Tentativa de modificação da string: 
Erro: String é imutável
<type 'exceptions.TypeError'>

String final: Fernanda
  • Lista

    É uma sequência de valores, se assemelhando a estrutura de vetor em outras linguagens de programação.

    Essa sequência pode conter valores de todos os tipos suportados pelo Python, inclusive uma outra lista. E uma mesma lista pode conter itens com tipos diferentes entre eles. A lista é indexável, sendo assim, cada item dela pode ser acessado pelo seu índice.

    Essa estrutura é definida com o uso de colchetes

1 a = ["banana", "laranja", 2, 18]    # lista com elementos de tipos diferentes
2 print "Lista inicial: " + str(a) +"\n"
3 print "a[0] = " + a[0]
4 a[0] = "melancia"
5 print "novo valor de a[0] = " + a[0]
6 print "Depois de modificação de um elemento, a nova lista gerada é " + str(a)
7 
8 print "\nIntervalo de elementos da lista: a[2:4] = " + str(a[2:4])
Lista inicial: ['banana', 'laranja', 2, 18]

a[0] = banana
novo valor de a[0] = melancia
Depois de modificação de um elemento, a nova lista gerada é ['melancia', 'laranja', 2, 18]

Intervalo de elementos da lista: a[2:4] = [2, 18]
  • Tupla

    É uma sequência de valores, como a do tipo 'Lista' descrito acima. A diferença entre esses dois tipos é que a tupla não pode ser modificada, depois de definida. A tupla, diferentemente da lista, é definida com o uso de parênteses

    No código abaixo, é feita uma tentativa de modificação da tupla. Mas, como esse tipo é imutável, será gerado uma exceção.

 1 a = ("banana", "laranja", 2, 4)    # tupla com elementos de tipos diferentes
 2 print "Tupla inicial: "+ str(a) + "\n"
 3 print "a[0] = " + a[0]
 4 print "\nTentativa de modificação da tupla"
 5 try:
 6     a[0] = "melancia"                     # tentativa de modificação da tupla
 7 except:
 8     print "Erro: Tupla é imutável"
 9     print sys.exc_info()[0]
10     print ""
11 
12 print "Valor final de a[0] = " + a[0]
13 print "Tupla final é " + str(a)
Tupla inicial: ('banana', 'laranja', 2, 4)

a[0] = banana

Tentativa de modificação da tupla
Erro: Tupla é imutável
<type 'exceptions.TypeError'>

Valor final de a[0] = banana
Tupla final é ('banana', 'laranja', 2, 4)
  • Dicionário

    É uma sequência que pode ser indexada por valores arbitrários de algum tipo imutável (string, tupla, número). O dicionário é definido usando chaves( { } ) como caracter delimitador

    No código abaixo, é feita uma tentativa de indexação com lista (tipo mutável). Mas, como só pode ser usado tipos imutáveis, será gerado uma exceção.

 1 a = {"fruta":"banana", ("azul", "branca"):"cor", 5:[1,2,3,4,5]}    # tupla com elementos de tipos diferentes
 2 print "Dicionário inicial : " + str(a)
 3 print "\nChaves: " + str(a.keys())
 4 print "\nValores: " + str(a.values()) +"\n"
 5 
 6 print "a['fruta'] = " + str(a["fruta"]) + "\n"
 7 a['fruta'] = ("laranja", "banana")
 8 print "Novo valor de a['fruta'] = " + str(a["fruta"]) + "\n"
 9 print "Dicionário final: "
10 print a
11 
12 try:
13     a = {"fruta":"banana", ["azul", "branca"]:"cor", "range_5":[1,2,3,4,5]}
14 except:
15     print "\nERRO: Tentativa de uso de tipo mutável(lista), como chave do dicionário"
16     print sys.exc_info()[0]
Dicionário inicial : {('azul', 'branca'): 'cor', 'fruta': 'banana', 5: [1, 2, 3, 4, 5]}

Chaves: [('azul', 'branca'), 'fruta', 5]

Valores: ['cor', 'banana', [1, 2, 3, 4, 5]]

a['fruta'] = banana

Novo valor de a['fruta'] = ('laranja', 'banana')

Dicionário final: 
{('azul', 'branca'): 'cor', 'fruta': ('laranja', 'banana'), 5: [1, 2, 3, 4, 5]}

ERRO: Tentativa de uso de tipo mutável(lista), como chave do dicionário
<type 'exceptions.TypeError'>
  • Classe

    Python é uma linguagem orientada a objeto. Classe é a estrutura para a criação de uma nova instância de um objeto concreto. Uma classe possui atributos e métodos, sendo um dos métodos denominado método construtor (__init__). O método construtor é opcional, e é invocado no momento da instanciação de um objeto da classe.

    Todo método possui, necessariamente, um primeiro argumento denominado self, que referencia o próprio objeto.

 1 class Conta:
 2 
 3     numero = None
 4     agencia = None
 5     proprietario = None
 6     dependente = None
 7 
 8     def __init__(self, prop, num, ag):
 9         self.numero = num
10         self.proprietario = prop
11         self.agencia = ag
12         self.dependente = []
13 
14     def verAgencia(self):
15         return self.agencia
16 
17     def verNumero(self):
18         return self.numero
19 
20     def verificaProprietario(self, nome):
21         if(nome==self.proprietario):
22             return True
23         else:
24             return False
25 
26     def incluiDependente(self, nome):
27         self.dependente.append(nome)
28 
29     def verDependente(self):
30         return self.dependente
31 
32 
33 n_conta = Conta("Maria", 333, 33)
34 usuario = "Maria"
35 print "Com usuário Maria, insere-se dois novos dependentes: Francisco e Marcela \n"
36 if(n_conta.verificaProprietario(usuario)):
37     n_conta.incluiDependente("Francisco")
38     n_conta.incluiDependente("Marcela")
39 
40 print "Conta Número " + str(n_conta.verNumero()) + ", Agência " + str(n_conta.verAgencia())
41 print "Dependentes: "+ str(n_conta.verDependente())
Com usuário Maria, insere-se dois novos dependentes: Francisco e Marcela 

Conta Número 333, Agência 33
Dependentes: ['Francisco', 'Marcela']
  • Importância da Indentação

    Em Python, o controle de blocos é feito pela indentação, e não por par de caracteres (ex: { }) ou par palavras-chave (ex: BEGIN, END)

    Sendo assim, os dois trechos de código apresentados abaixo são diferentes: O código 1, tem como resultado a = b. Enquanto que no fim da execução do código 2, a != b

 1 # Código 1: Nesse trecho, as variáveis 'a' e 'b' são acrescidas de 1, enquanto 'a' é menor que 10
 2 a = b = 0
 3 while(a<10):
 4     a+=1
 5     b+=1
 6 print "Codigo 1: a = " + str(a) + ", b = " + str(b) + ". Logo, a=b é " + str(a==b)
 7 
 8 # Código 2: Nesse trecho, a variável 'a' é acrescida de 1, enquanto ela é menor que 10. E a variável 'b' é acrescida de 1, quando a=10
 9 a = b = 0
10 while(a<10):
11     a+=1
12 b+=1            # instrução fora do loop, pois não está indentada
13 print "Codigo 2: a = " + str(a) + ", b = " + str(b) + ". Logo, a=b é " + str(a==b)
Codigo 1: a = 10, b = 10. Logo, a=b é True
Codigo 2: a = 10, b = 1. Logo, a=b é False

2. NumPy

O NumPy oferece um tipo a mais ao Python: o vetor multidimensional, que é uma matriz. Esse tipo é um vetor de elementos de um mesmo tipo, cujo índice é definido por uma tupla de inteiros positivos.
 1 a = arange(20).reshape(5,4)
 2 print "A = " + str(a)
 3 print "\nValor máximo de A: " + str(a.max())
 4 print "Valor mínimo de A: " + str(a.min())
 5 print "Soma dos elementos de A: " + str(a.sum())
 6 print "Soma acumulativa dos elementos ao longo de cada linha:\n" + str(a.cumsum(1))
 7 print "Soma acumulativa dos elementos ao longo de cada coluna:\n" + str(a.cumsum(0))
 8 
 9 b = 2*ones((5,4))
10 print "\nB = " + str(b)
11 c = arange(20,0,-1)
12 print "\nC = " + str(c)
13 c = c.reshape(4,5)
14 print "\nC = " + str(c)
15 print "\nMatriz Identidade\n" + str(eye(4))
16 
17 print "\nMultiplicação de matriz por escalar: \nB*5 = " + str(b*5)
18 print "\nSoma de matrizes: \nA+B = " + str(a+b)
19 print "\nProduto das matrizes A e B, elemento por elemento \n" + str(a*b)
20 print "\nProduto das matrizes A e C: \n" + str(dot(a,c))
21 print "\nTransposta de A: \n" + str(a.transpose())
22 
23 d = hstack((a, b))
24 print "\nMatrizes A e B concatenadas horizontalmente\n" + str(d)
25 d = vstack((a, b))
26 print "\nMatrizes A e B concatenadas verticalmente\n" + str(d)
A = [[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]
 [16 17 18 19]]

Valor máximo de A: 19
Valor mínimo de A: 0
Soma dos elementos de A: 190
Soma acumulativa dos elementos ao longo de cada linha:
[[ 0  1  3  6]
 [ 4  9 15 22]
 [ 8 17 27 38]
 [12 25 39 54]
 [16 33 51 70]]
Soma acumulativa dos elementos ao longo de cada coluna:
[[ 0  1  2  3]
 [ 4  6  8 10]
 [12 15 18 21]
 [24 28 32 36]
 [40 45 50 55]]

B = [[ 2.  2.  2.  2.]
 [ 2.  2.  2.  2.]
 [ 2.  2.  2.  2.]
 [ 2.  2.  2.  2.]
 [ 2.  2.  2.  2.]]

C = [20 19 18 17 16 15 14 13 12 11 10  9  8  7  6  5  4  3  2  1]

C = [[20 19 18 17 16]
 [15 14 13 12 11]
 [10  9  8  7  6]
 [ 5  4  3  2  1]]

Matriz Identidade
[[ 1.  0.  0.  0.]
 [ 0.  1.  0.  0.]
 [ 0.  0.  1.  0.]
 [ 0.  0.  0.  1.]]

Multiplicação de matriz por escalar: 
B*5 = [[ 10.  10.  10.  10.]
 [ 10.  10.  10.  10.]
 [ 10.  10.  10.  10.]
 [ 10.  10.  10.  10.]
 [ 10.  10.  10.  10.]]

Soma de matrizes: 
A+B = [[  2.   3.   4.   5.]
 [  6.   7.   8.   9.]
 [ 10.  11.  12.  13.]
 [ 14.  15.  16.  17.]
 [ 18.  19.  20.  21.]]

Produto das matrizes A e B, elemento por elemento 
[[  0.   2.   4.   6.]
 [  8.  10.  12.  14.]
 [ 16.  18.  20.  22.]
 [ 24.  26.  28.  30.]
 [ 32.  34.  36.  38.]]

Produto das matrizes A e C: 
[[ 50  44  38  32  26]
 [250 228 206 184 162]
 [450 412 374 336 298]
 [650 596 542 488 434]
 [850 780 710 640 570]]

Transposta de A: 
[[ 0  4  8 12 16]
 [ 1  5  9 13 17]
 [ 2  6 10 14 18]
 [ 3  7 11 15 19]]

Matrizes A e B concatenadas horizontalmente
[[  0.   1.   2.   3.   2.   2.   2.   2.]
 [  4.   5.   6.   7.   2.   2.   2.   2.]
 [  8.   9.  10.  11.   2.   2.   2.   2.]
 [ 12.  13.  14.  15.   2.   2.   2.   2.]
 [ 16.  17.  18.  19.   2.   2.   2.   2.]]

Matrizes A e B concatenadas verticalmente
[[  0.   1.   2.   3.]
 [  4.   5.   6.   7.]
 [  8.   9.  10.  11.]
 [ 12.  13.  14.  15.]
 [ 16.  17.  18.  19.]
 [  2.   2.   2.   2.]
 [  2.   2.   2.   2.]
 [  2.   2.   2.   2.]
 [  2.   2.   2.   2.]
 [  2.   2.   2.   2.]]

2. Graphviz: ferramenta de visualizaçao

Usando Graphviz, é possível definir um grafo com nós e arestas entre eles. Cada nó ou aresta pode ter características próprias, como forma, cor, estilo... Sendo também possível definir grupos de nós com propriedades em comum (cluster)

  • Código Graphviz

    No código abaixo, são criados 2 clusters com auxílio do Graphviz.

    O Cluster B - Arvore 1, representa uma árvore não balanceada. Dessa forma, foram definidos 5 nós com mesmo estilo, porém formas e labels diferentes e 4 arestas. Essa árvore, está numa região delimitada, colorida com verde.

    O Cluster A - Arvore 2, representa uma árvore balanceada. Dessa forma, foram definidos 7 nós com mesmo estilo, porém labels diferentes e 6 arestas, todas com um estilo pontilhado. Essa árvore, está numa região delimitada pela cor azul.

/media/_xsb/courseIA368Q1S2012/fer_ex02/GRVIZ62348_001.png

  • Criação de grafos utilizando Python

    A construção de grafos com Python é possível de 2 formas:

  • através da chamada de uma função que retorna uma imagem

    No código abaixo, é criado 2 clusters: A e B.

    No cluster A, cada nó possui nós internos, que podem ser ligados a outros nós. Além das definições comuns de estilo e forma para os nós, foram definidas arestas entre nós internos.

    No cluster B, foram feitas definições comuns de estilo a todo o cluster. Os nós são comuns, representando apenas um elemento, e as arestas foram definidas de duas formas: com apenas um sentido; ou com dois sentidos, tendo cada um deles uma cor.

    Por esse exemplo, observa-se também a possibilidade de definir arestas entre clusters, usando as propriedades ltail e lhead.

ERROR execute

------------------------------------------------------------
*** Exception while evaluating code:
  File "<string>", line 36, in <module>
  File "xs_runner_python.py", line 384, in mmgraphviz
    runner = config.xs_runner.theRunner.graphviz
AttributeError: 'module' object has no attribute 'xs_runner'

------------------------------------------------------------

  • com a utilização da extensão Python gvgen

    Nesse exemplo, foi criado um grafo orientado, onde cada aresta recebe um peso. A cor e o peso das arestas foram definidos de 2 formas: ou individualmente, para um aresta específica; ou para o grupo de arestas ligadas a um nó específico.

    Com a propriedade graph.smart_mode habilitada, criou-se uma aresta em duplo sentido entre os nós A e B,uma vez que foram definidas duas arestas com sentidos opostos entre esses nós.

ERROR execute

------------------------------------------------------------
*** Exception while evaluating code:
  File "<string>", line 41, in <module>
  File "xs_runner_python.py", line 384, in mmgraphviz
    runner = config.xs_runner.theRunner.graphviz
AttributeError: 'module' object has no attribute 'xs_runner'

------------------------------------------------------------