【问题标题】:Do python functions care whether or not you use their output?python函数是否关心你是否使用它们的输出?
【发布时间】:2014-08-02 22:09:08
【问题描述】:

我正在使用 urllib2 向带有参数的服务器发送 GET 和 POST 请求,但是对于某些请求,除了它不是 404 和 urlopen 引发异常之外,我不需要知道服务器的响应在 404s 上。但是,如果我只使用该行:

urllib2.urlopen(address, params)

服务器看不到请求。就好像它永远不会被发送一样。但是,如果我这样做

response = urllib2.urlopen(address, params)

命令通过。我查看了 urllib2 的源码,找到了 urlopen 的函数,如下所示:

def urlopen(url, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
    ...
    return _opener.open(url, data, timeout)

当我不存储 urlopen 的输出时,_opener.open 函数似乎没有运行。如果我不要求函数的输出,python 是否只是不执行 return 语句?

【问题讨论】:

  • 由于返回值的赋值发生在函数执行之后,函数不可能知道它的返回值是否被赋值给某个东西。正如 Martijn 所说,您的错误在别处。
  • @MartijnPieters 这不完全正确,有很多函数使用yield,除非你用它做点什么,否则不会做任何有意义的事情。
  • @Soviero:这些是生成器函数。他们确实返回一些东西,一个生成器对象。但是,urlopen() 不是生成器函数。
  • @MartijnPieters 是的。但我怀疑 OP 会做出这种区分。
  • @MartijnPieters 我知道他的函数不是生成器,只是指出一个异常。

标签: python python-2.7 urllib2


【解决方案1】:

不,函数的行为不会根据您是否存储对返回值的引用或只是忽略它而改变。该函数在返回值被存储或忽略之前执行。如果函数调用导致引发异常,则根本没有返回值。

您对发生的事情的分析不正确,问题出在其他地方。

不过,您自己也可以轻松测试:

>>> def foo():
...     print "foo() called"
... 
>>> def bar():
...     return foo()
... 
>>> bar()
foo() called
>>> result = bar()
foo() called

或者,使用 urllib2.urlopen() 本身,使用 http://httpbin.org/status/404 来触发 404 Not Found 响应:

>>> import urllib2
>>> response = urllib2.urlopen('http://httpbin.org/status/404')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/mj/Development/Library/buildout.python/parts/opt/lib/python2.7/urllib2.py", line 127, in urlopen
    return _opener.open(url, data, timeout)
  File "/Users/mj/Development/Library/buildout.python/parts/opt/lib/python2.7/urllib2.py", line 410, in open
    response = meth(req, response)
  File "/Users/mj/Development/Library/buildout.python/parts/opt/lib/python2.7/urllib2.py", line 523, in http_response
    'http', request, response, code, msg, hdrs)
  File "/Users/mj/Development/Library/buildout.python/parts/opt/lib/python2.7/urllib2.py", line 448, in error
    return self._call_chain(*args)
  File "/Users/mj/Development/Library/buildout.python/parts/opt/lib/python2.7/urllib2.py", line 382, in _call_chain
    result = func(*args)
  File "/Users/mj/Development/Library/buildout.python/parts/opt/lib/python2.7/urllib2.py", line 531, in http_error_default
    raise HTTPError(req.get_full_url(), code, msg, hdrs, fp)
urllib2.HTTPError: HTTP Error 404: NOT FOUND
>>> urllib2.urlopen('http://httpbin.org/status/404')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/mj/Development/Library/buildout.python/parts/opt/lib/python2.7/urllib2.py", line 127, in urlopen
    return _opener.open(url, data, timeout)
  File "/Users/mj/Development/Library/buildout.python/parts/opt/lib/python2.7/urllib2.py", line 410, in open
    response = meth(req, response)
  File "/Users/mj/Development/Library/buildout.python/parts/opt/lib/python2.7/urllib2.py", line 523, in http_response
    'http', request, response, code, msg, hdrs)
  File "/Users/mj/Development/Library/buildout.python/parts/opt/lib/python2.7/urllib2.py", line 448, in error
    return self._call_chain(*args)
  File "/Users/mj/Development/Library/buildout.python/parts/opt/lib/python2.7/urllib2.py", line 382, in _call_chain
    result = func(*args)
  File "/Users/mj/Development/Library/buildout.python/parts/opt/lib/python2.7/urllib2.py", line 531, in http_error_default
    raise HTTPError(req.get_full_url(), code, msg, hdrs, fp)
urllib2.HTTPError: HTTP Error 404: NOT FOUND

这两个操作都会引发异常。

【讨论】:

  • 该测试并没有真正的帮助,因为(理论上)可能有特殊的检查方法可以告诉您是否存储了返回值。
  • @poke:你可以使用__del__ 来检测引用计数是否下降到0,当然。但是,当调用者要丢弃返回对象时,Python 作为一种语言不会通过不执行 return 表达式来“优化”。
  • 我显然知道这是不可能的。我的观点是——正如我所说——理论上可能有什么东西;如果不知道这一点,你就无法真正编写一个测试它是否有效的示例。
  • @poke:你的意思是即使一个简单的实验可以证明他们的假设是错误的,OP 也无法保证他们的假设是错误的?
  • 不,我的意思是在urlopen 实现中的某处可能存在一些假设的abortFunctionIfReturnValueIsDiscarded 语句,这正是OP 认为会发生的事情。现在,如果您不知道该语句,则无法对其进行测试。
【解决方案2】:

无论你是否使用返回值,Python 都会始终执行 return 语句

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-26
    • 2014-12-03
    • 1970-01-01
    相关资源
    最近更新 更多