domingo, 2 de junho de 2013

Funções em Python - Variáveis por referência ou valor?

Olá pessoal, hoje vamos aprender um pouco mais de Python e entender como essa linguagem trabalha com variáveis em chamadas de funções.

Quando estamos escrevendo um programa estruturado certamente iremos construir algumas funções para solucionar algum problema. Em muitas linguagens de programação temos a opção de passar valores por refência ou por valor.

Quando passamos valores por referência estamos na verdade passando o endereço de memória onde a variável original aponta, então quem recebe esse endereço tem o que chamamos de acesso direto e toda alteração feita localmente reflete a variável original uma vez que o endereço apontado pela variável local é o mesmo da original.

Quando passamos por valor a variável local recebe uma "cópia" do valor que a variável original armazena, e toda a mudança que a variável local recebe NÃO é refletida na variável original pois a variável local é apenas uma cópia de seu valor.

Em Python não fazemos essa divisão em valor ou referencia. Em Python tudo é objeto, e quando eu digo tudo é tudo mesmo: 1, 10, 45, 543,  *lista, *tuplas, *dicionários, etc.

Então como fazer essa divisão em Python? Ora, muito simples. Dizemos que temos objetos que são mutáveis e objetos que são imutáveis. Objetos mutáveis como o próprio nome diz são objetos que podem mudar no decorrer da interpretação do código e objetos imutáveis são aqueles que não mudam no decorrer do código. Exemplo de objetos imutáveis: 1, 20, 123. O objeto 1 quando iniciamos o programa é 1 e no final dele continua sendo 1.

Agora objetos que são mutáveis temos: *listas, *dicionário, etc. Uma lista pode começar fazia, e no final da interpretação terminar com 10 elementos.

* Estruturas de dados da linguagem Python.

Persistir mudanças em variáveis externas

E agora vem a pergunta: Como fazer uma variável externa recuperar o valor que foi dado à ela dentro de uma função?.

A primeira coisa a ver nesse caso é se a variável a ser passada é mutável ou imutável. Caso ela seja mutável não é preciso fazer nada, toda a mudança que ela receber na função vai ser refletida a variável original .
def adicionarItem(item, lista): lista.append(item) lista = list() adicionarItem(5, lista) adicionarItem(10, lista) print(lista)
Veja que criamos uma lista, onde valores são inseridos e ao final exibimos e comprovamos que os valores foram inseridos na lista. Agora se a variável for imutável devemos retornar o valor calculado dentro da função para a variável externa, fazendo com que ela receba esse valor. Exemplo:
def incrementar(a): a += 1 return a a = 5 a = incrementar(a) print(a)
Temos uma função cujo o seu propósito é incrementar um ao valor original da variável passada. Criamos uma variável com o valor 5 e logo em seguida estamos chamando a função e atribuindo o valor de retorno a nossa variável. Ao final estamos imprimindo o valor calculado pela nossa função. Nesse caso nada de errado aconteceu e o valor 6 foi mostrado como já era previsto. Mas e se não tivéssemos atribuído esse retorno a variável, será que o resultado seria o mesmo? Vamos testar:
def incrementar(a): a += 1 return a a = 5 incrementar(a) print(a)
Opa agora o resultado que foi mostrado na tela foi o número 5 :s!!! Isso não era para estar acontecendo! Na verdade era, em Python temos uma tabela de objetos onde cada objeto tem um ID. Então quando criamos uma variável ela é uma etiqueta para esse ID que por sua vez faz uma referencia a memória. Então quando a variável é criada ela está etiquetando o ID do Objeto 5, é criada uma outra variável só que localmente e essa aponta para ID 6. Como a variável local não é retornada ela morre ou melhor deixa de existir assim que a função acaba de ser interpretada. Bom pessoal por hoje é só espero que tenham gostado. Bons estudos!!!

Estruturas em C - struct (só o básico)

Olá pessoal, hoje vamos falar de struct (Estruturas). As estruturas existem em linguagem C para agrupar dados de diferentes tipos. Podemos definir estruturas como tipo de dados  que armazenam dados de tipos desiguais.

