質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python 2.7

Python 2.7は2.xシリーズでは最後のメジャーバージョンです。Python3.1にある機能の多くが含まれています。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

3回答

1535閲覧

Pythonにも『ラムダ式の初期化キャプチャ』のような機能がありますか?

leilei

総合スコア39

Python 2.7

Python 2.7は2.xシリーズでは最後のメジャーバージョンです。Python3.1にある機能の多くが含まれています。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2018/08/25 02:55

編集2018/08/25 02:58

C++14には所謂『ラムダ式の初期化キャプチャ』という機能があります。
即ち、関数の中の部分パラメーターが環境やコンテクストに依存するものの、値は固定です。
なので、これらの環境依存のパラメーターを関数の引数として毎回毎回pass必要としないのです。それは以下のようなやり方で実現できます。

C++

1int increment(int x) 2{ 3 return x + 1; 4} 5 6int main() 7{ 8 // increment(3)の戻り値を、変数x,yとしてラムダ式内で使用する 9 auto f = [a = increment(1), b = increment(2), c = increment(3)](int x, int y) { return x*a*b + y*c; }; 10 11 int result=0; 12 for(int i=0; i<1000; i++) result += f(i, cos(i)); 13 14 return result; 15} 16

##C++14のこのようなやりかたがスマートと思いますので、Pythonにも似たやり方があるかどうかお尋ねしたいのです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

要するにクロージャとしての機能ですよね。
Pythonでは関数内関数を定義できるので、それを利用すれば良いです。

Python

1from math import cos 2 3 4def increment(x): 5 return x + 1 6 7 8def make_func(a0, b0, c0): 9 a = increment(a0) 10 b = increment(b0) 11 c = increment(c0) 12 13 def func(x, y): 14 return x * a * b + y * c; 15 16 return func 17 18 19def main(): 20 func = make_func(1, 2, 3) 21 return sum( 22 func(i, cos(i)) for i in range(1000) 23 ) 24 25 26print( 27 main() 28)

GCが働いてくれるので、オブジェクトの寿命に神経を使わなくて良いのは大きな利点です。


ラムダ式で表現することも出来ないことは無いですが、ここでは不向きです。

  • Pythonではラムダ式内に文を置くことができない
  • Pythonには代入式は存在せず、代入文が用いられる
  • PEP8の規定に依り、ラムダ関数を変数に束縛するのは好まれない

投稿2018/08/25 03:04

編集2018/08/25 03:20
LouiS0616

総合スコア35660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

leilei

2018/08/29 09:58

すばらしいコメント有難うい御座いました!
guest

0

すでにそのものズバリの回答がついているのと、個人的にあまり関数閉包が好きではないので、「似たやり方」をいくつか。

普通にクラスにする

けっきょく、欲しいものは閉じた名前空間のあるオブジェクト。普通に考えたらインスタンスです。

python

1class Hoge: 2 def __init__(self, i): 3 self.i = i 4 5 def f(self, x): 6 return x + self.i 7 8hlst = [] 9for i in range(5): 10 h = Hoge(i) 11 hlst.append(h) 12 13for h in hlst: 14 print(h.f(0)) 15 16""" => 170 181 192 203 214 22""" 23

この規模だと見栄えがしませんが、ある程度大きいものを作るならいい方法です。

引数のデフォルト値を活用する

デフォルト値が実行時(関数定義時)評価なのがキモ。

python

1flst = [] 2for i in range(5): 3 def f(x, i=i): 4 return x + i 5 flst.append(f) 6 7for f in flst: 8 print(f(0)) 9""" 100 111 122 133 144 15""" 16

単に外のスコープに置く

python

1a = increment(1) 2b = increment(2) 3c = increment(3) 4def func(x, y): 5 return x * a * b + y * c

これで済むなら別にこれでも良いのでは? と思います。

関数オブジェクトの属性に押し込む

この方法は汚いので非推奨ですが・・・

python

1flst = [] 2for i in range(5): 3 def f(x): 4 return x + f.i 5 f.i = i 6 flst.append(f) 7 8for f in flst: 9 print(f(0)) 10 11""" => 120 131 142 153 164 17"""

記述量だけならクロージャより少なくて済むのが強みです。引数のデフォルト値を使う方法には負けますが。

関数に呼び出しをまたいで変化する状態を持たせるような用途だと、この方法は輝きます。デフォルト値では(たぶん)できないからです。

これとクロージャでカウンタを書いた例。

python

1# クロージャ版 2def make_f(init): 3 def f(): 4 nonlocal init # 必須 5 init += 1 6 return init 7 return f 8 9f = make_f(0) 10for i in range(5): 11 print(f()) 12""" => 131 142 153 164 175 18""" 19 20# 属性版 21def f(): 22 f.init += 1 23 return f.init 24f.init = 0 25 26for i in range(5): 27 print(f()) 28""" => 291 302 313 324 335 34"""

投稿2018/08/26 00:08

編集2018/08/26 00:13
hayataka2049

総合スコア30933

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

leilei

2018/08/29 09:59

hayataka2049さん サンプルコード本当に有難うございます! 良い勉強になりました。
guest

0

python

1increment = lambda x: x + 1 2f = lambda x, y: x * increment(1) * increment(2) + y * increment(3) 3print(f(1, 2)) 4increment = lambda x: x + 2 5print(f(1, 2))

pythonはスクリプト言語なので、C++のようなことをしなくても良いのでは…

投稿2018/08/25 10:52

編集2018/08/25 10:55
mkgrei

総合スコア8560

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

leilei

2018/08/29 10:01 編集

> pythonはスクリプト言語なので、C++のようなことをしなくても良いのでは… この辺ですね! もう少し深く考えてみたいと思います。 良いヒント有難うございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問