No ruby eu consigo entender o porque. É um comportamento esperado já que o escopo do parametro "z" refere-se somente ao ciclo de vida dentro do método. A variável é criada à entrada do método e é destruída após o término da execução dele. Já o comportamento no python eu ainda não sei a explicação.
Por fim, se quiserem entender melhor, aconselho a leitura do python pitfalls, que ensina tudo o que não se deve fazer em python. Ou se for fazer, que use com consciencia.
Esquisito, pq em ruby listas e hashes também são mutáveis. No caso do exemplo que você deu eu até entendo, mas no caso da declaração do parâmetro só funcionar uma vez e depois ele assumir que é a declaração da primeira chamada é que funcionou é que eu não entendo. Lerei o artigo.
Isso acontece porque parâmetros default de funções só são atribuídos uma única vez, no momento que a instrução def é interpretada (quando o objeto function é criado)
Então sempre que você chamar essa função, ela vai usar o mesmo valor atribuído a x (caso você não passe outro na chamada).
Veja que ao chamar nada(), a identificação dos objetos não muda, são os mesmos. Você mudou o conteúdo da lista, porque ela é mutável, mas a lista em si é o mesmo objeto, assim como o inteiro também é o mesmo objeto, mas o inteiro você não pode mudar, qualquer operação que fizer com um inteiro vai te retornar outro (somar com outro, subtrair, etc).
Em Python os objetos são realmente como já disseram acima, ponteiros (como os de C).
O negócio é que Python REAPROVEITA alguns ponteiros. Se você atribuir duas strings iguais a duas variáveis diferentes e verificar com a função id, elas apontam para o mesmo endereço.
Agora se você fizer isso com Ruby, chamando a função __id__ de dois objetos com a mesma string, terá valores de retorno diferentes.
Ao executar pela primeira vez ele cria a referência para W. Na segunda vez que o método é chamado, W já está criado (por algum motivo o garbage collector talvez não tenha feito seu trabalho) e ele aproveita a referência.
olá
ResponderExcluirem ruby eu já sabia o comportamento, agora em python.. que loucura!! mas pode ser util em algumas situações
grande abraço
Bruno
Você poderia explicar pq acontece isso nas duas?
ResponderExcluirNo ruby eu consigo entender o porque. É um comportamento esperado já que o escopo do parametro "z" refere-se somente ao ciclo de vida dentro do método. A variável é criada à entrada do método e é destruída após o término da execução dele. Já o comportamento no python eu ainda não sei a explicação.
ResponderExcluirEsperava mesmo a explicação para o python
ResponderExcluirem ruby eu tinha entendido
É o seguinte.
ResponderExcluirEm python, tanto listas como dicionários são mutáveis, e por isso, funcionam como os ponteiros de C.
Por isso, é uma má prática usar listas ou dicionários vazios como valor padrão de métodos em python.
Outro exemplo:
dic1 = {}
def alterar(nome, valor, w):
w[nome] = valor
alterar("campo1", "valor1", dic1)
alterar("campo2", "valor2", dic1)
alterar("campo3", "valor3", dic1)
print dic1
{'campo1': 'valor1', 'campo2': 'valor2', 'campo3': 'valor3'}
Por fim, se quiserem entender melhor, aconselho a leitura do python pitfalls, que ensina tudo o que não se deve fazer em python. Ou se for fazer, que use com consciencia.
http://zephyrfalcon.org/labs/python_pitfalls.html
Abração!
Esquisito, pq em ruby listas e hashes também são mutáveis. No caso do exemplo que você deu eu até entendo, mas no caso da declaração do parâmetro só funcionar uma vez e depois ele assumir que é a declaração da primeira chamada é que funcionou é que eu não entendo. Lerei o artigo.
ResponderExcluirIsso acontece porque parâmetros default de funções só são atribuídos uma única vez, no momento que a instrução def é interpretada (quando o objeto function é criado)
ResponderExcluirEntão sempre que você chamar essa função, ela vai usar o mesmo valor atribuído a x (caso você não passe outro na chamada).
Veja esse outro exemplo:
>>> def nada(x=[], y=0):
... x.append(2)
... return x, y
...
Você pode acessar os atributos default:
>>> nada.__defaults__
([], 0)
>>> id(nada.__defaults__[0])
911760
>>> id(nada.__defaults__[1])
8427924
>>> nada()
([2], 0)
>>> id(nada.__defaults__[0])
911760
>>> id(nada.__defaults__[1])
8427924
Veja que ao chamar nada(), a identificação dos objetos não muda, são os mesmos. Você mudou o conteúdo da lista, porque ela é mutável, mas a lista em si é o mesmo objeto, assim como o inteiro também é o mesmo objeto, mas o inteiro você não pode mudar, qualquer operação que fizer com um inteiro vai te retornar outro (somar com outro, subtrair, etc).
Parece que em Python as variaveis locais tem escopo de classe '-',que loucura.
ResponderExcluirEm Python os objetos são realmente como já disseram acima, ponteiros (como os de C).
ResponderExcluirO negócio é que Python REAPROVEITA alguns ponteiros. Se você atribuir duas strings iguais a duas variáveis diferentes e verificar com a função id, elas apontam para o mesmo endereço.
Agora se você fizer isso com Ruby, chamando a função __id__ de dois objetos com a mesma string, terá valores de retorno diferentes.
Ao executar pela primeira vez ele cria a referência para W. Na segunda vez que o método é chamado, W já está criado (por algum motivo o garbage collector talvez não tenha feito seu trabalho) e ele aproveita a referência.
Acho que é isso.
(:
Complicado... Só entendi porque acontece isso em Python... porque listas são mutáveis... Sei nada de Ruby. Mas boa dica ;)
ResponderExcluir