簡體   English   中英

Python多態對象調用基類方法而不是子類方法

[英]Python polymorphic objects calling base class methods instead of subclass method

我在Django中有以下模型。 我有理由不將Animal作為抽象基類。

class Animal(models.Model):
    sound = "none"
    def ClassType(self):
        return 'animal'

class Cat(Animal):
    animal_id = models.OneToOneField(Animal,parent_link=True)
    sound = "meow"
    def ClassType(self):
        return 'cat'

class Dog(Animal):
    animal_id = models.OneToOneField(Animal,parent_link=True)
    sound = "bow"
    def ClassType(self):
        return 'dog'

我查詢一組動物

query = Animal.objects.all()

結果僅列出了貓和狗。 但是,在致電時

query[0].ClassType

我只有animal 在“查詢”中的所有對象給我animal ,而我想要得到dogcat取決於實例。 在Python多態世界中,我不了解什么?如何解決?

您可以使用點表示法(如屬性)訪問dog和cat對象。 查詢Animal.objects.all()將返回所有動物,其中包括所有貓和狗。

qs = Animal.objects.all()
for animal in qs:
    try:
        obj = animal.cat
        # its a cat
    except AttrbuteError:
        # its a dog
        obj = animal.dog

如您所見,在識別哪一只是狗和哪一只是貓時,存在一個小故障,一個好的方法是在動物模型中設置一個臨時屬性:

class Animal(models.Model):
    sound = "none"

    def is_cat(self):
        if not hasattr(self, '_is_cat'):
            self._is_cat = Cat.objects.filter(animal_id=self).exists()
        return self._is_cat

現在,您只需執行以下操作:

qs = Animal.objects.all()
for animal in qs:
    if animal.is_cat():
        # this is a cat
    else:
        # dog

不應將ClassType用作方法,而應使其成為實際字段,並在保存時存儲對象的類型。 否則,如您發現的那樣,當您查詢動物時,您只會得到動物,而不是子類型。

這個問題很舊,但是我遇到了同樣的問題,因此這是我的解決方案:

我使用了django_polymorphic應用程序,由於多種原因,它非常有用,但是它提供了相應模型實例的屬性及其名稱,可用於解決問題。

因此,您可以將基類更改為如下所示:

class Animal(PolymorphicModel):
    sound = "none"

    def ClassType(self):
        polymorphic_attr_name = self.name.lower().replace(" ", "")  # Get the name of the attribute that points to the instance
        if polymorphic_attr_name == 'animal':
            return 'animal'
        instance = getattr(self, polymorphic_attr_name)
        return instance.ClassType()

然后,您可以忘記任何動物子類。 它對我有用,希望對您有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM