有时需要检查python中的参数。例如,我有一个函数,它接受网络中其他节点的地址作为原始字符串地址,或者接受封装其他节点信息的类节点。
我使用类型(0功能,如:
1 2 3 4
| if type(n) == type(Node):
do this
elif type(n) == type(str)
do this |
这是一个很好的方法吗?
更新1:python 3有函数参数的注释。可以使用以下工具进行类型检查:http://mypy-lang.org/
- 重复stackoverflow.com/questions/378927/…。见答案。
- 另请参见:python ideas-proposal:对函数注释使用mypy语法-by:guido van rossum
- 当前接受的答案不提供解决方案。我推荐Johannes Wei&223;的答案,因为它更好地回答了被问的问题。
- 谢谢@stevenvascellaro,我已经更新了。确实,尽管它提供了一个适合鸭子打字的意见,但乔安妮给出了最好的答案。
使用isinstance()。。。。。。。抽样: </P >
1 2 3 4 5
| if isinstance(n, unicode):
# do this
elif isinstance(n, Node):
# do that
... |
- isInstance()还检查子类。
- isInstance(n,unicode)与python 2.x中的纯str对象不匹配。请与baseString比较,后者与str或unicode都匹配:isInstance(n,baseString)
- wiki.python.org/moin/…—第一段的一部分指出:在python中,程序的职责是使用诸如isInstance()和issubClass()之类的内置函数来测试变量类型和正确使用。python试图避开您的方法,同时为您提供实现强类型检查所需的一切。
- +1以弥补@nosklo的-1。我认为-1人并不酷,因为他们不同意你的实现概念。在许多情况下,类型检查是正确的,特别是因为它是一种重载函数的方法。这在设计API以确保用户做正确的事情时特别有用。
1 2 3 4
| >>> isinstance('a', str)
True
>>> isinstance(n, Node)
True |
- 嗯,在我的应用程序中,类型检查是必须的。我使用olefileio_pl,它返回嵌套列表中的项目列表。如果项是目录类型,则它是嵌套列表中的列表,如果它是文件,则它是字符串。如果不检查字符串,就不可能使用。
你也可以使用吧抓到型,如果必要的检查: </P >
1 2 3 4 5 6 7 8 9 10
| def my_function(this_node):
try:
# call a method/attribute for the Node object
if this_node.address:
# more code here
pass
except AttributeError, e:
# either this is not a Node or maybe it's a string,
# so behavior accordingly
pass |
你可以看到一个实例在本月初在Python中的第二对发电机组(197页在我的版)我相信在cookbook Python。多时报捕集的AttributeError或TypeError是simpler和apparently更快。它也可以工作,最好在这个大陆的,那么你是不知道你到一个特别的继承树(例如,你的对象可以是一个Node或它可能采取的其他面向,已同样的行为作为一种Node)。 </P >
- +1:属性检查不会影响代码的重用,所以它比类型检查要好,尽管基于类型具有不同行为的函数不是一个好主意。
- 只要不同的行为是相似的(至少在概念上是相似的),我看不出有什么大不了的。我们似乎都认为,+(又名操作符+())在数字或字符串上工作是可以的,但实际上它有不同的基于类型的行为。
- 在我的示例中,+运算符当然是由两个不同的函数实现的,它们重载了运算符。不幸的是,由于python中的变量不是类型化的,所以不能仅基于类型重载函数。
你的声音像是在一个"通用函数"这一behaves型有不同的arguments派出所。这是一位怎样样,你会得到一个不同的函数,当你呼叫的一种方法是从一个不同的对象,但是,比只使用第一argument(面向/自)查找到你的函数,而不是使用的全部arguments。。。。。。。 </P >
turbogears使用的东西,这样的方法断如何转化到JSON对象-如果我correctly召回。 </P >
我的一条从IBM使用dispatcher package for this sort of的事: </P >
从那条: </P >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import dispatch
@dispatch.generic()
def doIt(foo, other):
"Base generic function of 'doIt()'"
@doIt.when("isinstance(foo,int) and isinstance(other,str)")
def doIt(foo, other):
print"foo is an unrestricted int |", foo, other
@doIt.when("isinstance(foo,str) and isinstance(other,int)")
def doIt(foo, other):
print"foo is str, other an int |", foo, other
@doIt.when("isinstance(foo,int) and 3<=foo<=17 and isinstance(other,str)")
def doIt(foo, other):
print"foo is between 3 and 17 |", foo, other
@doIt.when("isinstance(foo,int) and 0<=foo<=1000 and isinstance(other,str)")
def doIt(foo, other):
print"foo is between 0 and 1000 |", foo, other |
- 这比使用类型检查IMO对其进行黑客攻击更糟糕,也更不易维护;这是一种试图将过载的函数移植到一种不太适合的语言上的尝试。
- 我喜欢函数重载的C++特性,用这种方法似乎是可能的。我认为它可以提高代码的可读性,因为您不必检查某些类型或值的参数。好帖子!
- 在C++中,这些都是重载函数:空DO(节点和;n);空洞DO(字符串n);
好的,具体的类型检查arguments在Python中是不必要的。它是永远 必要的。 </P >
如果你的代码accepts地址为rawstring或作为一个Node面向,你的 设计是破碎的。 </P >
这是从的事实是,如果你不知道已经在一型的 面向在你自己的程序的,当时你正在做的事情就已经错了。 </P >
具体的类型检查hurts代码重用和性能的影响。一种函数 这performs不同的事情depending型的"面向通过 易卒中型是错误的和有一个行为的努力来理解和maintain。。。。。。。 </P >
你有saner下面的选项: </P >
做一个Node面向constructor那accepts rawstrings,或一个函数 这converts串在Node对象。让你的函数的假设 通过argument是一个Node面向。这是通的,如果你需要一个通 字符串的函数,你就做: </P >
1
| myfunction(Node(some_string)) |
那是你的最佳选择,它是干净的,容易的理解和maintain。。。。。。。 任何人阅读的代码immediatelly understands什么是发生, 和你不要typecheck。。。。。。。 </P >
这两个函数,一个是accepts Node对象和一个accepts… rawstrings。。。。。。。你能让一个呼叫其他internally,在最 convenient通(myfunction_str可以创建一个面向Node和呼叫 myfunction_node,或其他办法左右)。 </P >
麦克Node对象有一个__str__方法和在你的函数, 呼叫str()对收到的argument。。。。。。。那通你总是得到一个字符串 通过coercion。。。。。。。 </P >
在任何情况下,不typecheck。。。。。。。这是完全不必要的和有只读 downsides。。。。。。。重构你的代码,而不是在一路,你不需要typecheck。。。。。。。 你只有在做得到的利益),都在短期和长期运行。 </P >
- 如果node和str都不是您自己的实现(它们可能不在这里),那么就不需要添加像str这样的方法来支持您的可选行为(*)。在这种情况下,类型检查是一个明显且可接受的选择,比必须包装每个str实例要好。
- (*:除非你建议猴子修补…)
- @波宾斯:请注意,添加str是我提供的第三个选项。在这种情况下,我会和第一个一起去。
- 检查通过线路接收到的数据的结构如何(例如,JSON)?我宁愿失败得更快,错误也更明显,而不是稍后在我的代码中假定存在一个特定的信息片段。思想?
- 基本上没有必要…从来没有。如果使用python定义远程接口(例如xmlrpc),那么在接口上进行强类型检查是一个好主意,即使只是为了阻止使用强类型语言(和思维方式)的rpc调用方的大脑/脾气爆发。
- 这是否意味着像matplotlib这样接受许多函数的不同参数类型的库做得不对?
- @submitteddied:不可以。您可以在一个参数中接受多种类型。错误的部分是检查您得到的类型,这样您就可以根据类型做不同的事情。
- @提交:如果你做同样的事情,不管类型是什么,那么可以把不同的类型作为参数。
- 在一个拥有不止一个开发人员的项目中,插入一些类型断言是很有用的,只是为了省去传递的参数和让代码自我解释。
- @戴尔特:我不同意,我和很多人一起工作,最好的方法是记录。将额外的代码用作文档感觉像是浪费,写docstring比写类型断言更好
- 在Python中,程序的职责是使用诸如isInstance()和issubClass()之类的内置函数来测试变量类型和正确使用。python试图避开您的方法,同时为您提供实现强类型检查所需的一切。-wiki.python.org/moin/&hellip;
- @Nosklo:你在其他问题上都会说"-1-别提检查类型是个坏主意"。但是在您的例子中,-1,它没有提到在哪里进行类型检查是一个正式的坏主意。这听起来更像是一种观点,或是借鉴了其他一些语言概念。似乎其他人正在指出支持类型检查行为的官方声明。
- 如果这是一个坏主意,那么inspect模块可能不是公共标准库。还有更多检查类型的方法。也可以使用"duck-typing"在接口上执行getattr检查,而不是类型检查。有时是必要的。
- 那么,为什么Python有类型检查工具呢?python编码人员比python的开发人员了解更多吗?
- @JDI我说过为什么这是个坏主意。它会损害代码重用并降低性能。它丢弃了一些程序员已经拥有的信息,并试图再次猜测它。
- @dman python是我的首选语言,但它并不完美。
- 这是一个非常主观的回答,我很惊讶它被接受为答案。寻找答案?看看下面的答案,当使用具有对象的大型面向对象系统时,类型检查/强制非常有用(…(非常特殊的类型)互相交流。虽然我不提倡类型检查内置类型(list、str等),但是允许类/对象使用/依赖于其他类/对象的定义行为是oop 101。imho将所有类型检查都注销为"糟糕的实践",只会限制作为OOP程序员的能力/能力。
- 但是我同意你,@nosklo,关于你所说的代码重用/可维护性等的大部分内容…特别是:"根据传递的对象的类型,具有执行不同操作的函数是容易出错的,并且具有难以理解和维护的行为。"对。拜托。不要这样做:)
- 这个回答中很不必要的尖酸刻薄的语气。这是一个观点,也包含了很多情感包袱。
- 如果您使用一个函数并意外地传递了一个错误的数据类型,则会得到一条合理的错误消息,说明"传递的序列和期望的函数是一个数据帧",这比其他地方的"序列不存在组件列"要好得多。或者更糟的是,这个函数正好可以工作,但是做了错误的事情,您只能在以后捕获错误。
- 用户面临着许多主流和流行的API和包,它们接受各种简单的域参数作为字符串。这是不现实的建议,即使技术上是正确的。
- 我认为这里的很多人都没有注意到作者在运行时谈论的类型检查,而不像大多数类型语言那样在编译时谈论。静态类型检查绝对没有这里提到的缺点。也许如果事先明确地说出来,就可以避免很多混乱。