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

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

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

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

Q&A

解決済

2回答

981閲覧

クラスを使ったリストの並び替えについて

bbettbn

総合スコア15

Python

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

0グッド

0クリップ

投稿2018/07/22 01:05

Humanというクラスを作り、そのクラスを使い、humansというリストを作りました。
humansリストからageに沿って並び替えをしたいというプログラムです。
並び替えのため、sorted関数を使いました。

class Human(): def __init__(self,age,name,gender): self.age = age self.name = name self.gender = gender human1 = Human(22,"mori","男") human2 = Human(20,"moriyama","男") human3 = Human(21,"moji","女") humans = [human1,human2,human3] result = sorted(humans, key=lambda t:t[0]) print(result)

エラーメッセージは以下の通りです。

Traceback (most recent call last): File "/home/ec2-user/environment/class_test.py", line 11, in <module> humanss = sorted(humans, key=lambda t:t[0]) File "/home/ec2-user/environment/class_test.py", line 11, in <lambda> humanss = sorted(humans, key=lambda t:t[0]) TypeError: 'Human' object does not support indexing

どうしてエラーになるのかを教えてください。また、sorted関数を使うときにkey=lambdaを使うとよいと知りましたが、key=lambdaのメカニズムは、tとしてhumansを引数にとり、humans[0]として、一つ目の要素、今回で言えばageを取り出すという理解でよいのでしょうか。
よろしくお願いします。

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

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

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

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

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

guest

回答2

0

ベストアンサー

Humanクラスはlistやtupleなどではないので、[0]といった形式で属性にアクセスすることは出来ません。

エラーを出さないためには、こう書く必要があります。

python

1class Human(): 2 def __init__(self,age,name,gender): 3 self.age = age 4 self.name = name 5 self.gender = gender 6 7human1 = Human(22,"mori","男") 8human2 = Human(20,"moriyama","男") 9human3 = Human(21,"moji","女") 10humans = [human1,human2,human3] 11result = sorted(humans, key=lambda t:t.age) 12print(result)

key=lambdaのメカニズム

キーワード引数keyに、ソート対象の要素から値を取り出すような関数を渡す必要があります。今回はlambda t:t.ageを渡せば用を達します。

投稿2018/07/22 01:13

編集2018/07/22 01:13
hayataka2049

総合スコア30933

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

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

bbettbn

2018/07/22 01:31

ありがとうございます。 エラーはなくなりました。 ただ、 [<__main__.Human object at 0x7f74b8cd5128>, <__main__.Human object at 0x7f74b8cd5160>, <__main__.Human object at 0x7f74b8cd50b8>] のように出力されます。何が原因でしょうか。
hayataka2049

2018/07/22 01:36

「__main__という名前空間で定義されているHumanクラスのオブジェクトですよ」というような意味の表示で、それで正常な表示です。 実際、human1などをそれぞれprintしてもそう見えるはずで。 適当なフォーマットで見えてほしければ、__repr__メソッドを定義してあげてください(検索すればその辺の話は出てくると思います)
bbettbn

2018/07/22 02:03

def __repr__(self): return repr((self.age,self.name,self.gender)) とすることで文字と数値で出力されました。ありがとうございました。 もしこのクラスにプロパティを利用するならば、以下のようなコードになるかと思いましたが、エラーでした。何が原因でしょうか。 ``` class Human(): def __init__(self,age,name,gender): self.__data=["age","name","gender"] @property def age(self): return self.__data[age] @property def name(self): return self.__data[name] @property def gender(self): return self.__data[gender] def __repr__(self): return repr((self.age,self.name,self.gender)) human1 = Human(22,"mori","男") human2 = Human(20,"moriyama","男") human3 = Human(21,"moji","女") humans = [human1,human2,human3] result = sorted(humans, key=lambda t:t.age) print(result) ```
hayataka2049

2018/07/22 02:09

__init__は受け取った引数をネグレクトして"age", "name", "gender"の文字列のリストなんかをself.__dataに代入していますし、プロパティ使うにしてもself.__data[age]とかはage等がメソッド内では未定義だろうし、そもそもリストにアクセスするなら整数渡してあげないといけないし
hayataka2049

2018/07/22 02:12 編集

