Python でメソッドの実装を要求するにはどうすればよいですか?
-
04-10-2019 - |
質問
Pythonでダックタイピングを使用しています。
def flagItem(object_to_flag, account_flagging, flag_type, is_flagged):
if flag_type == Flags.OFFENSIVE:
object_to_flag.is_offensive=is_flagged
elif flag_type == Flags.SPAM:
object_to_flag.is_spam=is_flagged
object_to_flag.is_active=(not is_flagged)
object_to_flag.cleanup()
return object_to_flag.put()
さまざまなオブジェクトが次のように渡される場合 object_to_flag
, 、すべてが持っています is_active
, is_spam
, is_offensive
属性。彼らはたまたま、 cleanup()
方法。
渡すオブジェクトはすべて同じ基本クラスを持っています (Google App Engine の db オブジェクトです)。
class User(db.Model):
...
is_active = db.BooleanProperty(default = True)
is_spam = db.BooleanProperty(default=False)
is_offensive = db.BooleanProperty(default=False)
def cleanup():
pass
class Post(db.Model):
...
is_active = db.BooleanProperty(default = True)
is_spam = db.BooleanProperty(default=False)
is_offensive = db.BooleanProperty(default=False)
def cleanup():
pass
どうすれば作れますか cleanup()
メソッド抽象を使用すると、子が実装を提供する必要があるこれらすべてのオブジェクトに同じ親クラスを持たせることができますか?
おそらくもっと重要なことは、これが「パイソン的」であるかどうかということです。この方法で進むべきでしょうか、それともダックタイピングに頼るべきでしょうか?私のバックグラウンドは Java で、Python のやり方を学ぼうとしています。
ありがとう!
解決
ABCを利用できないため、シンプルなメタラスでこれを行うことができます
class Abstract(type(db.Model)):
def __new__(metacls, clsname, bases, clsdict):
for methodname in clsdict.pop('_abstract_methods_', []):
try:
if not callable(clsdict[methodname]):
raise TypeError("{0} must implement {1}".format(clcname, methodname))
except KeyError:
raise TypeError("{0} must implement {1}".format(clcname, methodname))
return super(Abstract, metacls).__new__(metacls, clsname, bases, clsdict)
class RequireCleanup(db.Model):
__metaclass__ = Abstract
_abstract_methods_ = ['cleanup']
def cleanup(self):
pass
表現 type(db.Model)
Metaclassが使用するものはすべて解決します db.Model
したがって、Googleのコードを踏むことはありません。また、ポップします _abstract_methods_
Googleに渡される前にクラスの辞書から __new__
何も壊れないように方法。もしも db.Model
すでにその名前の属性を持っているので、それを何か他のものに変更する必要があります。
他のヒント
クリーンアップ メソッドが確実に実装されるようにしたい場合は、次のようにラップします。 @abc.virtualmethod
デコレーター。これにより、virtualmethod をオーバーライドしていないオブジェクトのインスタンス化でエラーが発生します。これには、次のことも必要です。 abc.ABCMeta
あなたのクラスの __metaclass__
.
を参照してください。 abcモジュール 詳細といくつかの例については、こちらをご覧ください。
これは一般的には行われません。通常は、実装者が指定されたメソッドをオーバーライドする必要があるという趣旨のドキュメントのみが存在します。ただし、これは、その新しさによるものかもしれません。 abc
モジュール (Python 2.6 の新機能) を使用すると、このアプローチの非Python 性が認識されます。
なぜ持ってみませんか cleanup
メソッドを上げるだけです NotImplementedError
いつ呼ばれますか?彼らがあなたの子供のクラスを働かせたいなら、彼らは何らかの実装を導入する必要があります。
私は個人的にそれを使用したことはありませんが、私は多くの言及を見てきました ZOPEインターフェイス. 。これはあなたのタスクにとってはやり過ぎかもしれませんが、それはあなたにある程度の方向性を与えるかもしれません。そして、それはJavaの背景を持つ誰かに快適に感じるかもしれません。