Solucionado (ver solução)
Solucionado
(ver solução)
5
respostas

[Projeto] Desafio: Conversão de moedas - dólar e real

import re


class ExtratorURL:
    def __init__(self: object, url: str) -> None:
        self.url = self.sanitiza_url(url)
        self.valida_url()

    def sanitiza_url(self: object, url: str) -> str:
        if type(url) == str:
            return url.strip()
        else:
            return ''

    def valida_url(self: object) -> None:
        if not self.url:
            raise ValueError('A URL está vazia')

        url = 'https://www.bytebank.com.br/cambio'
        padrao_url = re.compile(
            '(http(s)?://)?(www.)?bytebank.com(.br)?/cambio'
        )
        match = padrao_url.match(url)

        if not match:
            raise ValueError('A URL não é válida')

    def get_url_base(self: object) -> str:
        indice_interrogacao = self.url.find('?')
        url_base = self.url[:indice_interrogacao]
        return url_base

    def get_url_parametro(self: object) -> str:
        indice_interrogacao = self.url.find('?')
        url_parametro = self.url[indice_interrogacao + 1 :]
        return url_parametro

    def get_valor_parametro(self: object, parametro_busca) -> int:
        indice_parametro = self.get_url_parametro().find(parametro_busca)
        indice_valor = indice_parametro + len(parametro_busca) + 1
        indice_e_comercial = self.get_url_parametro().find('&', indice_valor)

        if indice_e_comercial == -1:
            valor = self.get_url_parametro()[indice_valor:]
        else:
            valor = self.get_url_parametro()[indice_valor:indice_e_comercial]
        return valor

    def __len__(self: object) -> int:
        return len(self.url)

    def __str__(self: object) -> str:
        return f'{self.url}\nParâmetros: {self.get_url_parametro()}\nURL Base: {self.get_url_base()}'

    def __eq__(self: object, other: str) -> bool:
        return self.url == other.url

    def consersao_moeda(self: object) -> None:
        valor_dolar = 5.50
        moeda_origem = extrator_url.get_valor_parametro('moedaOrigem')
        moeda_destino = extrator_url.get_valor_parametro('moedaDestino')
        quantidade = extrator_url.get_valor_parametro('quantidade')

        if moeda_origem == 'dolar' and moeda_destino == 'real':
            conversao = int(quantidade) * valor_dolar
            print(
                f'{quantidade} dolares convertidos para real dá {conversao} reais'
            )
        elif moeda_origem == 'real' and moeda_destino == 'dolar':
            conversao = int(quantidade) // valor_dolar
            print(
                f'{quantidade} reais convertidos para dolar dá {conversao} dolares'
            )

url = 'bytebank.com/cambio?quantidade=100&moedaOrigem=real&moedaDestino=dolar'
extrator_url = ExtratorURL(url)
extrator_url.consersao_moeda()
print(f'O tamanho da URL é de {len(extrator_url)} caracteres')
print(extrator_url)
5 respostas

Olá @Bruna, seja bem-vinda ao nosso Fórum,

Não entendi qual a sua pergunta. Seu código está com algumas linhas cortadas no começo e no fim, então está um pouco difícil de ler

Oii, erick, agora foi, não sei o que aconteceu para ter cortado! kkkkk Não foi uma pergunta, apenas postei a resolução do desafio que o professor da aula passou, caso tenha a necessidade de correção de algo ou alguma dica de melhoria. (:

Agora melhorou :)

Alguns comentários:

1 - Use isinstance()

Em vez de escrever:

if type(url) == str:
            # código

É preferível utilizar a função isinstance()

if isinstance(url, str):
            # código

O usuário da sua função pode querer criar uma subclasse de str por algum motivo, e o seu código deve aceitar as subclasses de str (O nome dessa boa prática é Princípio da Substituição de Liskov).

O código como está agora verificaria que o tipo não é exatamente igual a str e rejeitaria a entrada. Não devemos verificar a igualdade do tipo, mas sim se um objeto é instância de uma classe.

