LoginSignup
14
12

More than 3 years have passed since last update.

【Python】二通りのtype()の使い方

Last updated at Posted at 2020-02-02

はじめに

業務でDjangoのManager周りのコードを読んでいると
見慣れないtype()の使い方を見つけました。

GitHubのリンクはこちら


@classmethod
def from_queryset(cls, queryset_class, class_name=None):
    if class_name is None:
        class_name = '%sFrom%s' % (cls.__name__, queryset_class.__name__)
    return type(class_name, (cls,), {
        '_queryset_class': queryset_class,
        **cls._get_queryset_methods(queryset_class),
    })

typeに引数が三つ渡されている...???
なんだこれ?

調べてみた所、ちゃんとPython標準ライブラリのドキュメントに書いてありました。
(そりゃそう)

ほとんど引用に近い形にはなりますが、軽くまとめてみることにします。

結論

type()は引数の数によって挙動が変わる。


1.(恐らく)よくある使い方

引数が1つだけの場合、object の型を返します。返り値は型オブジェクトで、一般に object.class によって返されるのと同じオブジェクトです。(Pythonドキュメントより引用)


>>> class Bar:
...     pass

>>> class Foo(Bar):
...     pass

class Barとこれを継承したclass Fooを用意します。

この時type()の挙動は以下のようになります。

>>> foo = Foo()
>>> type(foo)
<class '__main__.Foo'>

>>> type(foo) is Foo
True

>>> type(foo) is Bar
False

場合によってisinstance()と使い分けましょう。

というのが自分の知っている話でした。

2.知らなかった使い方

class type(name, bases, dict)

引数が 3 つの場合、新しい型オブジェクトを返します。本質的には class 文の動的な形式です。
(Pythonドキュメントより引用)

ドキュメントでは以下の二つの文は同じtypeオブジェクトを作ると書かれています。


>>> class X:
...     a = 1

>>> X = type('X', (object,), dict(a=1))

第一引数: 生成するクラス名
第二引数: 継承するクラス
第三引数: オブジェクトの属性

となっています。

実際に試してみます。


>>> class Bar:
...     a=1
...
...     def print_hogefuga(self):
...         print('hogefuga')
...

>>> Foo = type('Foo', (Bar,), dict(b=2))

>>> foo = Foo()
>>> foo.print_hogefuga()
hogefuga
>>> foo.a
1
>>> foo.b
2

このようにBarClassを継承するFooClassを作ることが出来ました。

まとめ

以上、自分が知らなかったtype()の使い方についてでした。

type()以外にも驚きの使い方のものはたくさんありそうですね。

参考・引用

14
12
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
12