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

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

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

Jupyter (旧IPython notebook)は、Notebook形式でドキュメント作成し、プログラムの記述・実行、その実行結果を記録するツールです。メモの作成や保存、共有、確認などもブラウザ上で行うことができます。

Python 3.x

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

Python

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

Q&A

解決済

3回答

2707閲覧

pythonの内包表記について

yu__

総合スコア108

Jupyter

Jupyter (旧IPython notebook)は、Notebook形式でドキュメント作成し、プログラムの記述・実行、その実行結果を記録するツールです。メモの作成や保存、共有、確認などもブラウザ上で行うことができます。

Python 3.x

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

Python

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

1グッド

1クリップ

投稿2019/03/02 04:39

pythonの内包表記について

リスト内の同様の要素を削除するために以下のサイトを参考に以下の内包表記を実行しました。
https://note.nkmk.me/python-list-unique-duplicate/

python

1def get_unique_list(seq): 2 seen = [] 3 return [x for x in seq if x not in seen and not seen.append(x)] 4a = [1,1,1,2,2,3,4,5,6,6,6,7] 5print(get_unique_list(a))

結果

[1, 2, 3, 4, 5, 6, 7]

しかし私は以下のコードではないと理解できません。

python

1def get_unique_list1(seq): 2 seen = [] 3 [x for x in seq if x not in seen and seen.append(x)] 4 return seen 5a = [1,1,1,2,2,3,4,5,6,6,6,7]

結果

[1, 2, 3, 4, 5, 6, 7]

結果は一つ目のコードと二つ目は同じなのですが、
and notを使うかandを使うかという点が違います。
x not in seen and not seen.append(x)の部分を簡単に
A and not Bと置いて考えていくとseenは最初は空の配列なので、
Aは必ず論理を満たします。その後、not seen.append(x)の部分ですが
これはAを満たしたときのみ実行できると考えるとnot seen.append(x)
何もしていないと考えられます。それゆえにseenは空の配列のままです。
それゆえにseenが常に空であればAは必ず論理を満たします。
それゆえに結果は[1,1,1,2,2,3,4,5,6,6,6,7]になるように思えて仕方ありません。
私の考え方のおかしい部分を分かりやすく訂正していただけると幸いです。
よろしくお願いします。

kankan0👍を押しています

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

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

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

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

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

guest

回答3

0

質問の上の方のコードはseenを捨てて、内包表記の結果を返しています。
質問の下の方のコードは内包表記の結果を捨てて、seenを返しています。

seenというリストと、内包表記の結果のリストの役割が逆なのです。

質問の上の方のコードはifの条件がand not seen.append(x)であることが必須です。内包評価の結果を使うのでこれを逆にするとうまく動きません。

それに対して、質問の下の方のコードはifの条件がand not seen.append(x)でもand seen.append(x)でも動きます。内包表記の結果を捨てているのだからどっちでも動きます。


以下蛇足

seen = [] print(seen.append(1)) print(seen)

結果

None 1

seen = [] print(not seen.append(1)) print(seen)

結果

True 1

投稿2019/03/02 06:06

編集2019/03/02 06:07
quickquip

総合スコア11038

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

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

0

ベストアンサー

seenは最初は空の配列なので、

Aは必ず論理を満たします。その後、not seen.append(x)の部分ですが
これはAを満たしたときのみ実行できると考える

論理を満たすという言い方はどうかと思いますが(Aが真になるとかでいいのでは)、ここまでは正しい理解でしょう。

not seen.append(x)は何もしていないと考えられます。

Aが「seenにはxが含まれない」であることを忘れているか、not seen.append(x)が「seenにappendしない」という意味と誤解しているかのどちらかだと思います。

notはあくまでも真理値を反転するだけで、後ろの式は評価されます。「含まれていなかったら追加する」「含まれていたら追加しないで終わる」という処理なので、普通に理解できるのでは?

andでつなぐ都合上、seen.append(x)がTrueになってくれないとリスト内包表記の方のifの条件がTrueにならなくて空のリストが返ってしまうので、notで反転しているだけです。

