如何“纯虚拟方法”? [英] How about "pure virtual methods"?

查看:58
本文介绍了如何“纯虚拟方法”?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你好,


我想到了一个新的Python功能。请告诉我你的想法

关于它。


假设您想编写一个带有一些未实现方法的基类,那就是

子类必须实现(或者甚至只是声明一个接口,

没有实现方法)。现在,你真的没办法了。

吧。您可以将方法保留为通过,或者提出一个

NotImplementedError,但即使在我所知道的最佳解决方案中,

现在还有检查子类是否已实现所有必需的

方法而不运行它并测试它是否有效。现有解决方案的另一个问题是,提出NotImplementedError通常意味着

这种方法可能会实施一段时间,而不是你必须

当你继承我时,实现这个方法。


我建议的是一个新的类,名为notimplemented(你可以建议一个更好的名字) 。它会在它的构造函数中得到一个函数,并且只需要
保存对它的引用。诀窍是当一个新类型(

的子类是默认类型对象)被创建时,它将覆盖其所有成员并且

检查是否有任何它们是一个未实现的实例。如果那是

的情况,它就不允许自己进行实例化。


我想要的是如果我有这个模块:


======================


类BaseClass(对象):

def __init __(个体经营):

...


@notimplemented

def save_data(self, filename):