Nota: Podemos imaginar estruturas como sendo matrizes, porém, ela seria uma matriz turbinada que pode armazenar mais de um tipo de dado.

Criando uma estrutura

Para criar uma estrutura usamos a palavra-chave struct. Quando fazemos isso estamos definindo para o compilador um novo tipo de dado. Exemplo:

struct Relogio { int horas; int minutos; int segundos; };
A definição de uma estrutura não cria nenhuma variável, somente informa ao compilador as características de um novo tipo de dado. A palavra struct indica que um novo tipo de dados está sendo definido e Relogio será a sua entiqueta.

Outra coisa importante a dizer é que nesse exemplo definimos a struct como sendo global, ou seja, ela está acessível em qualquer parte do código. Podemos definir nossa struct dentro de uma função, com isso ela só poderá ser utilizada dentro dessa função pois seu escopo será local e não mais global. Exemplo:

#include <stdio.h>  int main(void) { struct Relogio { int horas; int minutos; int segundos; }; struct Relogio r; printf("\n O ponteiro hora está parado em qual número? \n >>> "); scanf("%d", &r.horas); printf("\n O ponteiro minuto está parado em qual número? \n >>> "); scanf("%d", &r.minutos); printf("\n O ponteiro de segundo está parado em qual número? \n >>> "); scanf("%d", &r.segundos); /* Não estou considerando se a hora é inválida! */ printf("\n Hora lida \n >>> %d:%d:%d", r.horas, r.minutos, r.segundos); return 0; }
No exemplo acima Relogio só pode ser acessado dentro da função principal (main). Por fim dessa introdução ao assunto gostaria de deixar uma definição sobre estruturas:
Uma estrutura é um tipo de dado cujo formato é definido pelo programador.

typedef + struct

Em C temos um recurso para dar novos nomes a tipos de dados que já existem (typedef). Com ele podemos então nomear as nossas estruturas. Podemos utilizar ele de 3 distintas formas, porém, para ser mas breve o possível vou adotar apenas uma forma e levar até o fim desse post.

typedef struct { int horas; int minutos; int segundos; } Relogio; Relogio rolex; /*Declara uma variavel do tipo Relogio*/
Para acessar os membros contidos em nossa struct utilizamos o operador "." (ponto final).
rolex.horas = 1;
Para acessar os membros de uma struct devemos utilizar o operador ponto. Esse operador conecta o nome de uma variável estrutura ao membro dela.

Estruturas aninhadas

Podemos ter uma estrutura que contém outra estrutura. Quando isso ocorre damos o nome de estruturas aninhadas. Para criar uma estrutura aninhada devemos criar todas as estruturas que agregam/compõem outras estruturas afim de suprir essa hierarquia montada:

typedef struct { int notas[3]; } Boletim; typedef struct { char nome[30]; Boletim boletim; } Aluno;
No exemplo acima temos duas estruturas: Boletim e Aluno. A estrutura Boletim possui apenas um membro já a estrutura Aluno possui dois membros, inclusive um de seus membros é do tipo Boletim. Então devido essa dependência devemos definir primeiramente Boletim e depois Aluno.
Para utilizar estruturas contidas em outras estruturas a ideia é a mesma. Devemos acessar os níveis hierárquicos utilizando o operador ponto e depois fazer a atribuição do valor, ou recuperar o mesmo. Exemplo:

typedef struct { int notas[3]; } Boletim; typedef struct { char nome[30]; Boletim boletim; } Aluno; Aluno Guilherme; int main(void) { Guilherme.boletim.notas[i]=10; return 0; }
Pessoal escrevi só o basicão, caso você goste e se interessou pelo assunto deixe seu comentário pedindo uma segunda parte mais avançada que eu farei ... lembre-se só farei se a demanda for alta por isso ajude ai compartilhando. Bons estudos!

Novidade!!! Agora vamos ter canal no Youtube =D

Fala pessoal tudo beleza, estou sumido a correria está forte por aqui. Estou querendo dar um start em um projeto antigo que vem desde o temp...