https://www.jb51.net/article/87710.htmjava
像java同样python也能够定义一个抽象类。python
在讲抽象类以前,先说下抽象方法的实现。ssh
抽象方法是基类中定义的方法,但却没有任何实现。在java中,能够把方法申明成一个接口。而在python中实现一个抽象方法的简单的方法是:this
1
2
3
|
class
Sheep(
object
):
def
get_size(
self
):
raise
NotImplementedError
|
任何从Sheep继承下来的子类必须实现get_size方法。不然就会产生一个错误。但这种实现方法有个缺点。定义的子类只有调用那个方法时才会抛错。这里有个简单方法能够在类被实例化后触发它。使用python提供的abc模块。spa
1
2
3
4
5
6
7
|
import
abc
class
Sheep(
object
):
__metaclass__
=
abc.ABCMeta
@abc
.absractmethod
def
get_size(
self
):
return
|
这里实例化Sheep类或任意从其继承的子类(未实现get_size)时候都会抛出异常。.net
所以,经过定义抽象类,能够定义子类的共同method(强制其实现)。code
如何使用抽象类htm
1
2
3
4
5
6
7
8
9
10
11
12
|
import
abc
class
A(
object
):
__metaclass__
=
abc.ABCMeta
@abc
.abstractmethod
def
load(
self
,
input
):
return
@abc
.abstractmethod
def
save(
self
, output, data):
return
|
经过ABCMeta元类来建立一个抽象类, 使用abstractmethod装饰器来代表抽象方法继承
注册具体类接口
1
2
3
4
5
6
7
8
9
10
11
12
13
|
class
B(
object
):
def
load(
self
,
input
):
return
input
.read()
def
save(
self
, output, data):
return
output.write(data)
A.register(B)
if
__name__
=
=
'__main__'
:
print
issubclass
(B, A)
# print True
print
isinstance
(B(), A)
# print True
|
从抽象类注册一个具体的类
子类化实现
1
2
3
4
5
6
7
8
9
10
11
|
class
C(A):
def
load(
self
,
input
):
return
input
.read()
def
save(
self
, output, data):
return
output.write(data)
if
__name__
=
=
'__main__'
:
print
issubclass
(C, A)
# print True
print
isinstance
(C(), A)
# print True
|
能够使用继承抽象类的方法来实现具体类这样能够避免使用register. 可是反作用是能够经过基类找出全部的具体类
1
2
3
4
|
for
sc
in
A.__subclasses__():
print
sc.__name__
# print C
|
若是使用继承的方式会找出全部的具体类,若是使用register的方式则不会被找出
使用__subclasshook__
使用__subclasshook__后只要具体类定义了与抽象类相同的方法就认为是他的子类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
import
abc
class
A(
object
):
__metaclass__
=
abc.ABCMeta
@abc
.abstractmethod
def
say(
self
):
return
'say yeah'
@classmethod
def
__subclasshook__(
cls
, C):
if
cls
is
A:
if
any
(
"say"
in
B.__dict__
for
B
in
C.__mro__):
return
True
return
NotTmplementd
class
B(
object
):
def
say(
self
):
return
'hello'
print
issubclass
(B, A)
# True
print
isinstance
(B(), A)
# True
print
B.__dict__
# {'say': <function say at 0x7f...>, ...}
print
A.__subclasshook__(B)
# True
|
不完整的实现
1
2
3
4
5
6
7
|
class
D(A):
def
save(
self
, output, data):
return
output.write(data)
if
__name__
=
=
'__main__'
:
print
issubclass
(D, A)
# print True
print
isinstance
(D(), A)
# raise TypeError
|
若是构建不完整的具体类会抛出D不能实例化抽象类和抽象方法
具体类中使用抽象基类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
import
abc
from
cStringIO
import
StringIO
class
A(
object
):
__metaclass__
=
abc.ABCMeta
@abc
.abstractmethod
def
retrieve_values(
self
,
input
):
pirnt
'base class reading data'
return
input
.read()
class
B(A):
def
retrieve_values(
self
,
input
):
base_data
=
super
(B,
self
).retrieve_values(
input
)
print
'subclass sorting data'
response
=
sorted
(base_data.splitlines())
return
response
input
=
StringIO(
"""line one
line two
line three
"""
)
reader
=
B()
print
reader.retrieve_values(
input
)
|
打印结果
1
2
3
|
base class reading data
subclass sorting data
['line one', 'line two', 'line three']
|
能够使用super来重用抽象基类中的罗辑, 但会迫使子类提供覆盖方法.
抽象属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
import
abc
class
A(
object
):
__metaclass__
=
abc.ABCMeta
@abc
.abstractproperty
def
value(
self
):
return
'should never get here.'
class
B(A):
@property
def
value(
self
):
return
'concrete property.'
try
:
a
=
A()
print
'A.value'
, a.value
except
Exception, err:
print
'Error: '
,
str
(err)
b
=
B()
print
'B.value'
, b.value
|
打印结果,A不能被实例化,由于只有一个抽象的property getter method.
1
2
|
Error: ...
print concrete property
|
定义抽象的读写属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
import
abc
class
A(
object
):
__metaclass__
=
abc.ABCMeta
def
value_getter(
self
):
return
'Should never see this.'
def
value_setter(
self
, value):
return
value
=
abc.abstractproperty(value_getter, value_setter)
class
B(A):
@abc
.abstractproperty
def
value(
self
):
return
'read-only'
class
C(A):
_value
=
'default value'
def
value_getter(
self
):
return
self
._value
def
value_setter(
self
, value):
self
._value
=
value
value
=
property
(value_getter, value_setter)
try
:
a
=
A()
print
a.value
except
Exception, err:
print
str
(err)
try
:
b
=
B()
print
b.value
except
Exception, err:
print
str
(err)
c
=
C()
print
c.value
c.value
=
'hello'
print
c.value
|
打印结果, 定义具体类的property时必须与抽象的abstract property相同。若是只覆盖其中一个将不会工做.
1
2
3
4
|
error: ...
error: ...
print 'default value'
print 'hello'
|
使用装饰器语法来实现读写的抽象属性, 读和写的方法应该相同.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
import
abc
class
A(
object
):
__metaclass__
=
abc.ABCMeta
@abc
.abstractproperty
def
value(
self
):
return
'should never see this.'
@value
.setter
def
value(
self
, _value):
return
class
B(A):
_value
=
'default'
@property
def
value(
self
):
return
self
._value
@value
.setter
def
value(
self
, _value):
self
._value
=
_value
b
=
B()
print
b.value
# print 'default'
b.value
=
'hello'
print
b.value
# print 'hello'
|