コードから「プログラミングの基本的な考え方に慣れていない人が書いたような臭い」がするので、とりあえず力に余ることはしないで、簡単な書き方をして慣れていけば良いのではないでしょうか
bbettbn

2018/07/22 02:19

回答ありがとうございます。 おっしゃる通り、まだプログラミングを始めたばかりです。classの考え方には特に慣れていません。 ただ、課題として出されているので、何としても完成させたいと思っています。 もう少し考えてみるので、またお願いします。
hayataka2049

2018/07/22 02:25

課題ですか。頑張ってくださいね
bbettbn

2018/07/22 02:25

きちんと出力されますが、これはpropetyになってますか? 見づらいでしょうが、よろしくお願いします。 class Human(): def __init__(self,age,name,gender): self.__data={"age":age,"name":name,"gender":gender} @property def age(self): return self.__data["age"] @property def name(self): return self.__data["name"] @property def gender(self): return self.__data["gender"] def __repr__(self): return repr((self.age,self.name,self.gender)) human1 = Human(22,"mori","男") human2 = Human(20,"moriyama","男") human3 = Human(21,"moji","女") humans = [human1,human2,human3] result = sorted(humans, reverse=True, key=lambda t:t.age) print(result)
hayataka2049

2018/07/22 02:36

基本的にはそれでよさそうです。 プロパティはsetterとdeleterを書いた方が気分的には安心できます。 あと、__repr__の返す文字列は"Human(22,'mori','男')"のような、コードとして評価すると元のオブジェクトに戻るようなフォーマットにするのが一般的な作法とされています。
bbettbn

2018/07/22 02:51

ありがとうございます。セッター関数も追加しました。 参考書片手に書いただけですので、意味は分かりません。 セッター関数を使うと、ゲッター関数だけのときに比べてどのようなメリットがあるのでしょうか。 また、基本的にプロパティを使うときは、辞書を初期化メソッドで定義してから使うことが多いのでしょうか。 フォーマットのついてのご指摘ありがとうございます。 どうしたらその位置でHumanが出力されますか。 class Human(): def __init__(self,age,name,gender): self.__data={"age":age,"name":name,"gender":gender} @property def age(self): return self.__data["age"] @age.setter def age(self,value): self.__data["age"]=value @property def name(self): return self.__data["name"] @name.setter def name(self,value): self.__data["name"]=value @property def gender(self): return self.__data["gender"] @gender.setter def gender(self,value): self.__data["gender"]=value def __repr__(self): return repr((self.age,self.name,self.gender)) human1 = Human(22,"mori","男") human2 = Human(20,"moriyama","男") human3 = Human(21,"moji","女") humans = [human1,human2,human3] result = sorted(humans, reverse=True, key=lambda t:t.age) print(result)
hayataka2049

2018/07/22 02:57

setter、deleterがないと、後からその属性に代入、削除できません。できなくても良いなら書かなくて良いので、「気分的には安心できます」と書きました。ちょっとわかりづらかったですね フォーマットに関しては、 return "Human({0}, '{1}', '{2}')".format(self.age,self.name,self.gender) みたいな感じでどうですか
bbettbn

2018/07/22 03:19

そうなんですね。 フォーマットの件もありがとうございました。 今回、回答を継続して頂いたおかげでとても勉強になりました! 本当に助かりました。 またよろしくお願いします。
guest

0

単に値を格納することが主目的なら、collections.namedtupleが便利です。

Python

1from collections import namedtuple 2 3Human = namedtuple('Human', ['age', 'name', 'gender']) 4 5human1 = Human(22, "mori", "男") 6human2 = Human(20, "moriyama", "男") 7human3 = Human(21, "moji", "女") 8humans = [human1, human2, human3] 9 10result = sorted(humans, key=lambda h: h[0]) # operators.itemgetterを使っても良い 11print(result)

ただし今後クラスを拡張していく場合は、普通のクラスを用いた方が良いでしょう。
Python3.7以降ならdataclassesを使ってみるのもアリです。

投稿2018/07/22 01:21

編集2018/07/22 01:34
LouiS0616

総合スコア35660

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

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

bbettbn

2018/07/22 01:31

そのモジュールは知りませんでした。 ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問