web-dev-qa-db-ja.com

関数の作り方composer

私は大学の学位のために他の機能を丸める機能を作ろうとしています。たとえば、round_sqrt = round(sqrt)を呼び出したいのですが、round_sqrt(5)を呼び出すと、_2_ではなく_2.23606797749979_を表示する必要があります。私がしようとしているのはこれです:

_def rounding(funct):
    return round(funct)
_

しかし、これは機能しません。

編集:関数にはパラメーターを1つだけ含める必要があります。たとえば、関数の開始は

_def rounding(func):
_

したがって、この関数ではfunct関数を丸める必要があります。 rounding(abs)(3.2)を呼び出すと、_3_と表示されます。

19
php kubrick

具体的な例として、次のように書くことができます

_def round_sqrt(x):
    return round(sqrt(x))
_

アレックスの答え これを一般化します。彼は、creates_round_sqrt_という関数を定義しています。関数がすでに定義されている場合は、引数としてrounderに渡すだけです:

_round_sqrt = rounder(sqrt)
_

もちろん、必要ない場合は_round_sqrt_を定義する必要はありません。 rounder(sqrt)(3.2)は直接呼び出すことができますが、毎回再定義するよりも、複数回使用する場合は、rounderの戻り値を安全に保存する方がはるかに効率的です。

それ以外の場合、デコレータの構文は短い(Alexの例を使用)

_def adder(x, y):
    return x + y

adder = rounder(adder)
_

私のコメントで述べたように、これは作曲を実装する例です。数学関数は常に単一の引数を取り、単一の引数を返すため、構成は単純です。そのため、2つの関数fgの構成は、常に次のように簡単に定義できます。

_def compose(f, g):
    def h(x):   # The name doesn't matter
        return f(g(x))
    return h
_

それから

_round_sqrt = compose(round, sqrt)
_

(実装に関するあらゆる種類の実際的な懸念を無視すると、Pythonは理論的にはUnicode演算子__を関数に提供することもできます:_round_sqrt = round ∘ sort_。説明whyこれが起こらないのは、この回答の範囲外です。

ただし、Pythonでは、関数ははるかに複雑です。それらは複数の引数を取ることができ、任意の数の引数と任意のキーワード引数を受け入れることができ、それぞれが技術的に単一の値を返しますが、その値は複数の値またはdictと考えられるタプルです。結果として、gの戻り値を関数fに渡すには、単純なcompose関数で簡単に対応できる以上の多くの方法があります。 。

15
chepner

クロージャをチェックアウトする必要があります。

def rounder(func):
    def inner(*args, **kwargs):
        return round(func(*args, **kwargs))
    return inner

次に、@文字を使用して関数を修飾できます。

@rounder
def adder(x, y):
    return x + y

print(adder(1.1, 2.2))

出力3

補足:

  1. クロージャで functools.wraps を使用して、元の関数に関する情報(docstring、関数名など)を失わないようにすることができます。
  2. クロージャー(例 12 )とデコレーター(例 12 =)これらの用語をグーグル検索することで見つけることができる。
27
Alex

関数構成は、Pythonでネイティブにサポートされていません。 @ Alexのソリューション に従ってデコレータを使用できます。 @ chepner's solution のように明示的に新しい関数を定義できます。

または、サードパーティのライブラリを使用できます。たとえば、 toolz.compose

from toolz import compose

def adder(x, y):
    return x + y

round_adder = compose(round, adder)

round_adder(1.1, 2.2)  # 3
5
jpp