python abc模块
面向对象的设计中,抽象类,接口这些必不可少的东西,在python中是如何提现的呢?
python作为一个动态语言,没有强类型的检查,而是以鸭子类型的方式提现,在执行的时候python不严格要求你必须是继承指定的父类而来,只要在调用的时候你有相应的方法和属性就可以了,长的像鸭子你就是鸭子。
也正是基于python这样的特性,python中没有interface的概念,有说interface并不是普遍存在的,而是作为一个特例出现在java中,为的是解决多继承的问题。python支持多继承,自然没有这个需要了。然而我们难免会有这样的需求:子类必须实现某些指定的方法和属性,否则就抛异常。使用一些笨方法自然是可以达到相同的效果,但是python为我们提供了abc模块。
http://bbs.chinaunix.net/thread-771123-1-1.html
java中的抽象类是为了实现c++中的抽象类和模板之类的东西
接口是为了解决java不能多继承的问题很显然楼主是从java才开始接触面向对象程序设计的。实际上java的“接口”是一个特例而非普通现象。如果可以多继承的话,那还要接口干什么?
实际上python才是最符合现实逻辑的“面向对象”
python允许多继承,正如现实中,你既是公民也是纳税人,我们直接使用这些“类”而不需要特别的创建什么“纳税人接口”
python中所有的类,都是抽象类,或者说根本不存在抽象类,类方法可以直接使用,“类”本身在定义的时候就已经实例化,你可以通过输入:某类[回车]看到其内存句柄。这是符合事实的,并且时简约明了的。
而在C++和java当中,一个类定义了以后,肯定是占用了内存空间,但是同时他又没有实例化,如果要使用的话还得实例化一次,又要占用一些内存空间。而类定义所占用的内存空间,使用率很低。
python中不存在“基类”的概念,也没有单根,更没有基本类型,所有的一切都是对象。
python是无神论的最完美体现,没有亚当,没有上帝,没有鬼神,没有唯一的主。你爱信什么信什么,爱是什么是什么,没有任何约束,但是不能存在特殊。另外,python根本没有意去模仿java的接口,因为那完全没必要,python的标准类就完全包含java中的接口的所有功能。倒是模仿一下c++的模板会有些实际用途。
好了,说完抽象类,接口的来历,我们看一看python中的abc模块是如何玩儿的:
python-3.6.0-docs-html/library/abc.html?highlight=abc#module-abc
https://www.python.org/dev/peps/pep-3119/
from abc import ABCMeta, abstractmethod, abstractproperty
class Drawable(metaclass=ABCMeta):
"""docstring for Drawable"""
@abstractproperty
def size(self):
# return 'mysize'
pass
@abstractmethod
def draw(self, x, y, scale=1.0):
# print(x * scale, y * scale)
pass
def double_draw(self, x, y):
self.draw(x, y, scale=2.0)
class Cicle(Drawable):
# 1. 使用继承的方法
"""docstring for Cicle"""
def draw(self, x, y, scale=1.0):
print(x * scale, y * scale)
@property
def size(self):
return 'Cicle size'
# Cicle如果没有override draw函数和size 属性,那么实例化的时候就会报错
# TypeError: Can't instantiate abstract class Cicle with abstract methods draw, size
c = Cicle()
print(dir(c))
c.draw(1, 2)
c.double_draw(1, 2)
print(isinstance(c, Drawable)) # True
print(isinstance(c, Drawable)) # True
class Rectangle():
"""docstring for Cicle"""
pass
# 使用抽象类函数的register方法注册具体的class
# 通过注册的类,可以直接实例化,但是无法访问抽象类的所有成员
# 其实就是只是让isinstance、issubclass识别注册的类为抽象类的成员和实例
Drawable.register(Rectangle)
r = Rectangle()
# r.double_draw(1, 2)
# AttributeError: 'Rectangle' object has no attribute 'double_draw'
print(dir(r))
print(isinstance(r, Drawable)) # True
print(issubclass(Rectangle, Drawable)) # True
# ['__abstractmethods__', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_abc_cache', '_abc_negative_cache', '_abc_negative_cache_version', '_abc_registry', 'double_draw', 'draw', 'size']
# 1.0 2.0
# 2.0 4.0
# True
# True
# ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
# True
# True
# [Finished in 0.2s]