web-dev-qa-db-ja.com

空の関数が必要な理由

私は学習を始めましたpython and私はなぜプログラミング言語で空の関数が必要なのかと思っています

例えばPythonで:

def empty_func():
    pass

シェルスクリプトでも空の関数空の関数を使用できます。

私の理解と質問:

  1. プログラミング言語に空の関数が必要なのはなぜですか?それは、プログラミング言語をいじくり回すだけなのか、それとも本当に重要なことなのか?

  2. これに目的がある場合、誰かがユースケースを説明したり、空の関数の使用法の実際の例を挙げたりできますか?

  3. または、空の関数を許可するプログラミング言語の伝統はありますか?


編集(あなたの回答を読んで得たもの):

  • スケッチアルゴリズムまたは抽象関数用
  • アクションなしでフォームを送信するには、実行する必要があります
  • いくつかのプレースホルダー 必須の操作
9
jeyanthinath

Bourneファミリのシェル言語では、:コマンドはまったく何もしませんが、通常は次の2つの状況で使用されます。

  • 何かが必須コマンドを期待するときのためのプレースホルダー、例えば.

    while some_condtion
    do :
    done
    

    doには少なくとも1つのコマンドが必要です。

  • 引数を破棄しますが、引数リスト内で副作用を実行します。

    : ${myvar=foo}
    

おそらくシェルの専門家が知っている他のアプリケーションがあると思います:)

Python(および他の言語)では、あまり使用されません。実際には何もしたくない場合は、高次関数の引数として機能します。たとえば、フォームを送信し、送信の完了後に非同期で関数を呼び出すことができる関数:

def submit(callback=empty_func):
    ...

このように、callbackが指定されていない場合でも、送信は行われますが、それ以上のアクションは実行されません。デフォルト値としてNoneを使用していた場合、コールバックがNoneであるかどうかを明示的に確認して、コードを整理する必要があります。

5
Rufflewind

それは、開発サイクルのどこに立っているかによって異なりますが、アルゴリズムをスケッチするときに、複雑なブロックをすぐに実装せずに抽象化したい場合があります。

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

init_stuffは機能します。頭の中で簡単ですが、すぐには必要ないので、空の関数として宣言します。それはあなたのコードが厄介な詳細を気にすることなくコンパイルして実行できるようにします。

リリースされたアプリケーションのもう1つの用途は、継承を使用する場合です。プラットフォーム固有のコードの動作を定義する大きなクラスがあるとします。あなたはこれに似たロジックで終わるかもしれません:

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

このコードは多くのプラットフォームで機能しますが、一部のプラットフォームではファイルシステムの初期化が不要な場合があります。次に、継承は次のようになります(C++での仮想的な= 0は、派生クラスがこれらのメソッドを実装する必要があることを意味します):

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

次に、このクラス(インターフェース)の特定の実装は、これらのメソッドの一部に対して何もしない場合があります。または、基本クラスは、仮想を宣言する代わりに、init/releaseの空のメソッドを宣言することもできます。

最後に(そして恥ずかしいことに)、非常に古いアプリケーションを維持することがあります。メソッドを削除すると問題が発生するのではないかと心配しています。これは、適切に理解されていない複雑な継承がある場合、または多くの関数ポインター(コールバック)がある場合に発生します。それらの中のコードを削除するだけで、何も壊さずに呼び出されます。

1
Eric

Rufflewindは、完成したプログラムで空の関数を使用する場合をカバーする優れた機能を果たしました。私の経験では、これは未完成のプログラムでより頻繁に使用される傾向があるため、これから作成する内容を計画し、実際に実装するまでコンパイルすることができます。つまり、通常は単なるプレースホルダーです。

中括弧{}を使用するCのような言語とは異なり、ブロックをマークするためにインデントを使用するため、これはpythonの場合に必要です。つまり、passがない場合、パーサーは空のままにするか、忘れたかを判断できませんでした。 passを含めると、パーサーがはるかにシンプルになり、実装されていないブロックを探しているときにWordを検索するのに便利です。

0
Karl Bielefeldt

これはPythonで期待することではありませんが、デバイスドライバーの世界では、(a)発生しないことがわかっている、または( b)気にしても気にしない。

これは、コールバックを使用してCでも確認できます。たまに、コールバックを提供したと仮定して、それを呼び出そうとするコードが表示され、nullポインタのリスクは無視されます。その場合にできることは、空のコールバックルーチンを提供することだけです。 (はい、私は特定のベンダーを念頭に置いています。)

0
John R. Strohm