概括地说,我有一个Django模型,我希望实例根据其中一个字段的值具有不同的行为:
ANIMAL_TYPES = ('cow', 'african swallow', 'dog')
ANIMAL_TYPE_CHOICES = tuple(enumerate(ANIMALS, start=1))
class Animal(models.Model):
animal_type = models.PositiveIntegerField(choices=ANIMAL_TYPE_CHOICES)
# ... other model fields
def speak_cow(self):
return 'moo'
def speak_african_swallow(self):
return 'squawk'
def speak_dog(self):
return 'woof'
choose_speak = {i: getattr(Animal,'speak_{}'.format(
name.replace(' ', '_'))) for (i, name) in ANIMAL_TYPE_CHOICES}
def speak(self):
return Animal.speak[self.animal_type](self)
目标是能够在speak()
的实例上调用Animal
,并让班级选择正确的speak
方法。 (要明确的是:speak
方法比返回字符串要多得多。)
这不起作用:Animal
不是由我在choose_speak
词典理解中使用它时定义的。choose_speak = [None, speak_cow, speak_african_swallow, speak_dog]
。目前,我的解决方法是使用
speak_sheep
但有没有办法自动生成我想要的内容,所以我不必手动添加我定义的任何新方法(例如val mediator = DistributedPubSubExtension(system).mediator
val chatMember1 = TestProbe()
mediator ! Subscribe(topic, chatMember1.ref)
//... Call the publisher to publish message
chatMember1.expectMsg(ChatMessage(UserId, message))
)?
答案 0 :(得分:2)
您需要的是getattr
:
def speak(self):
method_name = choose_speak[self.animal_type]
method = getattr(self, method_name)
return method()
但是我是你,我现在只在if ... else
使用speak
,因为它更加简单明了。
答案 1 :(得分:2)
您还可以定义包含动物所有声音的列表......即
ANIMAL_SOUNDS = ['moo', 'squawk'..]
这样你就不必定义新方法了。 使用它说:
def speak(self):
return ANIMAL_SOUNDS[self.animal_type]
修改强>:
只是为了它,我玩了一下,并在纯python中提出了这个代码,可能接近你想要的:
ANIMAL_TYPES = ('cow', 'african swallow', 'dog')
ANIMAL_TYPE_CHOICES = tuple(enumerate(ANIMAL_TYPES, start=1))
class Animal(object):
def __init__(self, *args, **kwargs):
self.choose_speak = {i: getattr(self, 'speak_{}'.format(
name.replace(' ', '_'))) for (i, name) in ANIMAL_TYPE_CHOICES}
animal_type = 1
def speak_cow(self):
return 'moo'
def speak_african_swallow(self):
return 'squawk'
def speak_dog(self):
return 'woof'
def speak(self):
return self.choose_speak[self.animal_type]()
animal = Animal()
animal.speak()
注意:覆盖模型的__init__
不是Django最佳实践,如here所示: