O vencimento bruto de um trabalhador está sujeito a descontos: 25% para o IRS, 5% para a Segurança social e 10% para a Caixa Nacional de Aposentações. O vencimento líquido é o que resulta da subtracção destes descontos ao vencimento bruto. Desenvolva um programa que dado o vencimento bruto devolve o correspondente vencimento líquido.
Eis algumas das soluções que me apresentaram.
Exemplo 1
01.
Def. vencimento(vbruto).
02.
virs
=
(vbruto)
*
0
,
25
03.
vss
=
(vbruto)
*
0
,
05
04.
vcna
=
(vbruto)
*
0
,
1
05.
vliquido
=
(virs)
+
(vss)
+
(vcna)
06.
return
vliquido
07.
08.
if
‘__main__’
=
=
__name__:
09.
print
vencimento()
Exemplo 2
01.
def
venc_liquido(n):
02.
total
=
0
03.
irs
=
(n
*
25
)
/
100
04.
sc
=
(n
*
5
)
/
100
05.
cna
=
(n
*
10
)
/
100
06.
total
=
n
-
(irs
+
sc
+
cna)
07.
return
total
08.
09.
if
__name__
=
=
‘__main__’:
10.
print
venc_liquido()
Exemplo 3
1.
def
vencimento(bruto):
2.
liquido
=
bruto
-
(bruto
*
0.25
+
bruto
*
0.05
+
bruto
*
0.1
)
3.
return
liquido
4.
5.
if
__name__
=
=
‘__main__’:
6.
print
vencimento(bruto)
O que todas estas soluções têm em comum é ... terem problemas. Há erros de sintaxe, há erros de lógica e há erros conceptuais graves. O primeiro exemplo é o pior de todos. Ttodos aqueles parênteses à volta dos nomes são desnecessários (interrogo-me se não os colocou levado pelo facto de quando se define a função termos que usar parênteses.). Nos números em vírgula flutuante usa a vírgula e não o ponto como separador entre a parte inteira e a parte fraccionária. Tem um erro de lógica: não subtrai ao vencimento bruto os descontos. No segundo exemplo, a lógica está correcta, só não se entendendo o porquê da inicialização de total a zero. Não é necessário. O terceiro exemplo, é o que está mais limpo. Nada a dizer sobre o modo como a definição é construída. Mas todos têm um erro conceptual grave, e isso manifesta-se no modo como usam a função que definiram, isto é, o que colocam depois do if. Nos dois primeiros casos a função é chamada sem argumento, enquanto que no terceiro caso a função é chamada tendo como argumento um nome que não está associado a nenhum objecto. O primeiro caso tem paralelo na situação de eu carregar numa tecla de função da minha calculadora, por exemplo sin, e não fazer mais nada ficando à espera que a máquina calcule qualquer coisa (embora não se saiba o quê).
Vamos ver se nos entendemos. Os problemas resolvem-se escrevendo programas. O programa é feito de definições e estas, para serem úteis, têm que ser usadas. Usar uma definição traduz-se por chamar a definição, indicando na altura da chamada quais os argumentos concretos a usar. Os argumentos das definições chamam-se parâmetros formais, e têm que ser nomes; os argumentos que usamos nas chamadas chamam-se parâmetros reais e têm que traduzir, directa ou indirectamente um objecto. Directamente se usamos o valor do objecto, indirectamente se usamos ou umaexpressão que quando calculada dá como resultado um objecto, ou um nome que está associado a um objecto. Os parâmetros formais, os que usamos nas definições, podem ter um nome qualquer, são mudos. Por exemplo, as duas definições abaixo definem exactamente a mesma coisa.
1.
def
dobro(n):
# <-- n parâmetro formal
2.
return
2
*
n
3.
4.
def
dobro(x):
# <-- x parâmetro formal
5.
return
2
*
x
Usar n ou x como parâmetro formal é irrelevante. Vejamos agora com um exemplo a questão da definição e da chamada.
01.
>>>
def
dobro(n):
# <-- x parâmetro formal
02.
...
return
2
*
n
03.
...
04.
>>> dobro(
5
)
# <-- 5 parâmetro real
05.
10
06.
>>> a
=
3
07.
>>> dobro(a)
# <-- a parâmetro real
08.
6
09.
>>> dobro(a
*
3
+
5
)
# <-- a*3+5 parâmetro real
10.
28
11.
>>>
No primeiro caso, chamamos com um objecto (5), no segundo, com o nome (a) associado a um objecto (3), no terceiro com uma expressão associada a um objecto de valor 14.
O que é que acontece se chamamos, ou sem argumento ou usando como argumento real um nome que não está associado a nenhum objecto? Um erro, claro:
01.
>>> dobro()
# <-- falta parâmetro real
02.
Traceback (most recent call last):
03.
File
"<string>"
, line
1
,
in
<fragment>
04.
TypeError: dobro() takes exactly
1
argument (
0
given)
05.
>>> dobro(z)
# <-- parâmtero real sem objecto associado
06.
Traceback (most recent call last):
07.
File
"<string>"
, line
1
,
in
<fragment>
08.
NameError: name
'z'
is
not
defined
09.
>>>
10.
<
/
fragment><
/
string><
/
fragment><
/
string>
Mas se disse que o nome usado como parâmetro formal pode ser qualquer o que acontece no caso de parâmetro formal (ou da definição) e parâmetro real (o da chamada) forem o mesmo nome?
1.
>>>
def
dobro(n):
2.
...
return
2
*
n
3.
...
4.
>>> n
=
6
5.
>>> dobro(n)
6.
12
7.
>>> n
8.
6
Como se pode ver, não acontece nada de anormal neste caso. Repito: o nome do parâmetro formal é arbitrário e só existe na realidade durante a execução da definição de que faz parte. Nessa altura é feita a associação do nome do parâmetro formal ao objecto passado como parâmetro real. No caso de o parâmetro real ser também um nome então o que é comunicado ao parâmetro formal é a referência (a identidade) do objecto a que está associado. Se o objecto correspondente ao parâmetro real for imutável nada de especial acontece, a não ser a definição ser executada e o resultado ser devolvido. Se o parâmetro real corresponder a um objecto mutável o caso muda de figura, pois as alterações ao parâmetro formal podem ser transferidas para o objecto associado ao parâmetro real. E nem é preciso os nomes dos parâmetros formal e real serem o mesmo!
01.
>>>
def
aumenta(lista,elem):
02.
... lista.append(elem)
03.
...
return
lista
04.
...
05.
>>> aumenta([
'a'
,
2
,
'c'
],
4
)
06.
[
'a'
,
2
,
'c'
,
4
]
07.
>>> minha_lista
=
[
1
,
2
,
3
]
08.
>>> aumenta(minha_lista,
4
)
09.
[
1
,
2
,
3
,
4
]
3
# <-- lista alterada dentro do programa
10.
>>> minha_lista
11.
[
1
,
2
,
3
,
4
]
3
<
-
-
minha_lista alterada como resultado da alteração a lista
12.
>>> lista
=
[
'a'
,
'b'
,
'c'
]
13.
>>> aumenta(lista,
'd'
)
14.
[
'a'
,
'b'
,
'c'
,
'd'
]
15.
>>> lista
16.
[
'a'
,
'b'
,
'c'
,
'd'
]
17.
>>>
Para se certificar se entendeu veja se não tem dúvidas neste último exemplo:
1.
>>> minha_lista
=
[
1
,
2
,
3
,
4
]
2.
>>> aumenta(minha_lista
+
[
5
],
6
)
3.
[
1
,
2
,
3
,
4
,
5
,
6
]
4.
>>> minha_lista
5.
[
1
,
2
,
3
,
4
]
6.
>>>
Enquanto não entender isto terá sempre dificuldades no futuro. Por isso batalhe até entender. Se as dúvidas se mantiverem, fale com o seu professor!
Sem comentários:
Enviar um comentário