python设计模式之内置装饰器使用(四)

前言

python内部有许多内建装饰器,它们都有特别的功能,下面对其归纳一下。

系列文章

python自带装饰器

staticmethod

staticmethod装饰器的功能是去除类的方法默认第一个参数是类的实例,使得该方法成为一个普通的函数,staticmethod是一个类,属于类装饰器。

class Person(object):
    def eat(self):
        print('eat thing')

    @staticmethod
    def go(): # 不再传递self
        print('go')

classmethod

类定义时,除了new方法外,其他定义的方法在调用时第一个参数传入的必须是一个实例,使用classmethod装饰器装饰后,方法的第一个参数是类对象;调用类方法不需要创建类的实例。classmethod也是一个类,所以classmethod是一个类装饰器。

class Person(object):
    _num_ear = 2

    def eat(self):
        print('eat thing')

    @classmethod
    def go(cls):
        print(cls._num_ear)
        print('go')

if __name__ == '__main__':
    Person.go() # 无需创建实例,直接调用。

property

对于一个类的属性,python的访问是没有限制的,但有时候我们需要对属性的访问加以限制,property装饰器就是干这个的。

property是一个类,它有三个方法,deleter,setter,getter,有两种使用方式。

class Person(Animal):
    _num_ear = 2

    def __init__(self):
        self._name = 'xiaoming'
        self.age = 20

    def get_name(self):
        print('get name')
        return self._name

    def set_name(self, name):
        print('set name')
        self._name = name

    def delete_name(self):
        print('del name')
        del self._name

    name = property(get_name, set_name, delete_name, doc='name of person')
    # 或使用匿名函数
    name = property(lambda self:self._name, lambda self, name: setattr(self, '_name', name), lambda self:delattr(self,'_name'))

if __name__ == '__main__':
    p = Person()
    print(p.name) # 会调用get_name
    p.name = 'xxxx'  # 会调用set_name
    del p.name     # 会调用delete_name

property可以手动指定限制的函数,有四个参数,但是这样显得比较麻烦,可以使用装饰器的形式。

class Person(Animal):
    _num_ear = 2

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, nm):
        self._name = nm

    @name.deleter
    def name(self):
        del self._name

if __name__ == '__main__':
    p = Person()
    print(p.name) 
    p.name = 'xxxx' 
    del p.name    

一个函数被property装饰后返回的是property对象,只有fget参数的函数可以被property,因为装饰器只接受一个参数;另外的属性设置和删除需要直观调用响应的方法。

abstractmethod

python的抽象类和java不一样,java的抽象类不能实例化,同时抽象方法子类必须实现,否则报错!但是python抽象类默认是可以实例化的,也可以这样说,如果我们对抽象类定义:本身不能实例化,子类必须实现抽象方法;那么我们一般写的基类都不是抽象类。如果想要实现java中的抽象类的效果该怎么办呢?使用abstractmethod装饰器,含义是抽象方法。

一个类中的任何方法被abstractmethod装饰后,这个类不能实例化并且子类必须实现被abstractmethod装饰的方法。

from abc import abstractmethod,ABCMeta
class Animal(metaclass=ABCMeta):

    @abstractmethod
    def eat(self):
        pass

class Person(Animal):
    _num_ear = 2
    def eat(self):
        print('eat thing')

    @classmethod
    def go(cls):
        print(cls._num_ear)
        print('go')

如果需要定义一个类是抽象类,那么它需要继承ABCMeta而不是object,这样abstractmethod装饰器才会起作用。其起作用的原理是将一个方法的__isabstractmethod__属性设置为True,这样解释器就会检查子类是否实现了抽象方法。

总结

posted @ 2018-08-29 16:30  倥偬时光  阅读(2335)  评论(0编辑  收藏  举报