if条件用于类中的多个方法

时间:2015-06-10 23:20:11

标签: python class methods

我在python中编写,以便在使用类时更好地了解良好实践。我为几个班级编写了一些方法;狗和人。我已经介绍了一种叫做die的狗的新方法,定义如下:

def die(self):
    if self.owner:
        self.owner.pets.discard(self)
    self.owner = None
    self.dead = True

现在我不希望能够将大多数其他方法用于死狗,即采用宠物的方法(person.adopt(self,pet))。由于有这种情况的方法很多(并且可能还有更多),我想避免在每个要求狗活着的方法中添加if语句。有没有办法简单地不允许某些方法给出一个条件,如self.dead == False?

2 个答案:

答案 0 :(得分:6)

使用装饰器怎么样?您将不得不装饰每个需要宠物活着的功能,但您将不必一遍又一遍地编写if逻辑:

connectionstring

答案 1 :(得分:0)

如果您有很多方法要进行装饰,您可能需要考虑使用元类来完成将其应用于所有方法的工作,即使它比您接受的答案更长。这样做的好处是,装饰方法列表都位于一个位置 - 因此更改它们并提供文档会更容易。我也将装饰器本身作为该类的静态方法,因为它是唯一使用它的地方。

from functools import wraps

class MetaDeco(type):
    def __new__(metaclass, name, bases, attrs):
        cls = super(MetaDeco, metaclass).__new__(metaclass, name, bases, attrs)
        if 'meta_args' in attrs:
            decoratorname, methodnames = attrs['meta_args']
            decorator = getattr(cls, decoratorname)
            for methodname in methodnames:
                setattr(cls, methodname, decorator(getattr(cls, methodname)))
            del attrs['meta_args']  # clean up
        return cls

class Pet(object):
    __metaclass__ = MetaDeco  # in Python 3 use Pet(metalcass=MetaDeco)
    meta_args = ('require_alive', ('eat', 'sleep'))

    @staticmethod
    def require_alive(method):
        @wraps(method)
        def wrapper(self, *args, **kwargs):
            if self.dead:
                raise Exception("Not alive")
            return method(self, *args, **kwargs)
        return wrapper

    def __init__(self, owner):
        self.owner = owner
        self.dead = False

    def die(self):
        self.owner = None
        self.dead = True

    def eat(self):
        print("Eating...")

    def sleep(self):
        print("Sleeping...")

p = Pet('Alex')
p.eat()  # -> Eating...
p.sleep()  # -> Sleeping...
p.die()
p.eat()  # will raise exception