Skip to main content
 首页 » 编程设计

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

2025年05月04日13qlqwjy

例如这样两者都能起作用 - 可能吗?

(val,VAL2) = func(args)  
val = func(args) 

val 不是元组

例如,我希望这些适用于我的自定义对象 something

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

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

编辑:从下面的答案可以看出,这真的不应该这样做。

请您参考如下方法:

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

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) 

例如。查看使用此模式的字典对象。 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 

可用的类似:

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 

免责声明:这是非常骇人听闻的错误做法,如果其他程序员在实际代码中看到它,将导致他们追捕您并杀死您。仅适用于 cpython(如果有)。 永远不要在生产代码中使用它(或者就此而言,可能是任何代码)。