Funções com parâmetros "defaults" para objetos mutáveis .
In [1]: def funcao(x, lista=[]):
...: lista.append(x)
...: return lista
...:
In [2]: print funcao('a')
------> print(funcao('a'))
['a']
In [3]: print funcao('b')
------> print(funcao('b'))
['a', 'b']
In [4]: print funcao('c')
------> print(funcao('c'))
['a', 'b', 'c']
In [5]: print funcao('d')
------> print(funcao('d'))
['a', 'b', 'c', 'd']
sendo que o esperado seria
print funcao('d')
>>['d']
print funcao('e')
>>['e']
como acontece abaixo
In [27]: def funcao(a=0):
....: return a
....:
In [28]: funcao(1)
Out[28]: 1
In [29]: funcao(2)
Out[29]: 2
In [30]: funcao()
Out[30]: 0
....: return a
....:
In [28]: funcao(1)
Out[28]: 1
In [29]: funcao(2)
Out[29]: 2
In [30]: funcao()
Out[30]: 0
O problema é que o "default value" é assinalado uma única vez, e não é quando a função é chamada, mas sim, quando é definida.
Problema parecido acontece quando o default value é um método....
In [66]: def funcao(tempo=time.time()):
....: print tempo
....:
....:
In [67]: funcao
Out[67]: <function funcao at 0x95f9534>
In [68]: funcao()
1254349399.98
In [69]: funcao()
1254349399.98
In [70]: funcao()
1254349399.98
In [71]: funcao()
1254349399.98
caso seja para sempre retornar o valor atualizado, devemos passar a referência à função
In [73]: def funcao(tempo=time.time):
....: print tempo()
....:
In [74]: funcao
Out[74]: <function funcao at 0x95f933c>
In [75]: funcao()
1254349428.79
In [76]: funcao()
1254349429.94
In [77]: funcao()
1254349431.35
....: print tempo
....:
....:
In [67]: funcao
Out[67]: <function funcao at 0x95f9534>
In [68]: funcao()
1254349399.98
In [69]: funcao()
1254349399.98
In [70]: funcao()
1254349399.98
In [71]: funcao()
1254349399.98
caso seja para sempre retornar o valor atualizado, devemos passar a referência à função
In [73]: def funcao(tempo=time.time):
....: print tempo()
....:
In [74]: funcao
Out[74]: <function funcao at 0x95f933c>
In [75]: funcao()
1254349428.79
In [76]: funcao()
1254349429.94
In [77]: funcao()
1254349431.35
Os cometários que explicam este comportamento:
"The default value is evaluated only once. This makes a difference when the default is a mutable object such as a list, dictionary, or instances of most classes. For example, the following function accumulates the arguments passed to it on subsequent calls: "
ou
Mas se isso é verdade, se o porque do "acúmulo" da varável é porque os valores defaults bem como variáveis e ou métodos de uma classe são "atribuidos" uma única vez quando a função é interpretada, então porque quando definimos def " funcao(x=0): " o problema nao occore não ocorre?
In [81]: def funcao(x=0):
....: x = x+1
....: return x
....:
In [82]: funcao(2)
Out[82]: 3
In [83]: funcao(2)
Out[83]: 3
In [84]: funcao(2)
Out[84]: 3
....: x = x+1
....: return x
....:
In [82]: funcao(2)
Out[82]: 3
In [83]: funcao(2)
Out[83]: 3
In [84]: funcao(2)
Out[84]: 3
Não está faltando nada no porque ?
se o valor default da var x, é assinlado somente uma única vez quando a função foi criada, porque ao alterar o valor de x dentro da minha função, também não ocorre o acúmulo? ou porque x não permanece com o último valor como acontece quando passado um método ou uma lista ?
pensando em ponteiros e memória, não consigo imaginar porque o comportamento diferente de uma var ou um metodo ou lista.
pensando em ponteiros e memória, não consigo imaginar porque o comportamento diferente de uma var ou um metodo ou lista.
Nenhum comentário:
Postar um comentário