Умножение кортежа на скаляр

У меня есть следующий код:

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. Не знаю, имеет ли это значение в данном случае.


person devoured elysium    schedule 23.11.2009    source источник
comment
Что не так с (10 * img.size[0], 10 * img.size[1])? Я не понимаю, почему вам нужно усложнять что-то такое простое, как умножение двух целых чисел. Обратите внимание, что этот кортеж всегда будет состоять только из двух элементов!   -  person paprika    schedule 23.11.2009
comment
Я не переусердствую. Я спрашиваю, есть ли более приятный и простой способ. Прочтите мой пост еще раз.   -  person devoured elysium    schedule 23.11.2009
comment
@paprika: ... потому что рассматриваемый кортеж может не иметь известной длины. В этом случае это так (как и в случае, который привел меня к этому вопросу), но кодирование для предполагаемой длины кортежа, повторение скаляра n раз и получение n< /i> индексирует правильно достаточно неуклюже, чтобы избежать, если это возможно.   -  person J0e3gan    schedule 23.02.2015


Ответы (11)


Может быть, это лучше, но это должно работать

tuple([10*x for x in img.size])
person Hannes Ovrén    schedule 23.11.2009
comment
Чуть лучше: tuple(10*x for x in img.size) - person Vegard; 26.08.2015

Способ pythonic будет использовать понимание списка:

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

Другой способ может быть:

y = tuple(map((10).__mul__, img.size))
person ChristopheD    schedule 23.11.2009
comment
Второй потрясающий... ха-ха. - person Mike Boers; 26.11.2009
comment
Ни один из примеров не отражает суть вопроса. Оба вынуждают программиста брать простую идею (умножение скалярных матриц на умножение) и деконструировать ее. - person Zeke Hansell; 08.12.2014

Решение:

set1=(70, 70)
tuple(2*array(set1))

Объяснение: arrays сделать возможным прямое скалярное умножение. Следовательно, tuple, называемое здесь set1, преобразуется в array. Я предполагаю, что вы хотите продолжать использовать tuple, поэтому мы преобразуем array обратно в tuple.

Это решение позволяет избежать явного и многословного цикла for. Я не знаю, быстрее или в обоих случаях происходит одно и то же.

person Mukul Atri    schedule 02.07.2014
comment
Насколько я могу судить, это не работает в 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. Можете ли вы расширить это с помощью более полного примера? - person Kumba; 15.08.2017
comment
Я предполагаю, что это массив numpy? - person InstaK0; 01.06.2020

Вероятно, есть более простой способ, чем этот, но

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

Будет делать почти то, что вы хотите, хотя печатается как список, а не кортеж. Оберните вызов map внутри tuple(map...), если вы хотите, чтобы он печатался как кортеж (скобки, а не квадратные скобки).

person sparklewhiskers    schedule 23.11.2009
comment
Лямбда-функцию можно заменить на 'map((10).__mul__, img.size)' - person InstaK0; 01.06.2020

Если у вас возникает эта проблема чаще и с большими кортежами или списками, вы можете использовать библиотеку numpy, который позволяет выполнять все виды математических операций над массивами. Однако в этой простой ситуации это было бы полным излишеством.

person nikow    schedule 23.11.2009
comment
В то время как для простого примера было бы излишним использовать numpy, суть вопроса, похоже, заключается в том, предлагает ли python способ простого выражения имитационных операций в математике? Я имею в виду, если у вас есть матрица A = [70 70], тогда 2A = [140 140]. - person Zeke Hansell; 08.12.2014

Простая вещь, если вы пишете кучу кода, но не хотите более сложную векторную библиотеку...

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')

чтобы обеспечить, чтобы все экземпляры были двумерными векторами....

person Marvin    schedule 20.01.2018

Вы можете попробовать что-то вроде этого:

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

Это даст вам новый список со всеми элементами, которые у вас есть в кортеже, умноженными на 10.

person Serge    schedule 23.11.2009

В соответствии с предыдущими ответами, но с использованием numpy:

import numpy as np
result = tuple(10*np.array(img.size))
person user2750362    schedule 08.02.2016

Просто обзор

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
person guesswho    schedule 20.04.2020

ничего не добавляя, кроме разнообразия..

import operator
img_size = (70, 70)
map(operator.mul, img_size, len(img_size)*(10,))
person elbeardmorez    schedule 26.07.2013

Вы пытаетесь применить функцию к Tuple в целом. Вам нужно применить его к отдельным элементам и вернуть новый кортеж.

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

Помните, что вы не можете изменить кортеж.

person user2766147    schedule 15.01.2018