微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在超类方法中访问子类属性,而不将其传递给

如何解决如何在超类方法中访问子类属性,而不将其传递给

如何使用基类方法访问派生类的属性(其他语言中的静态变量)? 即

class Base:
    @classmethod
    def get_list(cls):
        return [1,2,cls.x]

class Derived(Base):
    x = 3
    foo = Base.get_list()    

Derived.foo # Hope to have it set to [1,3]

我不希望直接将x传递给基类,即foo = Base.get_list(x),因为我有很多用相同变量调用方法

编辑

评论要求上下文。我试图提供一个最低限度的可重现性示例,以使大家省去细节。

这里是完整的上下文:因此,它实际上与Django Admin有关。 我有一个抽象模型。然后,我具有用于抽象模型的各种具体实现的各种管理界面。如您所料,我创建了一个抽象的管理模型来处理常见的逻辑。处理常见管理逻辑的一部分,例如在派生的管理模型上生成属性

例如,列表显示,这是创建列表显示的逻辑:

class FactAdmin(admin.ModelAdmin):
    @classmethod
    def build_list_display(cls,*custom):
        return (
            'created_utc',*custom,'foo__bar__abbreviation','foo__baz__name','foo__caz__name','foo__daz__description','foo__eaz__code',)

@admin.register(FooEntry)
class FoopEntryAdmin(FactAdmin):
    fieldsets = FactAdmin.build_list_display('cannon_ball','pogo_stick')

因此,在基本admin类中,它不断重用自定义字段自定义模型和其他内容的列表。因此,与其每次都为每个属性传递它们,不如将其设置为静态属性比较干燥。因此,我希望将它们设置为派生类的静态成员字段,并在基类中访问它们。

解决方法

您不应使用类属性和方法。您应该定义用于创建实例的类,并使用实例方法和属性,以使常规继承能够按预期的方式在语言中使用。

然后,您需要利用实例方法可以被子类覆盖的事实。在这里,为了让父类到达子类的x,可以在父类中定义一个您希望在子类中被覆盖的get_x方法。这样子类的x被父类使用,而不会传递给子类。

这是一个例子:

class Base:
    def set_foo(self):
        return [1,2,self.get_x()]

    def get_x(self):
        return 0

class Sub(Base):

    def __init__(self):
        self.x = 3
        self.foo = super().set_foo()

    def get_x(self):
        return self.x

print(Sub().foo)

结果:

[1,3]
,

在子类上调用的超类类方法中访问子类属性不是问题。可以按预期工作:

class Base:
    @classmethod
    def get_list(cls):
        return [1,cls.x]


class Derived(Base):
    x = 3


assert Derived.get_list() == [1,3]

但是,您不能在子类的类主体中轻松地调用该类方法,因为当时Derived的类对象和名称Derived尚不存在。 (您可以在方法,类方法和静态方法中调用它,因为它们的主体是在调用它们时进行评估的,而不是在定义它们时进行评估的。但这在这里无济于事。)并且如果在Base上调用显然缺少x。 (而且,作为get_list的Python类方法,必须在某些对象上显式调用。我们不能像Java中那样进行不合格的调用。)

所以

class Derived(Base):
    x = 3
    foo = get_list()

得出NameError: name 'get_list' is not defined

class Derived(Base):
    x = 3
    foo = Base.get_list()

得出AttributeError: type object 'Base' has no attribute 'x'

class Derived(Base):
    x = 3
    foo = Derived.get_list()

得出NameError: name 'Derived' is not defined

但是一切并没有丢失。别忘了Python允许我们从类外部创建和设置类属性。如此有效:

class Base:
    @classmethod
    def get_list(cls):
        return [1,cls.x]


class Derived(Base):
    x = 3


Derived.foo = Derived.get_list()


assert Derived.foo == [1,3]
,

如果您希望super访问派生类的属性,则可能是因为此属性被所有派生子类共享(无论如何您都无需对派生类类型进行任何检查)。在这种情况下,最合乎逻辑的事情是改为在super中实现该属性,从而解决了问题:

class Base:
    x = 3
    @classmethod
    def get_foo():
        return [1,self.x]

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。