-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: seção sobre atributos de classe iniciada em POO
- Loading branch information
1 parent
cf34ee7
commit 4347443
Showing
2 changed files
with
283 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,282 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"# Atributos de classes" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Vimos que podemos definir atributos de instância em uma classe, que são variáveis que pertencem a cada objeto da classe. Mas também podemos definir atributos de classe, que são variáveis que pertencem à classe em si, e não a cada objeto da classe. A diferença é que os atributos de classe são compartilhados por todos os objetos da classe. \n", | ||
"\n", | ||
"Eu sei que é difícil entender isso só com palavras, então vamos ver um exemplo." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"class Carro:\n", | ||
" quantidade_rodas: int = 4\n", | ||
"\n", | ||
" def __init__(self, marca: str, modelo: str):\n", | ||
" self.marca = marca\n", | ||
" self.modelo = modelo\n", | ||
"\n", | ||
"\n", | ||
"corolla = Carro(\"Toyota\", \"Corolla\")\n", | ||
"civic = Carro(\"Honda\", \"Civic\")" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"O que há de diferente no código acima? Percebam que o atributo `quantidade_rodas` é definido dentro da classe, porém fora do método `__init__` e sem usar a referência à instância `self` com a notação de ponto `self.quantidade_rodas`. O que isso quer dizer? Isso significa que ele é um atributo de classe e não de instância. Por ele ser um atributo de classe, significa que todas as instâncias da classe `Carro` compartilham o mesmo valor para `quantidade_rodas`.\n", | ||
"\n", | ||
"Por ele ser um atributo de classe, significa que todas as instâncias da classe `Carro` compartilham o mesmo valor para `quantidade_rodas`. Tal valor pode ser acessado por cada uma das instâncias ou a partir da própria classe com a notação de ponto `Carro.quantidade_rodas`." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 3, | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"name": "stdout", | ||
"output_type": "stream", | ||
"text": [ | ||
"4\n", | ||
"4\n" | ||
] | ||
} | ||
], | ||
"source": [ | ||
"class Carro:\n", | ||
" quantidade_rodas: int = 4\n", | ||
"\n", | ||
" def __init__(self, marca: str, modelo: str):\n", | ||
" self.marca = marca\n", | ||
" self.modelo = modelo\n", | ||
"\n", | ||
"\n", | ||
"corolla = Carro(\"Toyota\", \"Corolla\")\n", | ||
"civic = Carro(\"Honda\", \"Civic\")\n", | ||
"\n", | ||
"# Todas as instâncias compartilham o mesmo valor do atributo de classe quantidade_rodas\n", | ||
"print(Carro.quantidade_rodas) # 4\n", | ||
"print(corolla.quantidade_rodas) # 4\n", | ||
"print(civic.quantidade_rodas) # 4" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Podemos mudar de forma global o valor de `quantidade_rodas` para todas as instâncias da classe `Carro`, e isso será refletido em todas as instâncias. Nem sempre isso é desejado e é por isso que devemos ter cuidado ao usar atributos de classe principalmente quando alteramos tal valor." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 7, | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"name": "stdout", | ||
"output_type": "stream", | ||
"text": [ | ||
"Atributo de classe quantidade_rodas antes da alteração de valor\n", | ||
"Corolla tem 4 rodas\n", | ||
"Civi tem 4 rodas\n", | ||
"---\n", | ||
"Alteramos o valor do atributo de classe quantidade_rodas para 5\n", | ||
"---\n", | ||
"Instâncias criadas antes da alteração de valor do atributo de classe\n", | ||
"Corolla tem 5 rodas\n", | ||
"Civi tem 5 rodas\n", | ||
"Instância criada após a alteração de valor do atributo de classe\n", | ||
"Gol tem 5\n" | ||
] | ||
} | ||
], | ||
"source": [ | ||
"class Carro:\n", | ||
" quantidade_rodas: int = 4\n", | ||
"\n", | ||
" def __init__(self, marca: str, modelo: str):\n", | ||
" self.marca = marca\n", | ||
" self.modelo = modelo\n", | ||
"\n", | ||
"\n", | ||
"corolla = Carro(\"Toyota\", \"Corolla\")\n", | ||
"civic = Carro(\"Honda\", \"Civic\")\n", | ||
"\n", | ||
"print(\"Atributo de classe quantidade_rodas antes da alteração de valor\")\n", | ||
"print(f\"Corolla tem {corolla.quantidade_rodas} rodas\") # 4\n", | ||
"print(f\"Civi tem {civic.quantidade_rodas} rodas\") # 4\n", | ||
"\n", | ||
"# Alterando o valor do atributo de classe quantidade_rodas.\n", | ||
"# Isso terá reflexo tanto em instâncias criadas antes da\n", | ||
"# alteração quanto em instâncias criadas após a alteração!\n", | ||
"print(\"---\")\n", | ||
"print(\"Alteramos o valor do atributo de classe quantidade_rodas para 5!\")\n", | ||
"print(\"---\")\n", | ||
"\n", | ||
"Carro.quantidade_rodas = 5\n", | ||
"\n", | ||
"gol = Carro(\"Volkswagen\", \"Gol\")\n", | ||
"\n", | ||
"print(\"Instâncias criadas antes da alteração de valor do atributo de classe\")\n", | ||
"print(f\"Corolla tem {corolla.quantidade_rodas} rodas\") # 5\n", | ||
"print(f\"Civi tem {civic.quantidade_rodas} rodas\") # 5\n", | ||
"\n", | ||
"print(\"Instância criada após a alteração de valor do atributo de classe\")\n", | ||
"print(f\"Gol tem {gol.quantidade_rodas} rodas\") # 5" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Atributos de classe são úteis para definir valores que são compartilhados por todas as instâncias da classe, como por exemplo, valores padrão que são comuns a todas as instâncias. Porém, é preciso ter muito cuidado ao alterar tais valores, pois isso pode causar efeitos colaterais inesperados, conforme vimos acima.\n", | ||
"\n", | ||
"Vamos ver um exemplo real de aplicação de atributos de classe." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 15, | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"name": "stdout", | ||
"output_type": "stream", | ||
"text": [ | ||
"Salários iniciais:\n", | ||
"10000\n", | ||
"10000\n", | ||
"10000\n", | ||
"\n", | ||
"Salários após aumento de 5% para todos os sêniors da empresa:\n", | ||
"10500.0\n", | ||
"10500.0\n", | ||
"10500.0\n", | ||
"\n", | ||
"Salários após bônus individual para Carlos:\n", | ||
"10500.0\n", | ||
"11500.0\n", | ||
"10500.0\n" | ||
] | ||
} | ||
], | ||
"source": [ | ||
"# 1\n", | ||
"class Senior:\n", | ||
" # 2\n", | ||
" salario_base = 10_000\n", | ||
"\n", | ||
" # 3\n", | ||
" def __init__(self, nome: str, id_funcionario: int, anos_experiencia: int):\n", | ||
" self.nome = nome\n", | ||
" self.id_funcionario = id_funcionario\n", | ||
" self.anos_experiencia = anos_experiencia\n", | ||
" self.bonus_individual = 0\n", | ||
"\n", | ||
" # 4\n", | ||
" def calcular_salario(self) -> int:\n", | ||
" return Senior.salario_base + self.bonus_individual\n", | ||
"\n", | ||
" # 5\n", | ||
" def aplicar_bonus(self, valor: int) -> None:\n", | ||
" self.bonus_individual += valor\n", | ||
"\n", | ||
"\n", | ||
"# 6\n", | ||
"senior1 = Senior(nome=\"Ana Silva\", id_funcionario=1, anos_experiencia=8)\n", | ||
"senior2 = Senior(nome=\"Carlos Oliveira\", id_funcionario=2, anos_experiencia=10)\n", | ||
"senior3 = Senior(nome=\"Mariana Santos\", id_funcionario=3, anos_experiencia=7)\n", | ||
"\n", | ||
"# 7\n", | ||
"print(\"Salários iniciais:\")\n", | ||
"print(senior1.calcular_salario())\n", | ||
"print(senior2.calcular_salario())\n", | ||
"print(senior3.calcular_salario())\n", | ||
"\n", | ||
"# 8\n", | ||
"Senior.salario_base = Senior.salario_base * (1 + 5 / 100)\n", | ||
"\n", | ||
"# 9\n", | ||
"print(\"\\nSalários após aumento de 5% para todos os sêniors da empresa:\")\n", | ||
"print(senior1.calcular_salario())\n", | ||
"print(senior2.calcular_salario())\n", | ||
"print(senior3.calcular_salario())\n", | ||
"\n", | ||
"# 10\n", | ||
"senior2.aplicar_bonus(1_000)\n", | ||
"\n", | ||
"# 11\n", | ||
"print(\"\\nSalários após bônus individual para Carlos:\")\n", | ||
"print(senior1.calcular_salario())\n", | ||
"print(senior2.calcular_salario())\n", | ||
"print(senior3.calcular_salario())" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Vamos entender o código acima com calma. Vá acompanhando pelas numerações no código e a respectiva explicação abaixo.\n", | ||
"\n", | ||
"1. Criamos a classe `Senior`, que representa um colaborador sênior de uma empresa\n", | ||
"2. Definimos o atributo de classe `10_000`. Todos os sêniors da empresa recebem o mesmo salário.\n", | ||
"3. O método construtor define os atributos de instância `nome`, `id_funcionario`, `anos_experiencia` e `bonus_individual`.\n", | ||
"4. Temos um método que calcula o salário do colaborador sênior. O salário é a soma do salário base mais o bônus individual.\n", | ||
"5. Temos um outro método que acrescenta um valor ao bônus individual do colaborador sênior com base em um parâmetro informado.\n", | ||
"6. Criamos 3 funcionários seniores.\n", | ||
"7. Imprimimos os salários iniciais de cada um deles. Todos são iguais até aqui.\n", | ||
"8. **Aplicamos um aumento de 5% para todos os seniores modificando o atributo de classe.**\n", | ||
"9. Imprimimos novamente os salários de cada um deles. Todos tiveram um aumento de 5%.\n", | ||
"10. Configuramos um bônus individual para um dos seniores.\n", | ||
"11. Imprimimos novamente os salários de cada um deles. Apenas o salário do senior, que teve o bônus individual aplicado, foi alterado.\n", | ||
"\n", | ||
"O passo 8 é o principal, pois refere-se ao tópico desta seção. Ele poderia ser muito bem definido como uma regra igualitária da empresa na qual todos os colaboradores sêniores recebem um aumento de 5% no salário. Isso é um exemplo de aplicação de atributos de classe.\n", | ||
"\n", | ||
"Mas novamente, notem que ao alterar o atributo de classe, literalmente **todas as instâncias**, tanto aquelas criadas antes da alteração quanto as criadas após a alteração do atributo de classe **são afetadas.**" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## ⚒️👷 (WIP) capítulo em construção ⚒️👷" | ||
] | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": ".venv", | ||
"language": "python", | ||
"name": "python3" | ||
}, | ||
"language_info": { | ||
"codemirror_mode": { | ||
"name": "ipython", | ||
"version": 3 | ||
}, | ||
"file_extension": ".py", | ||
"mimetype": "text/x-python", | ||
"name": "python", | ||
"nbconvert_exporter": "python", | ||
"pygments_lexer": "ipython3", | ||
"version": "3.12.6" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 2 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters