如何在Python中要求方法的实现?
我在 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_offense
属性。它们也恰好有一个 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()
方法抽象,以便我可以拥有相同的父级所有这些对象的类需要子级提供实现吗?
也许更重要的是,这是“Pythonic”吗?我应该走这条路,还是应该只依靠鸭子打字?我的背景是 Java,我正在尝试学习 Python 的做事方式。
谢谢!
I'm using duck typing in 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()
Where different objects are passed in as object_to_flag
, all of which have is_active
, is_spam
, is_offensive
attributes. They also happen to have a cleanup()
method.
The objects I'm passing in all have the same base class (they're db objects in Google App Engine):
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
How can I make the cleanup()
method abstract so that I can have the same parent class for all these objects that requires the children provide implementation?
Perhaps more importantly, is this 'pythonic'? Should I go this route, or should I just rely on the duck typing? My background is in Java and I'm trying to learn the Python way of doing things.
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
使用
abc
模块。具体来说,将基类的元类设置为ABCMeta
并在cleanup
方法上使用@abstractmethod
装饰器。关于这是否是“Pythonic”的争论存在分歧。 PEP 3119 描述了该标准,列出了一些优点和缺点(但显然更喜欢 ABC)。它已被纳入标准库,这很好地表明许多人认为它在某些情况下很有用。对于你的情况,我认为是合适的。
Use the
abc
module. Specifically, set your base class's metaclass toABCMeta
and use the@abstractmethod
decorator on yourcleanup
method.The debate on whether this is "pythonic" is split. PEP 3119, which describes the standard, lists some of the pros and cons (but obviously favors ABCs). It made it into the standard library, which is a pretty good indication that many people consider it useful in some circumstances. In your case, I think it is appropriate.
如果你想确保 cleanup 方法被实现,你可以用
@abc.virtualmethod
装饰器包装。这将导致在实例化任何未重写虚拟方法的对象时出现错误。这还要求您将abc.ABCMeta
设为类的__metaclass__
。有关详细信息和一些示例,请参阅 abc 模块。
这并不常见:通常只有文档表明实现者必须重写给定的方法。然而,这可能更多是由于 abc 模块(Python 2.6 中的新增功能)的新颖性,而不是这种方法的非 Python 性。
If you want to ensure that the cleanup method is implemented, you can wrap with the
@abc.virtualmethod
decorator. This will cause an error on instantiation of any object that hasn't overridden the virtualmethod. This also requires that you makeabc.ABCMeta
your class's__metaclass__
.See the abc module for more info and some examples.
This is not commonly done: usually there will just be docs to the effect that implementers must override the given method. However this may be more due to the newness of the
abc
module (new in Python 2.6) than a perceived unpythonicness of this approach.为什么不让
cleanup
方法在调用时引发NotImplementedError
呢?如果他们希望你的孩子的课程能够正常进行,他们就必须采取某种实施措施。Why not have the
cleanup
method just raise anNotImplementedError
when it is called? If they want your children classes to work they'll have to put some sort of implementation in place.由于您没有可用的 abc,因此您可以使用一个简单的元类来执行此操作,
表达式
type(db.Model)
解析为用于db.Model
的任何元类,因此我们不践踏谷歌的代码。另外,在将_abstract_methods_
传递给 google 的__new__
方法之前,我们将其从类字典中弹出,这样我们就不会破坏任何内容。如果 db.Model 已经有一个具有该名称的属性,那么您需要将其更改为其他名称。Since you don't have abc available, you can do this with a simple metaclass
the expression
type(db.Model)
resolves to whatever metaclass gets used fordb.Model
so we don't step on google's code. Also, we pop_abstract_methods_
out of the class dictionary before it get's passed to google's__new__
method so that we don't break anything. Ifdb.Model
already has an attribute with that name, then you will need to change it to something else.虽然我个人从未使用过它,但我见过很多对 Zope 的引用接口。这对于您的任务来说可能有些过头了,但它可能会给您一些方向。对于具有 Java 背景的人来说可能会感觉很舒服。
Although I've never used it personally, I've seen many references to Zope interfaces. This may be overkill for your task, but it may give you some direction. And it may feel comfortable to someone with a Java background.