我在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?
答案 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