【问题标题】:Multiplying a tuple by a scalar将元组乘以标量
【发布时间】:2010-12-19 09:54:15
【问题描述】:

我有以下代码:

print(img.size)
print(10 * img.size)

这将打印:

(70, 70)
(70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70)

我想打印:

(700, 700)

有没有不用写的方法:

print(10 * img.size[0], 10 * img.size[1])

PS:img.size 是 PIL 图像。我不知道在这种情况下这是否重要。

【问题讨论】:

  • (10 * img.size[0], 10 * img.size[1]) 有什么问题?我不明白为什么你需要过度设计像 2 个整数相乘这样简单的东西。请注意,这个元组总是只有两个元素!
  • 我没有过度设计。我在问是否有更好,更简单的方法。再次阅读我的帖子。
  • @paprika: ...因为有问题的元组可能没有已知的长度。在这种情况下它确实如此(就像它在导致我提出这个问题的情况下所做的那样),但是编码一个假定的元组长度,重复标量 n 次,并且必须得到 n 正确的索引很笨拙,可以直接避免。

标签: python python-imaging-library


【解决方案1】:

解决方案:

import numpy as np
set1=(70, 70)
tuple(2*np.array(set1)) 

解释:arrays 使直接标量乘法成为可能。因此这里称为set1tuple 被转换为array。我假设您希望继续使用tuple,因此我们将array 转换回tuple

此解决方案是为了避免显式和冗长的for 循环。我不知道它是否更快,或者两种情况下是否会发生完全相同的事情。

【讨论】:

  • 据我所知,这在 Python 2 或 3 中不起作用。我假设array 来自array 模块? Python 需要一个字符作为array 的第一个参数,因此只传入一个元组将失败并返回TypeError: array() argument 1 or typecode must be char (string or ascii-unicode with length 1), not tuple。你能用一个更完整的例子来扩展这个吗?
  • 我认为它是一个 numpy 数组?
【解决方案2】:

只是概述

import timeit

# tuple element wise operations multiplication

# native
map_lambda = """
a = tuple(range(10000))
b = tuple(map(lambda x: x * 2, a))
"""

# native
tuple_comprehension = """
a = tuple(range(10000))
b = tuple(x * 2 for x in a)
"""

# numpy
using_numpy = """
import numpy as np
a = tuple(range(10000))
b = tuple((np.array(a) * 2).tolist())
"""

print('map_lambda =', timeit.timeit(map_lambda, number=1000))
print('tuple_comprehension =', timeit.timeit(tuple_comprehension, number=1000))
print('using_numpy =', timeit.timeit(using_numpy, number=1000))

我的机器上的计时

map_lambda = 1.541315148000649
tuple_comprehension = 1.0838452139996662
using_numpy = 1.2488984129995515

【讨论】:

    【解决方案3】:

    如果您正在编写一堆代码,但又不想要更复杂的向量库,那就把事情简单化...

    class V(tuple):
        '''A simple vector supporting scalar multiply and vector add'''
        def __new__ (cls, *args):
            return super(V, cls).__new__(cls, args)
        def __mul__(self,s):
            return V( *( c*s for c in self) )
        def __add__(self,s):
            return V( *( c[0]+c[1] for c in zip(self,s)) )
        def __repr__(self):
            return "V" + super(V, self).__repr__()
    
    # As long as the "vector" is on the left it just works
    
    xaxis = V(1.0, 0.0)
    yaxis = V(0.0, 1.0)
    print xaxis + yaxis      # => V(1.0, 1.0)
    print xaxis*3 + yaxis*5  # => V(3.0, 5.0)
    print 3*xaxis            # Broke, => (1.0, 0.0, 1.0, 0.0, 1.0, 0.0)
    

    “V”实例在其他方面的行为就像元组一样。这要求所有“V”实例都使用相同数量的元素创建。例如,您可以添加到 __new__

    if len(args)!=2: raise TypeError('Must be 2 elements')
    

    强制所有实例都是二维向量......

    【讨论】:

      【解决方案4】:

      您正在尝试将函数作为一个整体应用于 Tuple。 您需要将其应用于单个元素并返回一个新元组。

      newTuple = tuple([10*x for x in oldTuple])
      

      请记住,您不能更改元组。

      【讨论】:

        【解决方案5】:

        与之前的答案一致,但使用 numpy:

        import numpy as np
        result = tuple(10*np.array(img.size))
        

        【讨论】:

          【解决方案6】:

          除了品种什么都不添加..

          import operator
          img_size = (70, 70)
          map(operator.mul, img_size, len(img_size)*(10,))
          

          【讨论】:

            【解决方案7】:

            如果您经常遇到这个问题并且使用较大的元组或列表,那么您可能想要使用numpy 库,它允许您对数组进行各种数学运算。但是,在这种简单的情况下,这完全是矫枉过正。

            【讨论】:

            • 虽然对于 simple 示例来说使用 numpy 有点过头了,但问题的关键似乎是“python 是否提供了一种可以用数学简单地表达模拟操作的方法? "我的意思是如果你有一个矩阵 A = [ 70 70 ] 那么 2A = [ 140 140 ]。
            【解决方案8】:

            pythonic 方法是使用列表推导:

            y = tuple([z * 10 for z in img.size])
            

            另一种可能是:

            y = tuple(map((10).__mul__, img.size))
            

            【讨论】:

            • 第二个太棒了……哈哈。
            • 这两个例子都没有抓住问题的重点。两者都迫使程序员采用一个简单的想法(标量时间矩阵乘法)并解构它。
            • @ZekeHansell “强迫”程序员解构他的想法有什么问题?解构问题以便用代码封装解决方案是编程的本质。以上所有答案都解决了提问者所问的问题,以解决问题核心的方式,并以可重复、可重用的代码位(顺便说一句,所有单行代码)解决它。代码可以很容易地扩展以接受任意常数来执行简单的标量向量乘法,并且提问者获得了一种新方法,以及他/她的腰带上的新工具。那么问题出在哪里?
            【解决方案9】:

            可能还有比这更简单的方法,但是

            print map(lambda x: 10*x, img.size)
            

            几乎可以满足您的需求,尽管它打印为列表而不是元组。如果您希望将 map 调用包裹在 tuple(map...) 中,则将其打印为元组(括号而不是方括号)。

            【讨论】:

            • lambda函数可以用'map((10).__mul__, img.size)'代替
            【解决方案10】:
            img.size = tuple(i * 10 for i in img.size)
            

            【讨论】:

              【解决方案11】:

              你可以试试这样的:

              print [10 * s for s in img.size]
              

              它将为您提供一个新列表,其中包含您在元组中的所有元素乘以 10

              【讨论】:

                【解决方案12】:

                可能是更好的方法,但这应该可行

                tuple([10*x for x in img.size])
                

                【讨论】:

                • 稍微好一点:tuple(10*x for x in img.size)
                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2011-04-22
                • 1970-01-01
                • 1970-01-01
                • 2021-12-15
                • 1970-01-01
                相关资源
                最近更新 更多