【问题标题】:Define a list with type定义一个带有类型的列表
【发布时间】:2009-12-17 20:46:00
【问题描述】:

我来自 Java,我想做一些像这样的data transfer objects (DTO):

class ErrorDefinition():
    code = ''
    message = ''
    exception = ''

class ResponseDTO():
    sucess = True
    errors = list() # How do I say it that it is directly of the ErrorDefinition() type, to not import it every time that I'm going to append an error definition?

或者有更好的方法吗?

【问题讨论】:

    标签: python


    【解决方案1】:

    您可以将列表键入为 python 3.8.4

    https://docs.python.org/3/library/typing.html

    from typing import List
    vector:List[float] = list()
    

    from typing import List
    vector:List[float] = []
    

    Python 是动态类型的,但是 https://www.python.org/dev/peps/pep-0484/ 打字使代码更容易阅读、更容易理解、更有效地使用 IDE 工具并创建更高质量的软件。我想这就是它在 PEP 中的原因。

    【讨论】:

    • 发现这个并困惑了一段时间,因为我对它的误解给出了一些特别令人困惑的错误消息。事实证明,如果要定义具有类型的列表,则不能定义像“self.alist=List[float]”这样的列表,它必须是“self.alist: List[float] = []”
    • @Rugnir 是的,你说得对,我匆忙回应。我已经更正了答案。
    【解决方案2】:

    DTO 是 Java 的一种设计模式。尝试在 Python 中使用 Java 语义是行不通的。您需要跨出另一个级别并询问。这是我要解决的问题...,在 Java 中我会使用 DTO - 你将如何使用 Python 来解决它?

    【讨论】:

    • ...答案通常是“哦,我可以使用元组”或“哦,等等,我在 Python 中实际上没有这个问题”。 ;-)
    • 是的,为什么像 DTO 这样的复杂设计模式在 Python 中没有出现太多,这一定是有原因的吧?
    • 到目前为止,对我来说这些问题的答案是“在 Python 中是不可能的”。静态类型语言肯定会让您避免犯类型转换错误,甚至不会考虑大多数类型安全问题,老实说,现在不得不考虑这些东西有点烦人。
    【解决方案3】:

    errors = list() # 怎么说直接是ErrorDefinition()类型的,每次我要追加错误定义的时候都不导入?

    我不确定您在此评论中想说什么,但如果我理解正确,最好的方法是定义一个添加错误的方法。

    class ResponseDTO(object): # New style classes are just better, use them.
    
        def __init__(self):
            self.success = True # That's the idiomatic way to define an instance member.
            self.errors = [] # Empty list literal, equivalent to list() and more idiomatic.
    
        def append_error(self, code, message, exception):
            self.success = False
            self.errors.append(ErrorDefinition(code, message, exception))
    

    【讨论】:

      【解决方案4】:

      请解释一下“每次都导入”是什么意思。

      在探索它们的确切作用之前,您需要重新考虑使用类级属性,尤其是当您使用诸如列表之类的可变类型时。考虑一下:

      >>> class Borg(object):
      ...     alist = list()
      ...
      >>> a = Borg()
      >>> b = Borg()
      >>> a.alist.append('qwerty')
      >>> a.alist
      ['qwerty']
      >>> b.alist
      ['qwerty']
      >>>
      

      不是你想要的?使用通常的 Python 习惯用法在类的 __init__ 方法中设置您需要的内容:

      >>> class Normal(object):
      ...     def __init__(self):
      ...         self.alist = list()
      ...
      >>> x = Normal()
      >>> y = Normal()
      >>> x.alist.append('frobozz')
      >>> x.alist
      ['frobozz']
      >>> y.alist
      []
      >>>
      

      【讨论】:

        【解决方案5】:

        我很确定您不能为列表定义类型。您每次都需要导入 ErrorDefinition(看起来就像已经存在的 Exception 类)。

        【讨论】:

          【解决方案6】:

          您现在可以通过type hint 指定__init__ 函数的类型来实现此目的。举个简单的例子:

          class Foo:
              def __init__(self, value: int):
                  self.value = value
          
          
          class Bar:
              def __init__(self, values: List[Foo]):
                  self.values = values
          

          这样,我们知道Barvalues 应该包含对Foo 的引用列表;并且Foovalue 应该是一个整数。看看我们误用的时候有什么:

          foo = Foo(1)
          print(foo.value.split()) 
          #               ^^^^^ Hint warning: Unresolved attribute reference 'split' for class 'int'
          
          bar = Bar([foo])
          print(bar.values[0] + 2) 
          #     ^^^^^^^^^^^^^ Hint warnings: Expected type 'int', got 'Foo' instead 
          

          【讨论】:

            【解决方案7】:

            Python 是动态类型的,您不需要像在 Java 中那样为变量声明类型。在这个阶段强烈建议阅读The official tutorial

            【讨论】:

            • 虽然这可能是真的,但类型提示可以让生活变得更加美好,并帮助您避免愚蠢的错误。见:python.org/dev/peps/pep-0484
            • Python 有可选的类型检查。这既不符合问题的精神,也不符合语言的意图和能力。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-03-17
            • 1970-01-01
            相关资源
            最近更新 更多