"""此方法应该将类的内部状态保存为名为filename的
a文件。

" "

通过


类RealClass(BaseClass):

def save_data(self,filename):

open(filename).write(self.data)


======================


然后,如果我尝试实例化BaseClass,我会得到一个异常,但

实例化RealClass会没问题。

嗯,你怎么说?


Noam Raphael

Hello,

I thought about a new Python feature. Please tell me what you think
about it.

Say you want to write a base class with some unimplemented methods, that
subclasses must implement (or maybe even just declare an interface, with
no methods implemented). Right now, you don''t really have a way to do
it. You can leave the methods with a "pass", or raise a
NotImplementedError, but even in the best solution that I know of,
there''s now way to check if a subclass has implemented all the required
methods without running it and testing if it works. Another problem with
the existing solutions is that raising NotImplementedError usually means
"This method might be implemented some time", and not "you must
implement this method when you subclass me".

What I suggest is a new class, called notimplemented (you may suggest a
better name). It would get a function in its constructor, and would just
save a reference to it. The trick is that when a new type (a subclass of
the default type object) is created, It will go over all its members and
check to see if any of them is a notimplemented instance. If that is the
case, it would not allow an instantiation of itself.

What I want is that if I have this module:

======================

class BaseClass(object):
def __init__(self):
...

@notimplemented
def save_data(self, filename):
"""This method should save the internal state of the class to
a file named filename.
"""
pass

class RealClass(BaseClass):
def save_data(self, filename):
open(filename).write(self.data)

======================

then if I try to instantiate BaseClass I would get an exception, but
instantiating RealClass will be ok.
Well, what do you say?

Noam Raphael

推荐答案

Noam Raphael写道:
Noam Raphael wrote:
嗯,你怎么说?




在需要覆盖的方法中引发NotImplementedError是比较习惯,更直接的,以及已经很好了。


-

Erik Max Francis&& ma*@alcyone.com && http://www.alcyone.com/max/

美国加利福尼亚州圣何塞市&& 37 20 N 121 53 W&& AIM erikmaxfrancis

我们从历史中了解到我们没有从历史中吸取教训。

- Georg Friedrich Wilhelm Hegel



Raising NotImplementedError in the methods that need to be overridden is
much more customary, more straightforward, and already works fine.

--
Erik Max Francis && ma*@alcyone.com && http://www.alcyone.com/max/
San Jose, CA, USA && 37 20 N 121 53 W && AIM erikmaxfrancis
We learn from history that we do not learn from history.
-- Georg Friedrich Wilhelm Hegel


Noam Raphael< no *** @ remove.the.dot.myrea.lbox.com>写道:
Noam Raphael <no***@remove.the.dot.myrea.lbox.com> wrote:
我想要的是如果我有这个模块:

================= =====

类BaseClass(对象):
def __init __(自我):
...

@notimplemented
def save_data(self,filename):
"""此方法应该将类的内部状态保存为名为filename的文件。
"""


类RealClass(BaseClass):
def save_data(self,filename):
open(filename).write(self.data)

======================

然后,如果我尝试实例化BaseClass,我会得到一个例外,但是
实例化RealClass就没问题了。

嗯,你怎么说?
What I want is that if I have this module:

======================

class BaseClass(object):
def __init__(self):
...

@notimplemented
def save_data(self, filename):
"""This method should save the internal state of the class to
a file named filename.
"""
pass

class RealClass(BaseClass):
def save_data(self, filename):
open(filename).write(self.data)

======================

then if I try to instantiate BaseClass I would get an exception, but
instantiating RealClass will be ok.
Well, what do you say?




只要你不做就行已经很容易了不要坚持BaseClass必须

子类对象(或允许在那里进行__metaclass__赋值)。基本上,

你所描述的是一个自定义元类的工作,因为那就是定义了类的__call__方法的

(类是

元类)...比在课堂级别篡改__new__或

__init__更清洁。


在草图级别,你'有,比如说:


def notimplemented(f):

#如果你愿意,可以保存一些关于f的数据,例如:

返回未实现


导入检查


类Meta_for_NR(类型):

def __init __( cls,cn,cb,cd):

super(Meta_for_NR,cls).__ init __(cn,cb,cd)

abstract_methods = []

for n,v in inspect.getmembers(cls,inspect.ismethod):

如果v未实现:abstract_methods.append(n)

cls._abstract_methods = abstract_methods

def __call __(cls,* a,** k):

如果cls._abstract_methods:

引发TypeError,(不能实例化抽象类%s。

抽象方法:%s。 %(cls .__ name __,

'',''。join(cls._abstract_methods)))

返回super(Meta_for_NR,cls).__ call __(* a,* * k)


class Base_for_NR:__ metaclass__ = Meta_for_NR

继承Base_for_NR而不是继承自object应该

只给你一个你想要的行为(除了这个我的b $ b矿的代码是未经测试的事实,只是一个草图 - 但关键的想法是好的)。

如果你可以实现这个并且广泛使用,它可能是标准库中采用的
。除非经验证明

很多人都喜欢这种方法比事实上的b $ b b标准更好,所以这种采用是不太可能的。但最棒的是,

很容易实现你的想法,并试图为他们获得一个追随者,所以你有机会让他们进入标准库如果你

可以证明它们真的很好用并且很受欢迎!

Alex



It''s already easy to do as long as you don''t insist that BaseClass must
subclass object (or allow a __metaclass__ assignment there). Basically,
what you describe is the job of a custom metaclass, because that''s where
the __call__ method on classes is defined (classes being instances of
the metaclass)... much cleaner than tampering with the __new__ or
__init__ at class level.

At sketch level, you''d have, say:

def notimplemented(f):
# save some data about f somewhere if you wish, then, e.g.:
return notimplemented

import inspect

class Meta_for_NR(type):
def __init__(cls, cn, cb, cd):
super(Meta_for_NR, cls).__init__(cn, cb, cd)
abstract_methods = []
for n, v in inspect.getmembers(cls, inspect.ismethod):
if v is notimplemented: abstract_methods.append(n)
cls._abstract_methods = abstract_methods
def __call__(cls, *a, **k):
if cls._abstract_methods:
raise TypeError, ("Cannot instantiate abstract class %s."
" Abstract methods: %s." % (cls.__name__,
'', ''.join(cls._abstract_methods)))
return super(Meta_for_NR, cls).__call__(*a, **k)

class Base_for_NR: __metaclass__ = Meta_for_NR
Inheriting from Base_for_NR instead of inheriting from object should
give you just the behavior you desire (net of the fact that this code of
mine is untested, just a sketch -- but the key ideas shd be ok).
If you can implement this and get it into wide usage, it may well be
adopted in the standard library. Unless there is proof by experience
that a lot of people like this approach better than the de facto
standard, such adoption is very unlikely. But the great thing is that
it''s EASY to implement your ideas and try to garner a following for
them, so you stand a chance to get them into the standard library if you
can prove they really work well and are well-liked!
Alex


Alex Martelli写道:
Alex Martelli wrote:
类Meta_for_NR(类型):
def __init __(cls,cn,cb,cd):
super(Meta_for_NR,cls).__ init __(cn ,cb,cd)
abstract_methods = []
for n,v in inspect.getmembers(cls,inspect.ismethod):
如果v未实现:abstract_methods.append(n)
class Meta_for_NR(type):
def __init__(cls, cn, cb, cd):
super(Meta_for_NR, cls).__init__(cn, cb, cd)
abstract_methods = []
for n, v in inspect.getmembers(cls, inspect.ismethod):
if v is notimplemented: abstract_methods.append(n)



等等


我错过了问题的重点和Alex的答案。让我们通过这个步骤




1.程序员A设计基类的一些(或全部)方法是

摘要,即没有以有用的方式实现;他们

可能只是记录其论点的存根。


2.程序员B设计一个子类,*应该*实现方法

覆盖基类的那些。


3.程序员C写一个应该*应该*创建实例的应用程序

的子类。


4.可能出错的事情是(a)C实例化基类(b)B

未提供所有方法(c) B提供了方法,但是他们没有正常工作(d)C'的应用程序没有以

批准的方式调用B'的方法或序列或有意义的参数或...


5. Python中的标准方法是让虚拟方法在调用时引发异常
异常。这当然对问题没有帮助c

和d。为了根除问题c和d的实例,

程序员C将对@#


etc etc etc

I''m missing the point of the question and Alex''s answer. Let''s step
through this:

1. Programmer A designs a base class some (or all) of whose methods are
abstract i.e. not implemented in a do-something-useful fashion; they
may be only stubs which document their arguments.

2. Programmer B designs a sub-class, which *should* implement methods
which override those of the base class.

3. Programmer C writes an application which *should* create instances
of the sub-class.

4. Things that can go wrong are (a) C instantiates the base class (b) B
has not provided all the methods (c) B has provided methods but they
don''t work properly (d) C''s app doesn''t invoke B''s methods in the
approved manner or sequence or with meaningful arguments or ...

5. The standard approach in Python is to have the virtual methods raise
an exception if invoked. This of course doesn''t help with problems c
and d. In an attempt to root out instances of problems c and d,
programmer C will unit-test the @#

这篇关于如何“纯虚拟方法”?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