投稿2019/03/02 05:03

編集2019/03/02 05:20
hayataka2049

総合スコア30933

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

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

KSwordOfHaste

2019/03/02 05:11

「満たす」と表現するなら「A(という論理)」ではなく「A(という命題)」のほうがしっくりきます。でもそもそもAは文脈から「命題」であることは明らかなのでhayataka2049さんコメントのとおり「Aが真になる」ないしは「Aを満たす」が自然に感じました。
hayataka2049

2019/03/02 05:17 編集

一般的に「○○は論理を満たす」という表現は使わないという日本語の話のつもりで書きました。あまり深い意図はなかったです。Aが真になる、Aを満たすはどちらでも良いと思います。 改めて考えてみて、今回はpythonの式なので、プログラミング言語のレイヤで話すことにして「AはTrueになる」と書くのが一番かもしれない・・と思いました。
KSwordOfHaste

2019/03/02 05:26

自分も日本語の話のつもりでhayataka2049さんが感じたであろう違和感を質問者さんに対して「なぜ違和感を感じるか」を述べようとしたつもりでした。蛇足だったかもです。
yu__

2019/03/02 06:04

よい表現が見つからず申し訳ありません。任意のxが集合seenの要素ではないという命題を満たすという表現が正しいです。プログラミング言語のレイヤで話すことにして「AはTrueになる」と書くのが一番であるという考え理解しました。 not seen.append(x)が「seenにappendしない」という意味と誤解しています。 私はseen.append(x)はseenにxという配列を加えるもので、真理値を返すという考えが分かりません。 もしよかったら教えて頂けると恐縮です。
hayataka2049

2019/03/02 06:12

pythonの言語仕様では、関数・メソッドなどの呼び出しは「式」といって、何らかの値が必ず返ることになっています。余談ですが、他の「式」には変数名とかリテラルとか四則演算など、様々なものがあります。また、「式」の他には「文」があり、ifとかdefとかreturnなどが該当します。「文」は返り値を持たないというか、そもそも代入文の右辺とかリストの中とか、あらゆる「式」が想定される場所には書けないという性質があります。 話がそれましたが、appendもメソッドで呼び出せば「式」になるので、返り値があります。といっても、appendの返り値なんて要りませんから、Noneというものを返す、という仕様になっています(ちなみにreturn文のない関数を書いてもNoneが返ります)。 pythonではすべてのオブジェクトはbool型に変換できます。bool(None)はFalseです。なので、これをTrueにするためだけにnotが要るのです。
yu__

2019/03/03 03:18

理解しました。seen.append(x)の常に返り値がNone(つまり集合の要素がないような集合)にしておくことによってseenにはxを常に加えることができるがnot seen.append(x)をTrueにすることができるということなのですね。非常に分かりやすかったです。ベストアンサーにさせていただきました。
hayataka2049

2019/03/03 03:26 編集

Noneは別にそこまで深い意味(つまり集合の要素がないような集合)は持ちません。意味がない値というものを表すためにNoneという値が用意されているだけです。
guest

0

1番目のコードでは、配列内包をやっている配列の外側にreturnがついています。そして、list.append()Noneを返しますので、それをnotで否定することで、「list.append()を行ったもの」だけがtrueとなります。

Pythonのand短絡評価ですので(リファレンス)、x not in seenが成立しない場合にはnot seen.append(x)は評価されません。

投稿2019/03/02 04:51

maisumakun

総合スコア145184

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

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

maisumakun

2019/03/02 04:54

「これはAを満たしたときのみ実行できると考えるとnot seen.append(x)は何もしていない」という理屈はどのように導かれたものでしょうか。
yu__

2019/03/02 06:06

根本概念が違っていました。 私の考えではseen.append(x)はseenにxという配列を加えるもので、真理値を返すという考えがなかったです。 しかし、list.append()はNoneを返しますという理由が未だに分かりません。もしよかったら、教えて頂けると恐縮です。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問