【问题标题】:How can I make strong type object reference in Python?如何在 Python 中进行强类型对象引用?
【发布时间】:2014-04-06 10:03:56
【问题描述】:

我刚刚开始使用 Python 2.7。

我想从一个类到另一个类进行某种强类型引用。

假设我有两个类:

class Module:
    count = 0

    def __init__(self, m_name, m_type, m_on=False):
        self.name  = m_name
        self.type = m_type
        self.on = m_on
        self.id  = self.count
        self.count += 1

还有Slot 我想将Module 作为元素:

class Slot:
    count = 0

    def __init__(self):
        self.id  = self.count
        self.count += 1
        self.element = None

现在我想在该槽中添加设置element 的方法,然后在其他方法中使用它(使用它的字段和方法),但我想确保它是元素:模块。

如果我能“告诉”PyCharm elementModule 的类型,这也会很有帮助,这样它会自动完成我的输入。

有可能吗?我可以欺骗python吗:

self.element = Module()

在 init 方法中(如果我在上面这样做,它会将元素识别为 Module 的类型并自动完成)。

【问题讨论】:

    标签: python class object reference typing


    【解决方案1】:

    正如haraprasadj 所说,Python 不是静态类型的,因此您可能应该尝试习惯它并相应地编写代码。 Python 不是 Java。我来自 Java,我花了一段时间才习惯这种东西,但是一旦你习惯了,你会发现 Java 的语法不必要地“挑剔”和混乱(嗯……至少,我现在这样做了)

    说了这么多,有了new style classes(继承自object的类),您可以使用@propertydecorator并创建透明的gettersetter(见this questionthis questionthis document)

    在您的情况下,要强制Slot 类的element 属性始终为NoneModule 的实例,您可以执行以下操作:

    class Module(object):
        count = 0
    
        def __init__(self, m_name, m_type, m_on=False):
            self.name  = m_name
            self.type = m_type
            self.on = m_on
            self.id  = self.count
            self.count += 1
    
    class Slot(object):
        count = 0
    
        def __init__(self):
            self.id  = self.count
            self.count += 1
            self.element = None
    
        @property
        def element(self):
            return self._element
    
        @element.setter
        def element(self, e):
          if not(e is None or isinstance(e, Module)):
              raise TypeError("Element must be None or Module")
          self._element = e
    
    if __name__ == "__main__":
        s = Slot()
        m = Module('name', 'type')
        print "s.element? %s" % s.element
        s.element = m
        print "s.element? %s" % s.element
        # Now, exception:
        s.element = "hellouuuu"
    

    哪些输出:

    s.element? None
    s.element? <__main__.Module object at 0x26c9b10>
    Traceback (most recent call last):
      File "./stack13.py", line 35, in <module>
        s.element = "hellouuuu"
      File "./stack13.py", line 25, in element
        raise TypeError("Element must be None or Module")
    TypeError: Element must be None or Module
    

    好的,这里发生了什么?当您创建Slot 的实例(变量s)并尝试使用s.module = "whatever" 为其module 属性分配某些内容时,实际发生的是调用s@element.setter 方法,使用"whatever" 作为 e 参数。如果方法没有抛出异常,则实际属性存储在s._module中)您可以使用vars(s)检查类的实际属性(参见this关于vars):

    >> s = Slot()
    >> m = Module('name', 'type')
    >> s.element = m
    >> print "%s" % vars(s)
    {'count': 1, 'id': 0, '_element': <__main__.Module object at 0x19d0b10>}
    

    看到了吗?那里没有element,但是_element

    现在,当您尝试使用s.element 读取element 属性时,正在调用以@property 装饰的方法。

    在我发布的示例中,在该方法中添加 print 语句:

    @property
    def element(self):
        print "I'm reading self._element. Wohooo"
        return self._element
    

    现在,重新执行脚本。您将在输出中看到:

    I'm reading self._element. Wohooo
    s.element? None
    I'm reading self._element. Wohooo
    s.element? <__main__.Module object at 0x1fd0ad0>
    {'count': 1, 'id': 0, '_element': <__main__.Module object at 0x1fd0ad0>}
    Traceback (most recent call last):
      File "./stack13.py", line 37, in <module>
        s.element = "hellouuuu"
      File "./stack13.py", line 26, in element
        raise TypeError("Element must be None or Module")
    TypeError: Element must be None or Module
    

    【讨论】:

      【解决方案2】:

      我猜你的意思是静态类型引用,而不是强类型引用。 Python 引用是强类型的。

      如果你想要静态类型,Python 不适合。

      我也不认为这句话有什么诡计:

      self.element = Module()
      

      这只是创建了一个模块类的对象。除非您明确重新分配给另一种类型,否则变量“元素”的类型仍然是模块类。

      这与我们在 C++ 或 Java 中所做的不同,但在我看来,这种灵活性增加了 Python 的力量

      希望这会有所帮助。

      【讨论】:

      • 我忘了说我想避免调用“构造函数”——你可以看到它分配了 ID。我可以有很多 init 方法吗?
      • 据我了解,您可以在 Slot 类(例如 set_element)中创建另一个方法,该方法将模块作为输入参数。或者,如果您希望在创建 Slot 时设置元素,您可以向 Slot 的构造函数添加输入参数以接受模块并将该值设置为元素。如果您想完全做其他事情,对不起,我的知识也有限
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-11-09
      • 1970-01-01
      • 2015-02-26
      • 2017-11-30
      • 2021-11-08
      • 1970-01-01
      • 2019-05-27
      相关资源
      最近更新 更多