【问题标题】:How do I assign a property to an instance in Python?如何将属性分配给 Python 中的实例?
【发布时间】:2011-10-30 09:07:37
【问题描述】:

使用python,可以通过以下两种方法之一设置实例的属性:

>>> class Foo(object):
    pass

>>> a = Foo()
>>> a.x = 1
>>> a.x
1
>>> setattr(a, 'b', 2)
>>> a.b
2

也可以通过属性装饰器来分配属性。

>>> class Bar(object):
    @property
    def x(self):
        return 0


>>> a = Bar()
>>> a.x
0

我的问题是,如何将属性分配给实例?

我的直觉是尝试这样的事情......

>>> class Doo(object):
    pass

>>> a = Doo()
>>> def k():
    return 0

>>> a.m = property(k)
>>> a.m
<property object at 0x0380F540>

...但是,我得到了这个奇怪的属性对象。类似的实验产生了类似的结果。我的猜测是,在某些方面,属性与类的关系比与实例的关系更密切,但我不太了解内部工作原理,无法理解这里发生了什么。

【问题讨论】:

    标签: python attributes properties instance variable-assignment


    【解决方案1】:

    可以在类创建后动态添加属性:

    class Bar(object):
        def x(self):
            return 0
    
    setattr(Bar, 'x', property(Bar.x))
    
    print Bar.x
    # <property object at 0x04D37270>
    print Bar().x
    # 0
    

    但是,您不能在实例上设置属性,只能在类上设置。您可以使用实例来执行此操作:

    class Bar(object):
        def x(self):
            return 0
    
    bar = Bar()
    
    setattr(bar.__class__, 'x', property(bar.__class__.x))
    
    print Bar.x
    # <property object at 0x04D306F0>
    print bar.x
    # 0
    

    更多信息请参见How to add property to a class dynamically?

    【讨论】:

    • 我很确定他们需要这个每个实例。您的建议会影响所有实例。
    • 啊!比我早1分钟!! :) +1
    • @Ross - 我知道,它在答案中这么说。根本不可能向实例添加属性。请参阅我链接的主题。
    【解决方案2】:

    您可以将属性直接分配给类对象:

    >>> class Foo(object):
        pass    
    >>> a = Foo()
    >>> a.__class__
    __main__.Foo    
    >>> setattr(a.__class__, 'm', property(lambda self: 0))
    >>> a.m
    0 
    >>> a.m = 24
    AttributeError: can't set attribute
    

    【讨论】:

      【解决方案3】:

      属性使用descriptors,它只适用于类,因此 对于所有情况。但是你可以使用描述符的组合 一个会参考每个实例函数的类。

      >>> class Foo(object):
      ...     @property
      ...     def x(self):
      ...         if 'x' in self.__dict__:
      ...             return self.__dict__['x'](self)
      ... 
      >>> a = Foo()
      >>> def k(self):
      ...     return 0
      ... 
      >>> a.__dict__['x'] = k
      >>> a.x
      0
      

      【讨论】:

        【解决方案4】:

        这里我们采用@agf 的解决方案并使用lambda 函数来定义类属性。

        class A(object):
            pass
        
        a = A()
        a.__class__.f = property(lambda self: 57)
        a.f  # 57
        

        以下帖子提供了更多背景信息:https://crosscompute.com/n/jAbsB6OIm6oCCJX9PBIbY5FECFKCClyV/_/Assign%20a%20class%20property%20to%20an%20instance

        【讨论】:

          猜你喜欢
          • 2011-06-17
          • 1970-01-01
          • 2013-05-23
          • 1970-01-01
          • 2023-03-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-12-02
          相关资源
          最近更新 更多