pythonのstaticmethodとclassmethod実装インスタンスコード
5910 ワード
本稿は,pythonのstaticmethod()というbuiltin手法の実現を明らかにしたいという好奇心から,いくつかの資料(主にpython公式マニュアル)を調べてここに集めた.
pythonクラスでは、methodを呼び出す方法は3つあります.普通のmethod、staticmethod、classmethodの2つはよく理解できるはずです.classmethodは、この関数を呼び出すときに、呼び出されたオブジェクトのclass objectオブジェクトを暗黙的に転送します.あれ?このclass objectはタイプではありませんか?No、pythonではclass objectは静的言語のようにタイプではなく、仮想マシンではオブジェクトです.普通のmethod呼び出しは自分のselfをパラメータとして渡す必要があり、初心者の頃はどうしても理解できませんでしたが、見すぎると自然に慣れてしまいます.不思議なことにstaticmethodとclassmethodは静的言語のようにキーワード定義を保持するのではなく、
前にjavaを使ったことがあるので、最初の反応はannotationですが...うーん、確かにAOPのようなもので、pythonではdecoratorと呼ばれています.もし私たちが自分でstaticmethodを実現するなら、どう書きますか?
公式のコードを研究して、私はまた変更して、このように書くべきだと感じました.
出力結果は次のとおりです.
__init__() called ins = <__main__.class1 object=""at="">, Class1 = __get__() called INFO: self = <__main__.staticmethod object=""at="">, instance =<__main__.class1 object=""at="">, owner = __get__() called INFO: self = <__main__.staticmethod object=""at="">, instance =None, owner = ins.method = , Class1.method = __get__() called INFO: self = <__main__.staticmethod object=""at="">, instance =<__main__.class1 object=""at="">, owner = abc __get__() called INFO: self = <__main__.staticmethod object=""at="">, instance =None, owner = xyz
ええ、すべて順調に見えます.Class 1には変数methodが含まれていますが、このmethodも特殊に処理されたStaticMethodクラスです.このクラスには
はい、ではclassmethodはどのように実現しますか?
出力結果は次のとおりです.
ClassMethod: __init__() called __get__() called INFO: self = <__main__.classmethod object=""at="">, instance =<__main__.class2 object=""at="">, owner = __get__() called INFO: self = <__main__.classmethod object=""at="">, instance =None, owner = __get__() called INFO: self = <__main__.classmethod object=""at="">, instance =None, owner = ins.method = , Class2.method = , Class21.method = __get__() called INFO: self = <__main__.classmethod object=""at="">, instance =<__main__.class2 object=""at="">, owner = I'm tmpfunc foo2's class = abc __get__() called INFO: self = <__main__.classmethod object=""at="">, instance =None, owner = I'm tmpfunc foo2's class = xyz __get__() called INFO: self = <__main__.classmethod object=""at="">, instance =None, owner = I'm tmpfunc foo2's class = asdf
classmethodとstaticmethodの実現方法は大同小異であることがわかる.staticmethodは比較的簡単でselfに直接戻る.f変数でよいがclassmethodではだめで,呼び出し時のclassタイプ情報をfoo 2関数に伝達する必要があり,この関数は受信したclass情報に基づいて異なる作業を行う.(でも今は何に使えるか考えていません)
注意すべき点があります.同志たちもさっき考えたかもしれませんが、私は必ずtempfuncを定義して、それに戻ってから仕事を完成しなければなりませんか.なくてもいいですか
直接1つ戻ります
もちろん、もし友達が成功したら、必ずXDを教えてください.
小結:staticmethodとclassmethodの実現は難しくないようですが、
まとめ
以上、pythonのstaticmethodとclassmethod実装インスタンスコードについてすべて説明したので、皆さんの役に立つことを願っています.興味のある方は引き続き当駅の他の関連テーマを参照することができます.不足点があれば、伝言を歓迎します.友达の本駅に対する支持に感谢します!
pythonクラスでは、methodを呼び出す方法は3つあります.普通のmethod、staticmethod、classmethodの2つはよく理解できるはずです.classmethodは、この関数を呼び出すときに、呼び出されたオブジェクトのclass objectオブジェクトを暗黙的に転送します.あれ?このclass objectはタイプではありませんか?No、pythonではclass objectは静的言語のようにタイプではなく、仮想マシンではオブジェクトです.普通のmethod呼び出しは自分のselfをパラメータとして渡す必要があり、初心者の頃はどうしても理解できませんでしたが、見すぎると自然に慣れてしまいます.不思議なことにstaticmethodとclassmethodは静的言語のようにキーワード定義を保持するのではなく、
@staticmethod
またはstaticmethod()
というbuiltin関数を使用して定義されます.この@staticmethod
はいったい何ですか.
@staticmethod
def foo(x):
print(x)
前にjavaを使ったことがあるので、最初の反応はannotationですが...うーん、確かにAOPのようなもので、pythonではdecoratorと呼ばれています.もし私たちが自分でstaticmethodを実現するなら、どう書きますか?
公式のコードを研究して、私はまた変更して、このように書くべきだと感じました.
def foo(x):
print(x)
class StaticMethod(object):
def __init__(self, function):
print("__init__() called")
self.f = function
def __get__(self, instance, owner):
print("\t__get__() called")
print("\tINFO: self = %s, instance =%s, owner = %s" % (self, instance, owner))
return self.f
class Class1(object):
method = StaticMethod(foo)
if __name__ == '__main__':
ins = Class1()
print("ins = %s, Class1 = %s" % (ins, Class1))
print("ins.method = %s, Class1.method = %s" % (ins.method, Class1.method))
ins.method('abc')
Class1.method('xyz')
出力結果は次のとおりです.
__init__() called ins = <__main__.class1 object=""at="">, Class1 = __get__() called INFO: self = <__main__.staticmethod object=""at="">, instance =<__main__.class1 object=""at="">, owner = __get__() called INFO: self = <__main__.staticmethod object=""at="">, instance =None, owner = ins.method = , Class1.method = __get__() called INFO: self = <__main__.staticmethod object=""at="">, instance =<__main__.class1 object=""at="">, owner = abc __get__() called INFO: self = <__main__.staticmethod object=""at="">, instance =None, owner = xyz
ええ、すべて順調に見えます.Class 1には変数methodが含まれていますが、このmethodも特殊に処理されたStaticMethodクラスです.このクラスには
__get__
関数があり、クラスが「get」されたときにアクセスされると、アクセス者のinstanceとclass情報がデフォルトで送信されます.だからmethod()という関数を呼び出すかどうかにかかわらず、methodにぶつかると、この関数がトリガーされ、現在のinstanceとclass情報が印刷されるのを見ました.insとClass 1のinstanceはそれぞれ異なりますが、__get__
の関数ではfoo関数を返すだけなので、ここでmethodを呼び出すときは区別なく、同じfunctionオブジェクトを呼び出すことになります.はい、ではclassmethodはどのように実現しますか?
def foo2(cls, x):
print("foo2's class = ", cls)
print(x)
class ClassMethod(object):
def __init__(self, function):
print("ClassMethod: __init__() called")
self.f = function
def __get__(self, instance, owner = None):
print("\t__get__() called")
print("\tINFO: self = %s, instance =%s, owner = %s" % (self, instance, owner))
def tmpfunc(x):
print("I'm tmpfunc")
return self.f(owner, x)
return tmpfunc
class Class2(object):
method = ClassMethod(foo2)
class Class21(Class2):
pass
if __name__ == '__main__':
ins = Class2()
print("ins.method = %s, Class2.method = %s, Class21.method = %s" % (ins.method, Class2.method, Class21.method))
ins.method('abc')
Class2.method('xyz')
Class21.method('asdf')
出力結果は次のとおりです.
ClassMethod: __init__() called __get__() called INFO: self = <__main__.classmethod object=""at="">, instance =<__main__.class2 object=""at="">, owner = __get__() called INFO: self = <__main__.classmethod object=""at="">, instance =None, owner = __get__() called INFO: self = <__main__.classmethod object=""at="">, instance =None, owner = ins.method = , Class2.method = , Class21.method = __get__() called INFO: self = <__main__.classmethod object=""at="">, instance =<__main__.class2 object=""at="">, owner = I'm tmpfunc foo2's class = abc __get__() called INFO: self = <__main__.classmethod object=""at="">, instance =None, owner = I'm tmpfunc foo2's class = xyz __get__() called INFO: self = <__main__.classmethod object=""at="">, instance =None, owner = I'm tmpfunc foo2's class = asdf
classmethodとstaticmethodの実現方法は大同小異であることがわかる.staticmethodは比較的簡単でselfに直接戻る.f変数でよいがclassmethodではだめで,呼び出し時のclassタイプ情報をfoo 2関数に伝達する必要があり,この関数は受信したclass情報に基づいて異なる作業を行う.(でも今は何に使えるか考えていません)
注意すべき点があります.同志たちもさっき考えたかもしれませんが、私は必ずtempfuncを定義して、それに戻ってから仕事を完成しなければなりませんか.なくてもいいですか
def tmpfunc(x):
print("I'm tmpfunc")
return self.f(owner, x)
return tmpfunc
直接1つ戻ります
return self.f(owner, *args)
__get__
が呼び出されたとき、まだパラメータが伝わっていなかったので、argsのデフォルトパラメータを直接伝えてはいけません.Class2.method('xyz')
のパラメータは、return tmpfuncの後にのみtmpfuncに掛けられる.もちろん、もし友達が成功したら、必ずXDを教えてください.
小結:staticmethodとclassmethodの実現は難しくないようですが、
__get__
関数のおかげです.前にも__get__
が呼び出されたときにinstanceとclassの情報を記入するという話がありましたが、助かりました.しかし、この__get__
関数はいったいどういうことなのか.どうしてそんなに不思議なの?Python中_を参考にしてみてくださいget__および_getattr__および_getattribute__の違いまとめ
以上、pythonのstaticmethodとclassmethod実装インスタンスコードについてすべて説明したので、皆さんの役に立つことを願っています.興味のある方は引き続き当駅の他の関連テーマを参照することができます.不足点があれば、伝言を歓迎します.友达の本駅に対する支持に感谢します!