如何在python中使用备用返回值签名编写函数?(next()替代迭代器)

Evg*_*eny 1 python

例如,这些都可行 - 是否可能?

(val,VAL2) = func(args) 
val = func(args)
Run Code Online (Sandbox Code Playgroud)

其中VAL不是一个元组

例如,我想这对于我的自定义对象工作的东西

for item in something:
    do_item(item) #where again item - is not a tuple

for (item,key) in something:
    do_more(key,item)
Run Code Online (Sandbox Code Playgroud)

我认为我需要以两种不同的方式实现next()函数...

编辑:如下面的答案所示,这不应该真的完成.

Bri*_*ian 7

如果你的意思是,函数可以根据调用者期望的返回类型采取不同的行动,答案是否定的(bar非常讨厌字节码检查).在这种情况下,您应该在对象上提供两个不同的迭代器,并编写如下内容:

for item in something:  # Default iterator: returns non-tuple objects
    do_something(item)

for (item,key) in something.iter_pairs(): # iter_pairs returns different iterator
    do_something_else(item, key)
Run Code Online (Sandbox Code Playgroud)

例如.查看使用此模式的字典对象. for key in mydict迭代字典键. for k,v in mydict.iteritems()迭代(键,值)对.

[编辑]以防万一有人想通过"严重讨厌的字节码检查"看到我的意思,这里是一个快速实现:

import inspect, opcode

def num_expected_results():
    """Return the number of items the caller is expecting in a tuple.

    Returns None if a single value is expected, rather than a tuple.
    """
    f = inspect.currentframe(2)
    code = map(ord, f.f_code.co_code)
    pos = f.f_lasti
    if code[pos] == opcode.opmap['GET_ITER']: pos += 1 # Skip this and the FOR_ITER
    if code[pos] > opcode.EXTENDED_ARG: pos +=5
    elif code[pos] > opcode.HAVE_ARGUMENT: pos +=3
    else: pos += 1
    if code[pos] == opcode.opmap['UNPACK_SEQUENCE']:
        return code[pos+1] + (code[pos+2] << 8)
    return None
Run Code Online (Sandbox Code Playgroud)

可用类似于:

class MagicDict(dict):
    def __iter__(self):
        if num_expected_results() == 2:
            for k,v in self.iteritems():
                yield k,v
        else:
            for k in self.iterkeys(): 
                yield k

d=MagicDict(foo=1, bar=2)

print "Keys:"
for key in d:
    print "   ", key
print "Values"    
for k,v in d:
    print "   ",k,v
Run Code Online (Sandbox Code Playgroud)

免责声明:这是令人难以置信的hacky,非常糟糕的做法,如果他们在实际代码中看到它,导致其他程序员追捕并杀死你.仅适用于cpython(如果有). 切勿在生产代码中使用它(或者就此而言,可能是任何代码).


nos*_*klo 5

你有尝试过吗?有用。

def myfunction(data):
    datalen = len(data)
    result1 = data[:datalen/2]
    result2 = data[datalen/2:]
    return result1, result2


a, b = myfunction('stuff')
print a
print b

c = myfunction('other stuff')
print c
Run Code Online (Sandbox Code Playgroud)

实际上,没有“返回签名”之类的东西。所有函数都返回一个对象。似乎您返回的不止一个,但实际上您将它们包装到了一个容器元组对象中。