【问题标题】:Define class variable with instance of another class用另一个类的实例定义类变量
【发布时间】:2017-01-04 20:58:58
【问题描述】:

我有以下课程:

class External(object):

    def __init__(self, first, second):
        self.first = first
        self.second = second

    def foo():
        print('something')

class Parent(object):

    shirt_color = ''
    shoes_color = ''
    external_class = External(shirt_color, shoes_color)

class SouthParent(Parent):

    shirt_color = 'white'
    shoes_color = 'blue'

因为 SouthParent 是 Parent 的子级,并且类变量 shirt_color 和 shoes_color 在 SouthParent 类中重新定义,所以 External() 将接收的预期参数应该是 ('white', 'blue') 但它接收的是 ( '','')

这是这样定义的,用于像 SouthParent.external_class.foo() 这样的终端像 Django 模型( User.objects.all() )

【问题讨论】:

  • 在实际调用External的时候,shirt_colorshoes_color根本就不是类变量;它们只是 class 语句主体中的局部变量,一旦元类实际创建 Parent,它们将被添加到类的字典中。

标签: python class inheritance


【解决方案1】:

您永远不会在SouthParent 上定义external_class,因此访问该属性使用来自Parentexternal_class,它被定义为External('', '')

如果你想让它基于类属性构造external_class,你可以使用一个属性:

class Parent(object):

    shirt_color = ''
    shoes_color = ''

    @property
    def external_class(self):
        return External(self.shirt_color, self.shoes_color)

如果每次都应该是相同的 External 实例,那么这样做:

class Parent(object):

    shirt_color = ''
    shoes_color = ''

    _external_class = None

    @property
    def external_class(self):
        if self._external_class is None:
            self._external_class = External(self.shirt_color, self.shoes_color)
        return self._external_class

【讨论】:

  • 是的,但是我重新定义了在External中调用的类变量,你有替代方案吗?
  • 重新定义类变量不会做任何事情......为什么会这样? Python 不会神奇地记住每个值是如何构造的,并在其任何组件发生变化时重做构造
  • 如果类未实例化,则无法使用 @property 装饰器 like in here
  • 嗯,是的。您需要实例化该类。毕竟,这就是课程的用途。我以为那不用说...
  • 我不确定您是否熟悉 Django,但模型可用于实例化 User(email='asda@asd.com').save()User.objects.all() 这是我使用此代码的目的,以复制此代码
【解决方案2】:

可能的解决方案:(在@kindall 的帮助下)

使用 Python 元类

class External(object):
    def __init__(self, first, second):
        self.first = first
        self.second = second

    def foo():
        print('something')

class ParentMeta(type):
    def __new__(cls, name, bases, attrs):

        if attrs['shirt_color'] and attrs['shoes_color']:
            attrs['external_class'] = External(attrs['odoo_model'],attrs['cache_name'])

        return super(ParentMeta, cls).__new__(cls, name, bases, attrs)

class Parent(metaclass=ParentMeta):

    shirt_color = ''
    shoes_color = ''         

class SouthParent(Parent):

    shirt_color = 'white'
    shoes_color = 'blue'


SouthParent.external_class.foo()
# something

【讨论】:

    猜你喜欢
    • 2015-06-09
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    • 2018-07-25
    • 2017-08-12
    • 2012-05-21
    • 1970-01-01
    相关资源
    最近更新 更多