Python 2.5 的抽象类

发布于 2024-11-18 05:05:50 字数 410 浏览 0 评论 0原文

我目前重构了一个定义客户端或服务器的类。这个类有很多

if client:
    XXXXXXXXXXXX
elif server:
    YYYYYYYYYYYY

所以我决定创建一个具有类似代码的类A,一个用于客户端的类C和一个用于继承A的服务器的类S。(当然它们没有这些名称^^)

所以A类是某种抽象类。但问题是Python 2.5中没有抽象类,它是2.6版本中附带的。所以我想知道是否有一种方法可以禁止类 A 的实例化。

一种解决方案是在类 A 的构造函数中引发 NotImplemented 错误,但 C 和 S 具有相同的代码,因此我将其放在“抽象”A 类(坏主意?)。

这可能看起来很愚蠢,但我只是偶尔使用 Python 进行开发,而且我是一名年轻的程序员。 您有什么建议?

I currently refactor a class defining a client or a server. The class had a lot of

if client:
    XXXXXXXXXXXX
elif server:
    YYYYYYYYYYYY

So I decided to create a class A with the similar code and one class C for the client and an other one S for the server which inherit A. (they don't have theses names of course ^^)

So class A is some kind of abstract class. But the problem is there is no abstract classes in Python 2.5, it comes with 2.6 version. So I was wondering if there is a way to forbid instantiations of class A.

One solution would have been to raise a NotImplemented error in the constructor of the class A, but C and S have the same code for it so I put it in the "abstract" class A (bad idea ?).

This may seem stupid but I develop in Python only from time to time and I'm a young programmer.
What are your advices?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

乄_柒ぐ汐 2024-11-25 05:05:50

在静态类型语言中,您使用抽象基类(ABC),因为您需要传递一些具有已定义大小、接口等的对象。否则,尝试调用该对象的方法的代码将无法编译。

Python 不是静态类型语言,调用代码根本不需要知道它所调用的对象的类型。因此,您可以通过记录接口需求并直接在两个不相关的类中实现该接口来“定义”您的 ABC。

例如,

class Server:
    def do_thing(self):
        pass #do that server thing here

class Client:
    def do_thing(self):
        pass #do that client thing here

def do_thing(thingy):
    thingy.do_thing() # is it a Client? a Server? something else?

s=Server()
c=Client()

do_thing(s)
do_thing(c)

在这里,您可以使用参数与调用匹配的 do_thing 方法传入任何对象。

In statically-typed languages, you use an abstract base class (ABC) because you need some object with a defined size, interface etc. to pass around. Otherwise, the code trying to call methods on that object can't be compiled.

Python isn't a statically-typed language, and the calling code doesn't need to know the type of the object it's calling at all. So, you can "define" your ABC just by documenting the interface requirements, and implementing that interface directly in two unrelated classes.

Eg,

class Server:
    def do_thing(self):
        pass #do that server thing here

class Client:
    def do_thing(self):
        pass #do that client thing here

def do_thing(thingy):
    thingy.do_thing() # is it a Client? a Server? something else?

s=Server()
c=Client()

do_thing(s)
do_thing(c)

Here, you could pass in any object with a do_thing method whose arguments match the call.

赠佳期 2024-11-25 05:05:50

这种方法的优点是您无需对子类执行任何操作即可使其成为非抽象。

class ABC(object):
    abstract = True
    def __new__(cls, *args, **kwargs):
        if "abstract" in cls.__dict__ and cls.__dict__["abstract"] == True:
            raise RuntimeError(cls.__name__ + " is abstract!")
        return object.__new__(cls)

class Subclass(ABC):
    pass

print Subclass()
print ABC()

输出:

<__main__.Subclass object at 0xb7878a6c>
Traceback (most recent call last):
  File "abc.py", line 14, in <module>
    print ABC()
  File "abc.py", line 6, in __new__
    raise RuntimeError(cls.__name__ + " is abstract!")
RuntimeError: ABC is abstract!

如果你想创建一个抽象子类,只需这样做:

class AbstractSubclass(ABC):
    abstract = True

This approach has the advantage that you do not need to do anything to the subclass to make it non-abstract.

class ABC(object):
    abstract = True
    def __new__(cls, *args, **kwargs):
        if "abstract" in cls.__dict__ and cls.__dict__["abstract"] == True:
            raise RuntimeError(cls.__name__ + " is abstract!")
        return object.__new__(cls)

class Subclass(ABC):
    pass

print Subclass()
print ABC()

Output:

<__main__.Subclass object at 0xb7878a6c>
Traceback (most recent call last):
  File "abc.py", line 14, in <module>
    print ABC()
  File "abc.py", line 6, in __new__
    raise RuntimeError(cls.__name__ + " is abstract!")
RuntimeError: ABC is abstract!

If you want to create an abstract subclass, simply do like this:

class AbstractSubclass(ABC):
    abstract = True
草莓味的萝莉 2024-11-25 05:05:50

您可以在 A 构造函数的开头调用方法“foo”。在 A 中,此方法引发异常。在 C 和 S 中,您重新定义了“foo”,因此不再有例外。

You can call a method "foo" at the beginning of A constructor. In A, this method raises an exception. In C and in S, you redefine "foo" so there is no more exceptions.

拿命拼未来 2024-11-25 05:05:50

我的第一个问题是:为什么不能简单地避免从类 A 实例化对象?我的意思是,这有点像有关实现单例的问题...如此回答者正确引用:

在“四人帮”对我们进行所有学术研究之前,“单身人士”(没有正式名称)只是一个简单的想法,值得一行简单的代码,而不是一个完整的宗教。

同样 - IMO - 适用于抽象类(实际上已在 Python 中引入 除了您打算使用它们的原因之外

,您还可以在 A 类的 __init__ 方法中引发异常,例如:

>>> class A():
...     def __init__(self):
...             raise BaseException()
... 
>>> a = A()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in __init__
BaseException
>>> class B(A):
...     def __init__(self):
...             pass
... 
>>> b = B()
>>>

当然这只是一个粗略的想法:如果例如,您在 A.__init__ 中有一些有用的东西,您应该检查 __class__ 属性等...

My first question is: why can't you simply avoid to instantiate an object from class A? What I mean is that this is a bit like questions on implementing singletons... As this answerer correctly quoted:

Before the Gang of Four got all academic on us, "singleton" (without the formal name) was just a simple idea that deserved a simple line of code, not a whole religion.

The same - IMO - applies to abstract classes (which in fact have been introduced in Python for other reasons than the one you would intend to use them for.

That said, you could raise an exception in the __init__ method of class A. Something like:

>>> class A():
...     def __init__(self):
...             raise BaseException()
... 
>>> a = A()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in __init__
BaseException
>>> class B(A):
...     def __init__(self):
...             pass
... 
>>> b = B()
>>>

Of course this is just an rough idea: if you have - for example - some useful stuff in the A.__init__ you should check the __class__ attribute, etc...

阳光的暖冬 2024-11-25 05:05:50

真正的问题是:为什么需要抽象类?

如果您创建两个类,并让第二个类继承第一个类,那么这是清理代码的有效方法。

The real question is: why do you need an abstract class?

if you make 2 classes, and make the second herit from the first, it is an efficient way to clean your code.

静水深流 2024-11-25 05:05:50

有一个抽象基类模块满足您的需求。

< em>不适用于 2.5。

There's an abstract base class module for what you want.

Not applicable for 2.5.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文