【问题标题】:Context-dependent Python object property?依赖于上下文的 Python 对象属性?
【发布时间】:2021-07-07 20:42:53
【问题描述】:

我想编写一个带有属性的 Python 类(我在这里称其为“位置”),它可以以两种不同的、依赖于上下文的方式使用——有点像在 C 中可以用工会:

第一种方式,它有子属性——我称它们为 x 和 y:

my_object.position.x = 12
my_object.position.y = 13

print(my_object.position.x) # prints 12

第二种方式,获取并传递一个元组:

my_object.position = (12, 13)

print(my_object.position) # prints (12, 13)

我尝试这样做只是因为有时作为元组访问更方便,有时作为命名子属性访问。意图是元组和子属性表示相同的信息,因此 tuple[0] 是 x 属性,tuple[1] 是 y 属性,如:

my_object.position = (12, 13)

my_object.position.y = 14
   
print(my_object.position) # prints (12, 14)

我知道如何让它工作(子属性或元组),但不能同时工作。

(我知道元组是不可变的——数据不需要作为元组存储在对象中。)

我也已经知道如何让 setter 检查输入的类型,以便它可以(例如)接受元组或无。

在 Python 中是否有(合理的)方法可以做到这一点?这是一个坏主意吗?

【问题讨论】:

    标签: python methods properties


    【解决方案1】:

    这在 Python 中是完全合理的。事实上,这在 Python 中已经是一个既定的东西了。

    它被称为命名元组。

    https://www.pythontutorial.net/advanced-python/python-namedtuple/

    【讨论】:

    • 谢谢,但我不清楚如何将其作为属性(相对于属性)。我将如何编写一个可以将位置处理为 (x,y) 或 position.x position.y 的设置器?
    【解决方案2】:

    这是一个(我认为)可行的变体。

    code00.py

    #!/usr/bin/env python
    
    import sys
    
    
    class Pos:
        def __init__(self, x=0, y=0):
            self.x = x
            self.y = y
    
        def __getitem__(self, key):
            if key == 0:
                return self.x
            elif key == 1:
                return self.y
            raise IndexError("Index out of range")
    
        def __str__(self):
            return "({:}, {:})".format(self.x, self.y)
    
    
    class Test:
        def __init__(self):
            self._position = Pos()
    
        @property
        def position(self):
            return self._position
    
        @position.setter
        def position(self, value):
            self._position = Pos(*value)
    
    
    def main(*argv):
        t = Test()
        print("pos:", t.position)
        t.position.y = 13
        print("pos:", t.position)
        t.position.x = 12
        print("pos.x:", t.position.x)
        t.position = (12, 13)
        print("pos:", t.position)
        t.position.y = 14
        print("pos:", t.position)
        x, y = t.position
        print(x, y)
    
    
    if __name__ == "__main__":
        print("Python {0:s} {1:d}bit on {2:s}\n".format(" ".join(elem.strip() for elem in sys.version.split("\n")), 64 if sys.maxsize > 0x100000000 else 32, sys.platform))
        rc = main(*sys.argv[1:])
        print("\nDone.")
        sys.exit(rc)
    

    输出

    [cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q067063954]> "e:\Work\Dev\VEnvs\py_pc064_03.08.07_test0\Scripts\python.exe" code00.py
    Python 3.8.7 (tags/v3.8.7:6503f05, Dec 21 2020, 17:59:51) [MSC v.1928 64 bit (AMD64)] 64bit on win32
    
    pos: (0, 0)
    pos: (0, 13)
    pos.x: 12
    pos: (12, 13)
    pos: (12, 14)
    12 14
    
    Done.
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-06
      • 1970-01-01
      • 2020-06-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多