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

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

ただいまの
回答率

91.33%

  • Python

    3878questions

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

  • Python 3.x

    2451questions

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

  • 関数

    153questions

    関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

[python3]この関数の説明をしていただけないでしょうか

解決済

回答 2

投稿 2017/12/07 00:42

  • 評価
  • クリップ 1
  • VIEW 120

matsukogo

score 2

python初心者のものです。

あるサイトで初心者用のデコレータ関連の記事を読んでいて自分でコードを書いていじっていたところ、
どうしても仕組みを理解できない関数(といっていいのかわかりませんが…)が出来上がってしまいました。
エラーが発生しないので、ますますわかりません。どなたか教えていただけないでしょうか。

コードは下記です。

def scramble(egg):
    def _scramble():
        return "scramble " + egg() + "!"
    return _scramble

def potato():
    return "egg"

if __name__ == '__main__':
    scramble_egg = scramble(potato)
    print(scramble_egg()) 

#scramble egg! が表示されます

scramble()関数を引数potatoで呼び出すということだと思うのですが、
potato()関数がないと「potatoが定義されていない」というエラーになります。
potato()は一切かかわていないと思うのですが…。

ためしにtypeで型を調べてみました。

print(type(potato)) #func
print(type(potato())) #str

これはつまりscramble()の引数potatoは関数で、
関数が呼ばれてeggがreturnされ、scramble()の引数にeggが入ったということでしょうか?

よろしくおねがいします。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

+5

名前の付け方が少し混乱しているようなので整理してみました。これはクロージャという手法(仕組み?)ですが、リスト内包記法と同様に頭が慣れるまでは難しく感じるかもしれません。コメントも追加したので参考にしてみてください。

def scramble(fn):
    '''関数を受け取って少し手を加えた関数を返す

    関数に手を加えるのでデコレーターとも言います
    '''
    def closure():
        return "scramble " + fn() + "!"  # 元の関数を呼び出してその戻り値に手を加えて返します
    return closure  # 元々の関数ではなくて関数の中で定義した関数を返します

def potato():
    return "potato"

@scramble  # 特殊な書き方でこう書くと関数がデコレートされます
def egg():
    return "egg"

if __name__ == '__main__':
    print(egg())  # すでにデコレート済みなので「scramble egg!」と表示
    scramble_potato = scramble(potato)
    print(scramble_potato())  # 上の行で素のpotatoをデコレートしたので「scramble potato!」と表示

投稿 2017/12/07 01:17

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/07 09:53

    ご丁寧にありがとうございます。デコレータもクロージャもいろんな説明を読んだのですが、理解するにはまだかかりそうです・・・。ご説明いただいた内容を参考にさせていただきます。取り急ぎ感謝申し上げます。

    キャンセル

checkベストアンサー

+3

これはつまりscramble()の引数potatoは関数で、
関数が呼ばれてeggがreturnされ、scramble()の引数にeggが入ったということでしょうか?

その認識は異なります。Pythonでは、関数そのものを渡すことが可能です。

def hoge():
    print('hoge')

def spam_ham(func):
    print('spam')
    func()
    print('ham')

spam_ham(hoge)

"""実行結果
spam
hoge
ham
"""

関数の実行結果が渡されるわけではありません。
(実行されてから渡されるなら、第一行目にhogeと表示されるはず)


上記の例に加えて、こちらの例も示したいと思います。

def fuga():
    return 'fuga'

func = fuga    # 関数を代入
text = fuga()  # 関数の実行結果を代入

print(type(func))    # <class 'function'>
print(type(text))    # <class 'str'>

func()         # 関数は呼び出せる
# text()       # 関数じゃないから呼び出せない

これ以降、デコレータとは何ぞや、クロージャとは何ぞや、という理解が必要ですが、
そちらに関しましてはYouheiSakuraiさんの非常に丁寧かつ明確な回答をご覧ください。

投稿 2017/12/07 00:55

編集 2017/12/08 19:41

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/07 09:47

    ありがとうございます。大変理解が深まりました。クロージャやデコレータに関してはいまだにイマイチ理解ができていない部分が多いので今後勉強していきます。取り急ぎ感謝申し上げます。

    キャンセル

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

ただいまの回答率

91.33%

関連した質問

  • 解決済

    【Python】Classについて

    python初心者です。 pythonにおけるClassの作り方がよくわかりません。 class Something(): def hoge():

  • 解決済

    Python でclass内にdecoratorを持たせたい

    前提・実現したいこと Python でclass内にdecoratorを持たせたい 発生している問題・エラーメッセージ Traceback (most recent ca

  • 解決済

    Pythonの型について

    Pythonにおける型の扱いについて質問です。 例えば下記のようなコードの場合 def get_age(): return "20" age = get_ag

  • 解決済

    kivyのテキスト1行入力ボックスを作るコード

    kivyを勉強中なのですが、tkinterのEntryのようにテキスト1行入力ボックスを作りたくて、公式サイトをみると一応作れるようにはなっているみたいなのですが、よくわかりません

  • 解決済

    scrapyのrulesで相対URLを辿る

    現在scrapyを使ってWebスクレイピングの勉強をしています。 start_urlからリンクをたどる必要があるので、ClawlSpiderを使用しようと思っています。

  • 解決済

    リストの情報を他のクラスに渡す

    前提・実現したいこと 随時更新されていくリストの情報を他のクラスに渡したい 発生している問題・エラーメッセージ 今現在三目並べのプログラムを作っていますが、盤の情報を se

  • 解決済

    if:条件NG時の再計算

    質問事項 質問タイトルがわかり辛くすみません。 pythonの基礎勉強をしています。 下記補足に記したように、whileループの中にif文を2つ作り、各々ifの条件次第で、各々

  • 解決済

    python 文字列を判定する方法

    何らかのstr型が連続して格納されている配列(例['100'],['.'],['abc'])の各要素を判定し、数値ならint型に変換後次要素の判定に移る、数値ではないのであればfa

同じタグがついた質問を見る

  • Python

    3878questions

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

  • Python 3.x

    2451questions

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

  • 関数

    153questions

    関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。