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

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

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

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

Python

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

Q&A

解決済

3回答

1233閲覧

python 関数の戻り値の処理について

yu_jin

総合スコア15

関数

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

Python

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

0グッド

0クリップ

投稿2022/01/05 11:50

編集2022/01/05 12:06

Pythonの質問です。
利用環境はPYcharmです。
Pythonの関数処理の勉強で下記コードを実行し、中身を確認しながら進めているのですが
#1のコードはreturnで値をget_first_last_wordに戻しているので、printした際に実行結果になる
ことはわかったのですが、#2を同じようにprintで中身を確認したら<function greeting.<locals>.inner at 0x000001E3959A9F30>
と表示されます。これはreturnでinner関数の値をgreeting(func)に戻しているからこの結果になるのでしょうか。
#2も#1と同じようにprintで出力すると同じような出力をすると思っていました。

教えていただきたいこと
1 <function greeting.<locals>.inner at が表示される理由
2 printでgreeting関数を表示させる際に引数に(func)を使うとエラーが起こる理由

独学ゆえに質問内容におかしなところがあるかもしれませんが
宜しくお願いします。

実行結果
#1
1 Hello, my name is Mike
2 Hello my name is Mike
3 ['Hello', 'my', 'name', 'is', 'Mike']
Hello Mike
1 Hello, my name is Mike
2 Hello my name is Mike
3 ['Hello', 'my', 'name', 'is', 'Mike']
('Hello', 'Mike')
#2
<function greeting.<locals>.inner at 0x000001E3959A9F30>
Hello!
I'm Jiro
Nice to meet you!
<function greeting.<locals>.inner at 0x000001E3959AA050>

コード #1 def get_first_last_word(text): print("1", text) text = text.replace(",", "") print("2", text) words = text.split() print("3", words) return words[0], words[-1] text = "Hello, my name is Mike" first,last = get_first_last_word(text) print(first, last) print(get_first_last_word(text)) #2 def greeting(func): def inner(*args, **kwargs): print("Hello!") func(*args, **kwargs) print("Nice to meet you!") return inner print(greeting("abc")) # a = greeting(func) # print(a) @greeting # say_name = greeting(say_name)と同じ def say_name(name): print(f"I'm {name}") say_name("Jiro") print(greeting("abc"))

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

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

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

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

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

ozwk

2022/01/05 12:00

コードはコードブロック内に書いてください 読みづらいです。 さらにpythonの場合はインデントが消えて意味がわからなくなってしまいます
yu_jin

2022/01/05 12:07

すみません。テラテイルの使い方を把握していませんでした。
guest

回答3

0

ベストアンサー

1 <function greeting.<locals>.inner at が表示される理由

print()で表示されるのは、対象となっているオブジェクトを「印字」するために用意された「表現」の文字列です。

a = 10としたときに、aに束縛されているのは、int型のオブジェクトで値として10を持っているものです。
それをprint(a)とした場合、そのint型のオブジェクトが表示されるわけですが、わかりやすく「10」という文字列が表示されます。

l = [10, 20, 'abc']のようなリストの同様です。lに束縛されているのは、見た目のとおりの数字/文字の並びではなく、リストオブジェクトです。
これをprint(l)とした場合は、わかりやすくするために、[10, 20, 'abc']のような文字列になるのです。

これらのようなオブジェクトは、人が見てわかりやすいような文字列による表現方法が用意されているので、そのように表示されるようにしていますが、オブジェクトによっては、適切な文字列表現が無いものもあります。

その1つが関数です。

defによって関数が定義さえrた場合、その関数名(これも変数です)に関数オブジェクトが束縛されます。
関数名は変数なので、他の変数に束縛するこもできます。

python

1def func_1(): 2 print('func 1') 3 4func_1() # 関数が実行され func 1 と表示される。 5 6x = func_1 # x def func_1で生成された関数オブジェクトが束縛される。 7 8x() # 関数が実行され、func 1 と表示される 9 10print(x) # <function func_1....> のように表示される。

そして、その関数オブジェクトを表示しようとした場合、一般的に関数そのものを文字列で表わす方法が無いので、pythonでは
「<function greeting.<locals>.inner at 0x000001E3959AA050>」
というような形の文字列を表示します。

また、関数オブジェクトは変数に束縛できるだけでなく、引数にもできますし、関数の返り値とすることもできます。
質問の例では、返り値としていますね。

python

1def greeting(func): 2 def inner(*args, **kwargs): 3 print("Hello!") 4 func(*args, **kwargs) 5 print("Nice to meet you!") 6 7 return inner # 上で定義した関数オブジェクトが返る。 8 9print(greeting("abc")) # <function inner...> のような表示

greeting は内部で生成した innter関数オブジェクトを返しています。

printは 「greeting("abc")」の返り値を表示しますから表示するのは、返ってきたinner関数オブジェクトで、その表示は、「<function ...>」のようなものになるというわけです。