2 - valida_url()

No método valida_url(), em vez de acessar o atributo self.url, está sendo definida uma variável url com um valor constante. O método não está validando o atributo url do objeto, e nunca vai levantar uma exceção.

3 - get_url_parametro()

Caso não existam parâmetros na URL, o método vai retornar a URL inteira.

4 - Princípio da Responsabilidade Única

Uma classe URL tem métodos relacionados com o tratamento da URL. Não faz sentido criar métodos para outras coisas não relacionadas, como um conversor de moedas. Note que o parâmetro self nem foi utilizado pelo método.

Separar a funcionalidade de conversão de moedas em uma classe específica para isso (ou uma função mesmo) permitirá que outras funções o encontrem e o reutilizem.

Oii, Erick, tudo bem? Pensei nas suas dicas e entendi perfeitamente, obrigada pela ajuda! Vê agora, por favor, seria assim?

import re

class ExtratorURL:
    def __init__(self: object, url: str) -> None:
            self.url = self.sanitiza_url(url)
            self.valida_url()

    def sanitiza_url(self: object, url: str) -> str:
        if isinstance(url, str):
            return url.strip()
        else:
            return ''

    def valida_url(self: object) -> None:
        if not self.url:
            raise ValueError('A URL está vazia')

        padrao_url = re.compile(
            '(http(s)?://)?(www.)?bytebank.com(.br)?/cambio'
        )
        match = padrao_url.match(url)
        if not match:
            raise ValueError('A URL não é válida')

    def get_url_base(self: object) -> str:
        indice_interrogacao = self.url.find('?')
        url_base = self.url[:indice_interrogacao]
        return url_base

    def get_url_parametro(self: object) -> str:
        indice_interrogacao = self.url.find('?')

        if indice_interrogacao:
            url_parametro = self.url[indice_interrogacao + 1 :]
            return url_parametro

    def get_valor_parametro(self: object, parametro_busca) -> int:
        indice_parametro = self.get_url_parametro().find(parametro_busca)
        indice_valor = indice_parametro + len(parametro_busca) + 1
        indice_e_comercial = self.get_url_parametro().find('&', indice_valor)

        if indice_e_comercial == -1:
            valor = self.get_url_parametro()[indice_valor:]
        else:
            valor = self.get_url_parametro()[indice_valor:indice_e_comercial]
        return valor

    def __len__(self: object) -> int:
        return len(self.url)

    def __str__(self: object) -> str:
        return f'{self.url}\nParâmetros: {self.get_url_parametro()}\nURL Base: {self.get_url_base()}'

    def __eq__(self: object, other: str) -> bool:
        return self.url == other.url

url = "bytebank.com/cambio?quantidade=100&moedaOrigem=dolar&moedaDestino=real"
extrator_url = ExtratorURL(url)

print(f'O tamanho da URL é de {len(extrator_url)} caracteres')
print(extrator_url)

moeda_origem = extrator_url.get_valor_parametro('moedaOrigem')
moeda_destino = extrator_url.get_valor_parametro('moedaDestino')
quantidade = extrator_url.get_valor_parametro('quantidade')

valor_dolar = 5.50

def consersao_moeda() -> None:
    if moeda_origem == 'dolar' and moeda_destino == 'real':
        conversao = int(quantidade) * valor_dolar
        print(
            f'{quantidade} dolares convertidos para real dá {conversao} reais'
        )
    elif moeda_origem == 'real' and moeda_destino == 'dolar':
        conversao = int(quantidade) // valor_dolar
        print(
            f'{quantidade} reais convertidos para dolar dá {conversao} dolares'
        )

consersao_moeda()
solução!

Muito bom @Bruna!

Recomendo a leitura desses artigos sobre Guard Clauses. É uma técnica para melhorar a qualidade do código e que me ajudou bastante: Guard clauses for better “if” statements — Python Refactoring: Guard Clauses

Caso meu post tenha ajudado, por favor, você poderia marcar este tópico como "solucionado"?

Bons estudos!