LoginSignup
20
20

More than 5 years have passed since last update.

Pythonで複数のイニシャライザを定義する

Last updated at Posted at 2016-05-07

@singledispatchでできるかと思えば、第一引数の型でしか割当出来ない仕様なので、第一引数がselfの__init__には使えない

結論

僕がPython慣れてないだけだけだった
defaultValueを使えばいい

#coding: utf-8

class Pokemon(object):
    def __init__(self, id=25, name="ピカチュウ"):
        self._id = id
        self._name = name
    def __str__(self):
        return "Pokemon<{0._id}, {0._name}>".format(self)

pika = Pokemon()
print(pika)

mew = Pokemon(151, "ミュウ")
print(mew)

Pokemon<25, ピカチュウ>
Pokemon<151, ミュウ>

Python慣れないなあ・・・

でも

パラメータごとなら受け取れるけど、例えば他のクラスのインスタンス受け取ってでも初期化、みたいにしたかったらかなり面倒になる
他の値を捨てる感じ。

#coding: utf-8

class Zukan(object):
    def __init__(self, page_id, title):
        self._page_id = page_id
        self._title = title

class Pokemon(object):
    def __init__(self, id=25, name="ピカチュウ", zukan=None):
        if zukan:
            self._id = zukan._page_id
            self._name = zukan._title
        else:
            self._id = id
            self._name = name
    def __str__(self):
        return "Pokemon<{0._id}, {0._name}>".format(self)

pika = Pokemon()
print(pika)

mew = Pokemon(151, "ミュウ")
print(mew)

mew2 = Pokemon(zukan=Zukan(150, "ミュウツー"))
print(mew2)

Pokemon<25, ピカチュウ>
Pokemon<151, ミュウ>
Pokemon<150, ミュウツー>

こんな感じかなあ

あえて全ての引数のデフォルト値をNoneにしておいて、イニシャライズ時に引数名を必ず書くような規約にしても良いかもしれない

of(Java風に)

上のやつみたいにするなら、わざわざイニシャライザでディスパッチしなくてもいい感ある
たとえばOptional.ofとか、ImmutableMap.of()
みたいな感じで、builderメソッドを追加したほうがキレイかもしれない

#coding: utf-8

class Zukan(object):
    def __init__(self, page_id, title):
        self._page_id = page_id
        self._title = title

class Pokemon(object):
    def __init__(self, id=25, name="ピカチュウ"):
        self._id = id
        self._name = name
    def __str__(self):
        return "Pokemon<{0._id}, {0._name}>".format(self)
    @staticmethod
    def createFromZukan(zukan):
        instance = Pokemon(zukan._page_id, zukan._title)
        return instance

pika = Pokemon()
print(pika)

mew = Pokemon(151, "ミュウ")
print(mew)

mew2 = Pokemon.createFromZukan(Zukan(150, "ミュウツー"))
print(mew2)

サブクラスにする

コメントで、サブクラスにする、という手段も教えていただきました。

class Rect(object):
    def __init__(self, x, y, width, height):
        self.x, self.y, self.width, self.height = x, y, width, height
    def __str__(self):
        return '(%s, %s, %s, %s)' % (self.x, self.y, self.width, self.height)
    def __repr__(self):
        return 'Rect(%s, %s, %s, %s)' % (self.x, self.y, self.width, self.height)

class RectOfPointSize(Rect):
    def __init__(self, point, size):
        super(RectOfPointSize, self).__init__(point.x, point.y, size.width, size.height)
    def __repr__(self):
        return 'RectOfPointSize(Point(%s, %s), Size(%s, %s))' % (self.x, self.y, self.width, self.height)

class RectOfPointPoint(Rect):
    def __init__(self, point, size):
        super(RectOfPointPoint, self).__init__(point.x, point.y, size.x, size.y)
    def __repr__(self):
        return 'RectOfPointPoint(Point(%s, %s), Point(%s, %s))' % (self.x, self.y, self.width, self.height)

class Object(object): pass

point = Object()
point.x = 5
point.y = 6
size = Object()
size.width = 7
size.height = 8

r1 = Rect(1, 2, 3, 4)
r2 = RectOfPointSize(point, size)
r3 = RectOfPointPoint(point, point)

print r1, r2, r3
print repr(r1), repr(r2), repr(r3)

基底クラスはprivateか何かにおいて、サブクラスのみを使うのも、特に生成のあたりの可読性が高いのでこれもいいですね

その他

ディクショナリから作るなら

引数にするときに、ディクショナリをタプルに展開してイニシャライザ引数に渡すのもキレイ

おわりに

趣味の世界になってきた

もっと良い実装あれば教えて下さい

20
20
3

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
20
20