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

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

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

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

Python

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

Q&A

解決済

1回答

800閲覧

メタクラスにおける__new__()の返り値はtype型、object型のどちらですか。

0ipanema0

総合スコア15

Python 3.x

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

Python

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

0グッド

0クリップ

投稿2019/06/21 09:05

#####はじめに
pythonを勉強中のものです。
メタクラスの動作がよくわかりません。
不明点を以下にまとめました。
ご教示いただけますと嬉しいです。

#####不明点
0. メタクラスは type明記して継承しなければいけないそうですががなぜですか。objectを明記して継承させる場合や、何も明記しない場合とどこが違うのでしょうか。
*明記... class A(type): の(type)のこと

  1. type型とobject型の違い(どちらがどちらのスーパークラスか)もよくわかりません。全ての型がtype型のサブクラスだということは知っています。

  2. b.bの値をインスタンス作成時の任意値にしたいのですがどうすればいいですか。

インスタンス作成、b = B(任意値)とした時b.b = 任意値としたいです。以下のコードだとエラーとなってしまいます。

Python

1TypeError: B() takes no arguments

メタクラスの勉強をしているのでclass Bのメタクラスは必ずclass Aでお願いします。

前提のコード

Python

1class A(type): 2 def __new__(cls, *args): 3 print("Called A's __new__!") 4 _s = type.__new__(cls, *args) 5 _s.a = "This is A's attr" 6 return _s 7 def __init__(self, *args): 8 print("Called A's __init__!") 9 self.b = args[1] 10 11class B(metaclass=A): 12 pass 13 14 15b = B() 16print(b.a,b.b, sep="\n")

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

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

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

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

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

quickquip

2019/06/21 13:25

初心者マークは外した方がいいんじゃないでしょうか? (Pythonの中でもとりわけ難しい話題でしょう)
guest

回答1

0

ベストアンサー

メタクラスは typeを明記して継承しなければいけないそうですががなぜですか。objectを明記して継承させる場合や、何も明記しない場合とどこが違うのでしょうか。

*明記... class A(type): の(type)のこと

よくある普通のクラスはtypeのインスタンスです。typeを継承するとメタクラスが作れます。class B(metaclass=A):のような記述は、BクラスそのものをAのインスタンスとして作りますよ、ということを表します。

python

1>>> class Hoge: 2... pass 3... 4>>> class Fuga(type): 5... pass 6... 7>>> class Piyo(metaclass=Fuga): 8... pass 9... 10>>> type(Hoge) 11<class 'type'> 12>>> type(Fuga) 13<class 'type'> 14>>> type(Piyo) 15<class '__main__.Fuga'>

Piyoだけ型が違いますね。これがメタクラスの機能です。

type型とobject型の違い(どちらがどちらのスーパークラスか)もよくわかりません。全ての型がtype型のサブクラスだということは知っています。

objectがpython3の世界の最上位クラスです。typeobjectのサブクラスです。

python

1>>> object.__bases__ 2() 3>>> type.__bases__ 4(<class 'object'>,)

でも、これは約束事だし、知っておいてもそんなにメリットはないかもしれません。

b.bの値をインスタンス作成時の任意値にしたいのですがどうすればいいですか。

インスタンス作成、b = B(任意値)とした時b.b = 任意値としたいです。以下のコードだとエラーとなってしまいます。

まずメタクラスはあくまでもクラスの拡張ですから、

python

1class A(type): 2 def __new__(cls, *args): 3 print("Called A's __new__!") 4 _s = type.__new__(cls, *args) 5 _s.a = "This is A's attr" 6 return _s 7 def __init__(self, *args): 8 print("Called A's __init__!") 9 self.b = args[1] 10 11print("def B") 12class B(metaclass=A): 13 pass 14print("end of def B") 15 16b = B() 17print(b.a,b.b, sep="\n") 18""" => 19def B 20Called A's __new__! 21Called A's __init__! 22end of def B 23This is A's attr 24() 25"""

という動作になることを理解しておかないといけないのです。A__init__で行っている操作というのは、たとえば

python

1class A(type): 2 def __new__(cls, *args): 3 print("Called A's __new__!") 4 _s = type.__new__(cls, *args) 5 _s.a = "This is A's attr" 6 return _s 7 def __init__(self, *args): 8 print("Called A's __init__!") 9 self.b = args[1] 10 11class B(int, metaclass=A): 12 pass 13 14b = B() 15print(b.a,b.b, sep="\n") 16""" => 17Called A's __new__! 18Called A's __init__! 19This is A's attr 20(<class 'int'>,) 21"""

こういう操作を可能にする(ここではB定義時に引数を受け取っている)、ということなのです。どの段階で何を受け取るのかを注意してください。

質問文のやりたいことはインスタンスをいじりたいということなので、たぶん普通のクラスの継承でやった方がいいのですが。どうしてもやるなら、

python

1class A(type): 2 def __init__(self, *args): 3 def init(self, arg): 4 self.b = arg 5 self.__init__ = init 6 7class B(metaclass=A): 8 pass 9 10b = B("hoge") 11print(b.b) # => hoge

という感じでしょうか。Aをメタクラスにするクラスの__init__はすべてデフォルトで任意値を一つ引数に取り、それをbという属性に束縛するという動作になります。

投稿2019/06/21 13:36

編集2019/06/21 16:12
hayataka2049

総合スコア30933

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

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

0ipanema0

2019/06/23 15:16

@hayataka2049さん ご回答ありがとうございます。疑問が解けました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問