【问题标题】:Accessing attributes of class instances passed as optional arguments访问作为可选参数传递的类实例的属性
【发布时间】:2015-04-19 08:26:10
【问题描述】:

我有两个具有列表属性的类实例,例如:

foo.range = [1,2]
bar.range = [3,4]

我还有一个接受多个参数的函数:

def permutations(*args):
    return list(itertools.product(arg.range for arg in args))

我希望permutations(foo, bar) 返回这两个(或更多)列表的所有排列(即[(1,3), (1,4) …]),但我实际上得到了[([1, 2],), ([3, 4],)]

有人可以帮助我了解我哪里出错了以及如何实现我希望的结果吗?

【问题讨论】:

    标签: python class python-2.7 instance argument-passing


    【解决方案1】:

    itertools.product 期望可迭代对象作为单独的参数 (itertools.product(*iterables[, repeat])),因此您需要使用 splat(*) 运算符将项目解压缩到其中:

    >>> def permutations(*args):
            return list(itertools.product(*(arg.range for arg in args)))
    
    >>> permutations(foo, bar)
    [(1, 3), (1, 4), (2, 3), (2, 4)]
    

    考虑这个简单的函数,它会收集在 args 中传递给它的所有位置参数:

    >>> def func(*args):
        print args
        print list(args[0])
    ...
    

    当我们向它传递一个生成器表达式时,它被收集为args 元组中的一个单独项目:

    >>> func(x for x in range(5))
    (<generator object <genexpr> at 0x7fda2ab4e780>,)
    [0, 1, 2, 3, 4]
    

    要解决这个问题,我们需要解压缩生成器表达式,而且像 *x for x in range(5) 这样的东西在 Python 中不是有效语法,我们需要在生成器表达式周围添加额外的括号:

    >>> func(*(x for x in range(5)))
    (0, 1, 2, 3, 4)
    # Failed as expected for args[0]
    Traceback (most recent call last):
      File "<ipython-input-215-13af4340dad1>", line 1, in <module>
        func(*(x for x in range(5)))
      File "<ipython-input-213-08941e2a3c06>", line 3, in func
        print list(args[0])
    TypeError: 'int' object is not iterable
    

    【讨论】:

    • 太完美了。感谢您的决议和出色的解释。我非常接近,意识到我需要打开包装,但不知道把星号放在哪里。
    猜你喜欢
    • 2011-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-24
    • 2014-05-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多