Python クラスメソッドとスタティックメソッド

Python学習【365日チャレンジ!】87日目のマスターU(@Udemy11)です。

無性に焼き鳥が食べたいので、自宅で焼き鳥を計画中ですが、串に刺すのが面倒なんですよね。

それに胸肉1枚で10本作れないし、皮は串に刺すときに、指に串を刺してしまいそうで怖いし、砂ずりを触ったときに、指を怪我してたら、めっちゃしみて痛くなるし、などなど結構面倒なんですが、やっぱ自宅で七輪を使って備長炭で焼くと、めっちゃおいしいんですよね。

想像しただけでよだれが出てきます。

といっても計画が実行に移されるかどうかはちょっと微妙なところですが、そのうち自宅焼き鳥を実行したら、お知らせしますね。

そんな報告いりません!と言われる前に、さっそくPython学習をはじめましょう!

昨日の復習

昨日は、クラス変数について学習しました。

文字列などの中身が変化しない変数で、オブジェクト間で共有したいクラス変数は、メソッドの外に記述すれば、クラス変数として扱うことができました。

class Animal:

    kind = 'dog'

    def __init__(self, name):
        self.name = name

    def what_is_it(self):
        print(self.name, self.kind)

a = Animal('A')
a.what_is_it()
b = Animal('B')
b.what_is_it()

出力結果

A dog
B dog

クラス変数にリストなどの値を変更したり、追加したりできるタイプを指定すると、生成したオブジェクト間で共有されるため、オブジェクト間で独立したリストにしたい場合は、__init__の中でクラス変数を定義するということでした。

クラス変数の詳しい内容は、こちらの記事をごらんになってください。

それでは本日のPython学習をすすめましょう!

クラスメソッド

これまで、クラスは設計図で、インスタンス(オブジェクト)は生成物だということを学習しました。

インスタンスを生成するためには、設計図であるクラスのあとにPerenthesesの丸括弧をつけてオブジェクトを生成する必要があります。

丸括弧をつけなければ、オブジェクトになる前のクラスのままなので、クラス内に記述されているメソッドを使うことはできません。

class Animals:

    kind = 'cat'

    def __init__(self):
        self.a = 20

r = Animals()
print(r)
print(r.kind)
l = Animals
print(l)
print(l.kind)

出力結果

<__main__.Animals object at 0x10dc3f3c8>
cat
<class '__main__.Animals'>
cat

8行目では、Animalクラスからオブジェクト化したインスタンスで、11行目は、()がないので、オブジェクト化されていないクラスのままです。

出力結果は、オブジェクト化されたものは、objectに対して、下はclassになっています。

メソッドの外に定義されているクラス変数kindは、どちらからもアクセス可能で、catが出力されています。

この状態から8行目から13行目を次のように変えてみました。

r = Animals()
print(r.a)
l = Animals
print(l.a)

この場合、オブジェクト化したr.a20と出力されますが、11行目は、Animalsクラスのままですので、エラーが起こります。

こんなときに活用するのがクラスメソッドです。

クラスメソッドの使い所

クラスメソッドを使えば、クラスを元にインスタンスを生成せずにメソッドを使うことが可能になります。

class Animals:

    kind = 'cat'

    @classmethod
    def what_is_this(cls):
        return cls.kind

r = Animals()
print(r.what_is_this())

print(Animals.what_is_this())

出力結果

cat
cat

10行目はインスタンスを作って、r.what_is_thisメソッドを使っているので、普通にcatが出力されます。

一方で、12行目のprint(Animals.what_is_this())の場合、クラスから直接メソッドを参照しているので、出力されないかと思いきや、きちんとcatが出力されます。

これがクラスメソッドの特徴ですが、5行目に@classmethodを指定して、6行目と7行目のselfclsに変更します。

この@classmethodを使うことで、オブジェクトを作らなくてもメソッドを使えるようになるということです。

スタティックメソッド

スタティックメソッドも、クラスをインスタンス化しなくても、クラスからメソッドを呼び出すことが可能です。

class Animals:

    kind = 'cat'

    @classmethod
    def what_is_this(cls):
        return cls.kind

    @staticmethod
    def about(country):
        print('about animal {}'.format(country))

Animals.about('Japan')

出力結果

about animal Japan

インスタンスを生成せずに、Animalsクラスからaboutメソッドを呼び出しています。

クラスメソッドと同じく、スタティックメソッドもインスタンスを生成せずに呼び出すことができるというわけですね。

クラス外に記述してもOK

スタティックメソッドの場合、クラスと直接関係していないため、クラスの外に記述することが可能です。

def about(country):
    print('about animal {}'.format(country))

class Animals:

    kind = 'cat'

    @classmethod
    def what_is_this(cls):
        return cls.kind

about('Japan')

出力結果

about animal Japan

クラス内に記述する場合と何が違うかというと、クラスであるAnimalが頭につくかつかないかだけの違いで、Animalに関するメソッドにしたいのなら、クラス内、特になんのつながりも必要ないのなら、クラス外に記述すればいいでしょう。

あまり使われないらしい。

酒井さんの講座では、クラスメソッドは活用場面がそれなりにあるような感じで、スタティックメソッドはそんなに使うことはないらしく、コードで見かけたら、「スタティックメソッドを使っているということだな」程度で覚えておけば大丈夫のようでした。

ここまでいろいろなメソッドや変数などを学習してきましたが、ほんとどんどん難しくなるので、脱落してしまいそうになるのですが、ここでやめたら、間違いなく後悔だけしか残らないので、しっかりと継続して学習していこうと気を引き締めました。

それでは、明日もGood Python!