python:抽象类和接口

起因

最近在写上两篇restframework的博文中遇到了一个问题,认证和权限中有一个方法定义必须为固定方法名,不是的话就报错,我当时并不知道是为什么,以为是某种特性,也没有深究,今天在群里和别人聊天的时候,突然看到其他人也有这个问题,然后一查资料,发现了这确实是一个有点意思的东西。

java中的抽象类和接口

参数 抽象类 接口
默认的方法实现 它可以有默认的方法实现 接口完全是抽象的。它根本不存在方法的实现
实现 子类使用extends关键字来继承抽象类。如果子类不是抽象类的话,它需要提供抽象类中所有声明的方法的实现。 子类使用关键字implements来实现接口。它需要提供接口中所有声明的方法的实现
构造器 抽象类可以有构造器 接口不能有构造器
与正常Java类的区别 除了你不能实例化抽象类之外,它和普通Java类没有任何区别 接口是完全不同的类型
访问修饰符 抽象方法可以有public、protected和default这些修饰符 接口方法默认修饰符是public。你不可以使用其它修饰符。
main方法 抽象方法可以有main方法并且我们可以运行它 接口没有main方法,因此我们不能运行它。
多继承 抽象方法可以继承一个类和实现多个接口 接口只可以继承一个或多个其它接口
速度 它比接口速度要快 接口是稍微有点慢的,因为它需要时间去寻找在类中实现的方法。
添加新方法 如果你往抽象类中添加新的方法,你可以给它提供默认的实现。因此你不需要改变你现在的代码。 如果你往接口中添加方法,那么你必须改变实现该接口的类。

用python伪代码模拟接口和模型类

接口

	Interface IMessage:
	def func1(self):
		pass 
	def func2(self):
		pass 

class Msg(IMessage):
	def func1(self):
		print('func1') 
	def func2(self):
		print('func1') 

上面需要说明的是,假如这是一个接口,它可以内部定义方法,但方法里不能有值,只能写pass,而如果有多个函数,那么它也必须全部是pass,否则就会报错

下面我们可以定义一个类去继承这个接口,那么我们定义的这个类就可以定义参数以及做其它操作,但函数的名字、个数必须和接口中的方法相同,否则约束还是不成立,依然报错。这是一种约束


抽象类

class abstract IMessage:
	def abstract func1(self):
		pass 
	def abstract func2(self):
		pass 
	
	def func3(self):
		print('123') 
		
class Msg(IMessage):
	def func1(self):
		print('func1') 
	def func2(self):
		print('func1') 

在抽象类里面,可以有抽象方法和非抽象方法,抽象方法为pass,非抽象方法就是普通的函数。那么当另一个类来继承这个抽象类时,当前的msg类方法,要全部继承imassage中的抽象方法,但非抽象方法可写可不写,这是一种约束加继承。

python中的抽象类/抽象方法

from abc import ABCMeta,abstractmethod
class Abstract(metaclass=ABCMeta):	# 抽象类
    @abstractmethod
    def func(self):
        pass	# 指定了某种规范

class A(Abstract):
    def func(self):	 # 遵守这种规范
        print("A")

class B(Abstract):
    pass

a = A()
b = B()#报错,没有实现抽象方法

在定义抽象类前需要从类库abc导入ABCmeta类(即Metaclass for defining Abstract BaseClasses,抽象基类的元类)和abstractmethod类。
python中是没有接口的,但是有抽象方法和抽象类,通过abc这个模块,另外就是当我们定义了一个这样的方法时,相当于制定了规则,那么后来者需要这个规则,否则将会抛异常。

restframework中的约束类

在我们上两篇博文中,我们再自定义认证函数时,都重写了

class BaseAuthentication(object):
    """
    All authentication classes should extend BaseAuthentication.
    """

    def authenticate(self, request):
        """
        Authenticate the request and return a two-tuple of (user, token).
        """
        raise NotImplementedError(".authenticate() must be overridden.")

也就是因为这个原因,所以我们后面继承的自定义认证类需要去继承这个authenticate方法,否则就会报错,报错信息为NotImplementedError,一般基本所有的语言如果没有去继承这个约束类中的约束方法,都会报这个错,但python中的是抛异常而已。我们再来看看我们当初写的认证类:

from rest_framework import exceptions
from rest_framework.authentication import BaseAuthentication

from .models import Token
class TokenAuth(BaseAuthentication):
    def authenticate(self,request):
        token = request.GET.get("token")
        token_obj = Token.objects.filter(token=token).first()
        if not token_obj:
            raise exceptions.AuthenticationFailed("验证失败123!")
        else:
            return token_obj.user.name,token_obj.token

关于这个类的解释在认证.中有说明。另外权限也差不多的意思,这里就不再提了。



参考文献:

  1. https://pypi.org/project/zope.interface/
  2. http://www.importnew.com/12399.html
  3. https://blog.csdn.net/fenglibing/article/details/2745123

你可能感兴趣的:(python)