【问题标题】:Change Python Class attribute dynamically动态更改 Python 类属性
【发布时间】:2015-08-24 12:05:42
【问题描述】:

我有一个 B 类继承 A 类,其类属性为 cls_attr。 我想在 B 类中动态设置 cls_attr。 类似的东西:

class A():
   cls_attr= 'value'

class B(A):

   def get_cls_val(self):
       if xxx:
          return cls_attr = 'this_value'
       return cls_attr = 'that_value'
   cls_attr = get_cls_val()

我尝试了几件事。我知道我可能没有找对地方,但我没有解决方案。

编辑:类是 django 管理类

谢谢。

【问题讨论】:

  • 你看到这个答案stackoverflow.com/a/2584050/471899了吗?
  • 我认为你需要解释你想要更清楚地看到的行为。也就是说,您是否打算在调用get_cls_val() 后更改A.cls_attr,还是应该只在BB 的实例上看到更改。
  • 嗨@Dunes,后者,我只想要B中的变化。

标签: python class django-admin


【解决方案1】:

类属性可以在类或实例上读取,但您只能在类上设置它们(尝试在实例上设置它们只会创建一个会影响类属性的实例属性)。

如果在导入时条件已知,您可以在class 正文中进行测试:

xxx = True 

class A(object):
   cls_attr = 'value'

class B(A):
   if xxx:
       cls_attr = 'this_value'
   else
       cls_attr = 'that_value'

现在如果你想在程序执行期间改变它,你要么必须使用classmethod

class B(A):
   @classmethod
   def set_cls_attr(cls, xxx):   
       if xxx:
           cls.cls_attr = 'this_value'
       else:
           cls.cls_attr = 'that_value'

或者如果您需要在测试期间访问您的实例:

class B(A):
   def set_cls_attr(self, xxx):   
       cls = type(self)
       if xxx:
           cls.cls_attr = 'this_value'
       else:
           cls.cls_attr = 'that_value'

【讨论】:

  • 这是正确答案,感谢您的建议。我需要记得在回答之前喝咖啡。
  • 您好,我尝试了您的@classmethod 解决方案。似乎没有调用函数 set_cls_attr...
  • @jcs 如果不调用它为什么会被调用?如果您知道导入时的值,请检查答案的第一部分。否则,请尝试澄清您的问题。
  • @brunodesthuilliers if 部分取决于用户配置文件,所以我需要访问“请求”(Django),不能使用第一部分。是的,我知道我必须调用该函数,这就是我在示例中添加 cls_attr = get_cls_val() 的原因,即使这不是正确的方法。
  • @brunodesthuilliers 如何让函数在类本身内执行?
【解决方案2】:

如何使用classmethod 并在子类中多态地覆盖它?

class A:
    @classmethod
    def cls_attr(cls):
        return 'value'

class B(A):
    @classmethod
    def cls_attr(cls):
        if cond():
            return 'this'
        else:
            return 'that'

assert A.cls_attr() == 'value'      
cond = lambda: True
assert B.cls_attr() == 'this'
cond = lambda: False
assert B.cls_attr() == 'that'

【讨论】:

  • 您还应该提到属性,这可能是一个看起来更优雅的解决方案。
  • @kirbyfan64sos 我从未见过@property@classmethod。这是一件事吗?例如属性,当然可以,但它适用于类属性/方法吗?
  • 属性自动工作,无需定义为类方法。
  • @ŁukaszR。这不会设置类属性。
  • @kirbyfan64sos 属性在类上查找属性时不起作用 - 必须在实例上查找。所以你不能做B.cls_attr,这有点像一开始就有一个类属性......
【解决方案3】:

对我来说最简单的解决方案是使用 property 装饰器:

class B:
    @property
    def attr_name(self):
        """ do your stuff to define attr_name dynamically """
        return attr_name

【讨论】:

    【解决方案4】:

    这似乎是你想要的:

    >>> class B(A):
         @classmethod
         def set_cls_val(cls, x):
                 if x == 1:
                         cls.cls_attr = "new"
    
    >>> c = B()
    >>> c.cls_attr
    'value'
    >>> c.set_cls_val(B, 1)
    >>> c.cls_attr
    'new'
    >>> B.cls_attr
    'new'
    

    只需在函数内设置即可。

    编辑:更新为设置类属性而不是实例属性,感谢@bruno-desthuilliers。

    编辑:再次更新,感谢@bruno-desthuilliers。我应该更清楚地思考我的答案。但你想要的答案在下面。

    【讨论】:

    • 不会更改类属性,抱歉。
    • 修复抱歉。感谢那。我有实例而不是类。
    • 如果你硬编码类名,classmethod 有什么用? (提示:classmethods 的约定是将第一个参数命名为 'cls' - 你能猜到为什么吗?)
    • 仍然如此。它更多地用于元分类,这是一种奇怪的情况。在这种情况下,它确实应该是一个静态方法或单独的函数。
    猜你喜欢
    • 2017-11-05
    • 1970-01-01
    • 2019-08-11
    • 1970-01-01
    • 1970-01-01
    • 2015-08-15
    • 1970-01-01
    • 2013-09-25
    • 2020-02-17
    相关资源
    最近更新 更多