【问题标题】:How to specify argument type in a dynamically typed language, i.e. Python?如何在动态类型语言(即 Python)中指定参数类型?
【发布时间】:2011-04-14 18:42:44
【问题描述】:

有没有类似的Java

String myMethod (MyClass argument) {...}

在 Python 中?

谢谢你,托马斯

【问题讨论】:

  • 如果有,该语言将不会被动态键入。
  • 学习 Java 最好的事情之一就是不必猜测类型,有时当文档记录不充分时,您可以像拼图一样将它们拼凑在一起,只要知道您需要构造 A 类,并且把它喂给 B 班让事情正常工作真是太好了。这是我最不喜欢动态语言的事情之一——我坚信在代码中添加帮助有助于节省每个人的下线时间,即使它会让你多输入 10 个字符。
  • @delnan Common Lisp 具有动态类型并允许声明类型。它是可选的,但如果您指定类型,编译器可以生成非常高效的代码。
  • @gpeche:我怀疑这是否等同于 Java 类型注释——它们是在编译时强制执行的;但是在动态类型语言中(甚至在具有变体类型的静态类型语言中),变量(/变体)在给定时间引用的值的类型无法通过静态分析确定->只能检查在运行时。
  • @delnan 不等价,但相当不错,因为它可以在编译时生成大量警告。显然语言语义不允许更多,但如果你习惯让你的代码在没有警告的情况下编译,那么它基本上是一样的。

标签: java python dynamic static


【解决方案1】:

没有。 (还有更多内容可以将其四舍五入到 15 个字符...)

【讨论】:

  • 我能告诉我这种方法只适用于 MyClass 的实例吗,换句话说,我怎么能告诉任何使用 myMethod 的人他必须传递一个作为 MyClass 实例的参数?跨度>
  • Tomas,在调试环境中,您可以使用 isinstance() 和 issubclass() 方法通过引发异常或简单的打印消息来发出警报。
  • 还有type()。如下所述,不推荐的做法——unpythonic。
  • 他们不必传递 MyClass 的实例,除非代码专门检查它。它们可以传递具有代码所需方法和属性的任何对象,而不管所述对象的出处。
【解决方案2】:

不,没有。

事实上,检查类型被认为是“非 Pythonic”,因为任何类型的对象都应该被平等对待。

【讨论】:

  • “看起来很像预期的类型”——意思是“支持足够多的必要接口和语义”(在 Google 上搜索“Python”和“duck typing”进行相关讨论)。跨度>
  • 由于 Python 的后期绑定,实际上不可能在执行代码之前告诉 anything 的类型(除了文字)。因此,即使您可以指定类型,也对您没有多大好处。
【解决方案3】:

Python 3.x 具有函数注释,您可以在其中声明参数和返回类型:

def myMethod(argument: MyClass) -> str:
   ...

但目前 Python 对它们没有任何作用,它们仅用作文档。

【讨论】:

  • 这非常有用! +1
【解决方案4】:

我只想说我完全同意类型检查是邪恶的。但是 python 也非常灵活,我很想变坏。此代码将在运行时生效,而不是编译时生效。您可以对返回类型执行类似的操作。这样的东西可能对调试很有用,而且因为它是一个装饰器,所以很容易删除。

为了使它对调试有用,您必须有两种类型具有被访问但具有不同语义的所有相同属性的情况。所以这是一个非常有限的案例。除此之外,当这段代码运行时,无论如何你都会得到一个打字错误。好消息是这几乎从来不是问题。我真的不知道为什么静态类型语言的人对它如此重视。

def types(*args, **kwargs):
    arg_types = args
    kwarg_types = kwargs
    def decorator(f):
        def func(*args, **kwargs):
            for arg, arg_type in zip(args, arg_types):
                if not isinstance(arg, arg_type):
                    raise TypeError("Wrong type suckah")
            for kw, arg in kwargs.items():
                if not isinstance(arg, kwarg_types[kw]):
                    raise TypeError("this is a bad error message")
            return f(*args, **kwargs)
        return func
    return decorator

@types(int, str, bool, flag=bool)
def demo(i, strng, flag=False):
    print i, strng, flag

demo(1, "foo", True)

try:
    demo("foo", "bar", flag="foobar")
except TypeError:
    print "busted on posargs"

try:
    demo(1, "foo", flag=2)
except TypeError:
    print "busted on keyargs"

try:
    demo(1, "foo", 3)
except TypeError:
    print "no use sneaking it through"

【讨论】:

  • 我喜欢创造性地(ab)使用装饰器。
【解决方案5】:

没有。

在 Python 中,它是程序的 使用内置的责任 isinstance() 和 issubclass() 测试变量类型 并正确使用。 Python 试图 在给你的同时别挡道 实现强类型所需的一切 检查。

来自Why is Python a dynamic language and also a strongly typed language。还

在动态类型语言中, 变量只是一个绑定到 a 的值 姓名;该值有一个类型——比如 “整数”或“字符串”或“列表”——但是 变量本身没有。你可以 有一个变量,现在, 持有一个号码,然后分配一个 如果您需要更改它,请给它字符串。

此外,isinstance() 和 issubclass() 可用于进行类型检查。如果要确保参数是 MyClass 类型,可以在函数内部进行检查。您甚至可以对参数的值进行类型转换(如果您有一个接受此类值的构造函数)并将其分配给 my_object。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-19
    相关资源
    最近更新 更多