por que a função vazia é necessária


9

Comecei a aprender python e estou me perguntando por que a função vazia é necessária em uma linguagem de programação

por exemplo, em python:

def empty_func():
    pass

mesmo em scripts de shell, função vazia, funções vazias estão disponíveis.

Meus entendimentos e pergunta:

  1. Por que a linguagem de programação precisava de funções vazias? É apenas para brincar com a linguagem de programação ou nada mais que realmente importa?

  2. Se isso tiver um objetivo, alguém pode descrever o caso de uso ou dar um exemplo real do uso de funções vazias?

  3. Ou existe alguma tradição de linguagens de programação que permitam funções vazias?


EDIT (Coisas que recebi ao ler suas respostas):

  • Para esboçar algoritmos ou com funções abstratas
  • Para enviar formulários sem ação, é necessário executar
  • Espaço reservado para algumas operações obrigatórias

11
eles podem ser usados ​​como STUBS se a execução do programa espera encontrá-los / usá-los, no entanto, você não deseja alterar nada através deles.
G.Rassovsky

Respostas:


5

Nas linguagens shell da família Bourne, o :comando, que nada faz, geralmente é usado em duas situações:

  • Espaço reservado para quando algo espera um comando obrigatório, por exemplo

    while some_condtion
    do :
    done
    

    já que dorequer pelo menos um comando.

  • Descartando os argumentos, mas realizando efeitos colaterais dentro da lista de argumentos, por exemplo,

    : ${myvar=foo}

Tenho certeza de que provavelmente existem outros aplicativos que os especialistas em shell conheceriam :)

No Python (e em outras línguas) é usado com menos frequência. Pode atuar como argumento para uma função de ordem superior quando você realmente não deseja fazer nada. Por exemplo, digamos que você tenha uma função que envia um formulário e permite que uma função seja chamada de forma assíncrona após a conclusão do envio:

def submit(callback=empty_func):
    ...

Dessa forma, se o callbackitem não for fornecido, o envio ainda será concluído, mas nenhuma ação adicional será executada. Se você tivesse usado Nonecomo o valor padrão, teria que verificar explicitamente se o retorno de chamada era None, adicionando confusão ao código.


1

Depende de onde você está no ciclo de desenvolvimento, mas às vezes, ao esboçar um algoritmo, você deseja abstrair sobre blocos complexos sem implementá-los imediatamente.

def full_algo():
  init_stuff()
  process_stuff()
  ...

Você sabe como init_stuffvai funcionar, é bastante simples na sua cabeça, mas você realmente não precisa disso imediatamente, então a declara como uma função vazia. Isso permitirá que seu código seja compilado e executado sem se preocupar com os detalhes sangrentos.

Outro uso para aplicativos liberados é ao usar herança. Suponha que você tenha uma classe grande que define o comportamento do código específico da plataforma. Você pode acabar com uma lógica semelhante a esta:

init_filesystem();
access_files();
release_filesystem();

Esse código funcionará em muitas plataformas, mas algumas plataformas podem não precisar da inicialização do sistema de arquivos. Então sua herança ficará assim (virtual com = 0 em C ++ significa apenas que as classes derivadas DEVEM implementar esses métodos):

class FileSystem{
  virtual void init_filesystem() = 0;
  virtual void access_files() = 0;
  virtual void release_filesystem() = 0;
};

Então, uma implementação específica dessa classe (interface) pode não fazer nada para alguns desses métodos. Como alternativa, a classe base poderia declarar métodos vazios para init / release em vez de declará-los virtuais.

Finalmente (e vergonhosamente), às vezes você mantém um aplicativo muito antigo. Você teme que os métodos de exclusão quebrem as coisas. Isso acontece quando você tem uma herança complexa que não é entendida corretamente ou quando você tem muitos ponteiros de função (retornos de chamada). Você apenas exclui o código dentro deles para que eles sejam chamados de qualquer maneira sem quebrar nada.


0

O Rufflewind fez um bom trabalho ao cobrir quando você pode usar uma função vazia em um programa concluído. Na minha experiência, ele tende a ser usado com mais frequência em programas inacabados, para que você possa planejar o que vai escrever e ainda compilar até que você possa realmente implementá-lo. Em outras palavras, geralmente é apenas um espaço reservado.

É necessário no caso do python porque usa recuo para marcar blocos, ao contrário de linguagens do tipo C que usam chaves {}. Isso significa que, se você não tiver pass, o analisador não saberá se você deseja deixá-lo vazio ou se esqueceu. A inclusão passtorna o analisador muito mais simples e fornece uma palavra conveniente para procurar quando você procura blocos não implementados.


11
Para código inacabado, jogar NotImplementedErroré uma solução mais adequada, pois "Erros nunca devem passar silenciosamente" e chamar uma função não implementada em um programa ativo é um erro.
ivan_pozdeev

Depende. Para o código que você envia, sim. Mas se é um código que você espera implementar em uma hora e você o deixa não implementado enquanto trabalha nos testes de unidade, simplesmente não deixar nenhuma implementação pode ser uma opção melhor. Muitas vezes, meu trabalho é o método 1) write esboço com pass 2) teste de gravação unidade que valor testes de retorno 3) verificar teste falhar (como método retorna indefinido) 4) implementar o método 5) verificar teste agora passa
Gort o robô

0

Embora não seja algo que você esperaria fazer no Python, há momentos no mundo dos drivers de dispositivo em que você precisa fornecer uma função vazia, para lidar com um evento que você (a) sabe que não vai acontecer ou ( b) não se importa, mesmo que isso aconteça.

Você também vê isso em C com retornos de chamada. Ocasionalmente, você verá um código que ASSUME que você forneceu um retorno de chamada e tenta chamá-lo, ignorando o risco de um ponteiro nulo. Tudo o que você pode fazer nesse caso é fornecer uma rotina de retorno de chamada vazia. (Sim, eu tenho um fornecedor específico em mente.)


Eu usei passmuito como espaço reservado ao escrever código, especialmente em classes, quando quero algo executável antes que tudo esteja completo. É realmente o equivalente do {}python, o qual o python não pode fazer, pois não usa chaves. Nesse sentido, todas as línguas que eu conheço permitem isso, é que apenas algumas delas pythonexigem uma palavra-chave. Mesmo nos dias de assembléia que tivemos NOP.
Gort the Robot

@StevenBurnap, geralmente quando faço algo assim, incluo o equivalente local de printf (">>> rotina XXX chamada \ n");
John R. Strohm
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.