2 printでgreeting関数を表示させる際に引数に(func)を使うとエラーが起こる理由

意味がよくわからないのですが、

python

1print(greeting(func))

としたのであれば、func が定義されていないからではないでしょうか?

投稿2022/01/05 15:14

TakaiY

総合スコア12765

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

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

0

私もpythonまだまだ勉強中のためおかしい所があったら指摘お願いします。

まず、質問者さんのコードについての説明から始めます。

python

1def greeting(func): 2 def inner(*args, **kwargs): 3 print("Hello!") 4 func(*args, **kwargs) 5 print("Nice to meet you!") 6 7 return inner

これは、inner関数を戻り値としています。
そしてinner関数は、greeting関数の引数funcを使用した関数です。
またinner関数ではfuncを関数として呼び出しているためgreetingの引数は関数である必要があります。
(inner関数の戻り値をgreeting関数の戻り値とする為にはreturn inner()というようにinner関数を実行する必要があります。)

この事から、greeting("abc")はおかしいです。
greetingの引数は関数である必要があるのに、"abc"という文字列を渡しているからです。
文字列は関数ではありません。

このgreeting関数の定義であれば、以下のように使う必要があります。

python

1def greeting(func): 2 def inner(*args, **kwargs): 3 print("Hello!") 4 func(*args, **kwargs) 5 print("Nice to meet you!") 6 7 return inner 8 9def test(name): 10 print(f"{name} is dead") 11 12 13print(greeting(test)) # A1 14print(greeting(test)('abc')) # A2 15print(greeting) # A3

greeting関数に渡す引数は、関数である必要があるので
まず、例えばtestという関数を定義し、それで#A1のように呼び出す必要があります。

しかし、#A1ではまだ「<function greeting.<locals>.inner」と表示されます。
これは、greeting関数の戻り値が関数のためです。
文字として表示するには、その戻り値である関数を実行する必要があります。
つまり、#A2のように実行する必要があるという事です。

ついでに、#A3のようにすると関数greetingがprintされます。
「<function greeting at 0x000001985D3E6B90>」ってな感じで。
def greeting(func):という定義で関数greetingが定義されているわけですね。

シンプルにすると

python

1def test(name): 2 print(f"{name} is dead") 3 4print(test) # B1 5print(test("taro")) # B2

この#B1ではtest関数をprintしているので、
<function test at 0x000001DD1A2F6B00>
と出力されます。
関数の戻り値を表示するには、関数を実行する必要があります。
関数を実行するには、#B2のように関数の定義に合わせたパラメータを使い
()を使って呼び出す必要があります。

説明ここまで、以下質問内容の回答

これはreturnでinner関数の値をgreeting(func)に戻しているからこの結果になるのでしょうか。

2も#1と同じようにprintで出力すると同じような出力をすると思っていました。

inner関数をgreeting関数の戻り値としている為です。
関数の戻り値を出力するには()をつけて呼び出す必要があります。

1 <function greeting.<locals>.inner at が表示される理由

greeting関数は、inner関数を戻り値としています。
関数が戻り値になっている為、
<function greeting.<locals>.inner = greetingの中で定義されたinner関数
とprintされます。

2 printでgreeting関数を表示させる際に引数に(func)を使うとエラーが起こる理由

python

a = greeting(func)
print(a)

ここでのgreeting(func)の意味は、greeting関数を引数funcで実行する。という意味になります。 「greeting(func)」という名前の関数が定義されているわけではありません。 定義されている関数の名前はgreetingです。 定義されていないfuncを使用している為エラーとなります。

投稿2022/01/05 21:21

xail2222

総合スコア1497

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

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

0

公式ドキュメント Python 言語リファレンス 8. 複合文 (compound statement) 8.7. 関数定義には以下のように書かれています。

関数定義は一つ以上の デコレータ 式でラップできます。デコレータ式は関数を定義するとき、関数定義の入っているスコープで評価されます。その結果は、関数オブジェクトを唯一の引数にとる呼び出し可能オブジェクトでなければなりません。関数オブジェクトの代わりに、返された値が関数名に束縛されます。複数のデコレータはネストして適用されます。例えば、以下のようなコード:

python

1@f1(arg) 2@f2 3def func(): pass

は、だいたい次と等価です

python

1def func(): pass 2func = f1(arg)(f2(func))

ただし、前者のコードでは元々の関数を func という名前へ一時的に束縛することはない、というところを除きます。

これの意味するところは、

python

1@greeting 2def say_name(name): 3 print(f"I'm {name}") 4 5say_name("Jiro")

python

1def say_name2(name): 2 print(f"I'm {name}") 3 4greeting(say_name2)("Jiro")

とほぼ同じであるという意味です。greeting("Jiro")と同じであるという意味ではありません。

投稿2022/01/05 14:38

ppaul

総合スコア24666

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問