Python 2.5的抽象类
我目前正在重构一个定义客户机或服务器的类。这个班有很多学生Python 2.5的抽象类,python,refactoring,Python,Refactoring,我目前正在重构一个定义客户机或服务器的类。这个班有很多学生 if client: XXXXXXXXXXXX elif server: YYYYYYYYYYYY 所以我决定用类似的代码创建一个类a,一个类C用于客户端,另一个类S用于服务器,服务器继承了a。(当然,它们没有这些名称^^) 所以类A是一种抽象类。但问题是Python2.5中没有抽象类,它是2.6版本的。所以我想知道是否有办法禁止类a的实例化 一种解决方案是在类a的构造函数中引发NotImplemented错误,但C和
if client:
XXXXXXXXXXXX
elif server:
YYYYYYYYYYYY
所以我决定用类似的代码创建一个类a,一个类C用于客户端,另一个类S用于服务器,服务器继承了a。(当然,它们没有这些名称^^)
所以类A是一种抽象类。但问题是Python2.5中没有抽象类,它是2.6版本的。所以我想知道是否有办法禁止类a的实例化
一种解决方案是在类a的构造函数中引发NotImplemented错误,但C和S的代码相同,所以我将其放在“抽象”类a中(坏主意?)
这可能看起来很愚蠢,但我只是偶尔用Python开发,而且我是一个年轻的程序员。
你的建议是什么?你想要什么就有什么
不适用于2.5。对于您想要的内容,有一个解决方案
不适用于2.5。真正的问题是:为什么需要抽象类
如果您创建两个类,并从第一个类创建第二个类,这是清理代码的有效方法。真正的问题是:为什么需要抽象类
如果您创建两个类,并从第一个类创建第二个类,这是清理代码的有效方法。您可以在构造函数开头调用方法“foo”。在中,此方法引发异常。在C和S中,您重新定义了“foo”,因此不再有异常。您可以在构造函数的开头调用方法“foo”。在中,此方法引发异常。在C和S中,您重新定义了“foo”,这样就没有更多的异常了。我的第一个问题是:为什么您不能简单地避免从类
A
实例化对象?我的意思是这有点像。。。如正确引用的:
在“四人帮”对我们进行学术研究之前,“单身”(没有正式名称)只是一个简单的想法,应该有一行简单的代码,而不是整个宗教
同样的-IMO-也适用于抽象类(实际上,Python中引入的抽象类比您打算使用它们的抽象类要多)
也就是说,您可以在类A
的\uuuu init\uuuu
方法中引发异常。类似于:
>>> 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类()
…定义初始化(自):
…引发BaseException()
...
>>>a=a()
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“”,第3行,在_init中__
基本例外
>>>B(A)类:
…定义初始化(自):
…通过
...
>>>b=b()
>>>
当然这只是一个粗略的想法:例如,如果你在
A中有一些有用的东西,你应该检查\uuu class\uuuu
属性,等等…我的第一个问题是:为什么你不能简单地避免从classA
实例化一个对象?我的意思是,这有点像…正确地引用d:
在“四人帮”对我们进行学术研究之前,“单身”(没有正式名称)只是一个简单的想法,应该有一行简单的代码,而不是整个宗教
同样的-IMO-也适用于抽象类(实际上,Python中引入的抽象类比您打算使用它们的抽象类要多)
也就是说,您可以在类A
的\uuuu init\uuuu
方法中引发异常。类似于:
>>> 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类()
…定义初始化(自):
…引发BaseException()
...
>>>a=a()
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“”,第3行,在_init中__
基本例外
>>>B(A)类:
…定义初始化(自):
…通过
...
>>>b=b()
>>>
当然,这只是一个粗略的想法:例如,如果你在A.中有一些有用的东西,你应该检查\uuu class\uuuu
属性,等等。这种方法的优点是你不需要对子类做任何事情来使它非抽象
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 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!
在静态类型语言中,您使用抽象基类(ABC),因为您需要一些具有定义大小、接口等的对象来传递。否则,无法编译试图调用该对象上的方法的代码
Python不是一种静态类型的语言,调用代码根本不需要知道它调用的对象的类型。因此,您可以通过记录接口需求并直接在两个不相关的类中实现该接口来“定义”ABC
例如
在这里,您可以使用参数与调用匹配的do_thing方法传入任何对象。在静态类型语言中,您使用抽象基类(ABC),因为您需要一些具有定义大小、接口等的对象来传递。否则,无法编译尝试调用该对象上的方法的代码
Python不是一种静态类型的语言,调用代码根本不需要知道它调用的对象的类型。因此,您可以通过记录接口需求并直接在两个不相关的类中实现该接口来“定义”ABC
例如
在这里,您可以通过Dou-thing方法传入任何对象,该方法的参数与调用匹配。在2.6版中新增,正如OP在问题中所说,他使用2.5。是的,我必须继续使用2.5版。问题确实明确提到了Python 2.5,并且在2.6版中引入了abc
。(尽管升级和使用abc
对我来说似乎是最好的解决方案。)OP已经知道了。事实上,它提到了ABC是在Python的2.6版本中引入的……在2.6版本中是新的,正如OP在他的问题中所说,他使用了2.5。是的,我必须坚持使用2.5版本。问题确实明确提到了Python 2.5,ABC
是在2.6中引入的