Soru Aynı Uzunluktaki Tupllerden Değerler Ekleme


Pygame kullanarak yazdığım bir grafik programında, aşağıdaki gibi bir koordinatı temsil eden bir tuple kullanıyorum: (50, 50).

Bazen, koordinattaki değişikliği temsil eden (3, -5) gibi bir başka tuple döndüren bir işlevi çağırırım.

Değişiklik değerini koordinat değerine eklemenin en iyi yolu nedir? Koordinat + = değişim gibi bir şey yapabilsem hoş olurdu, ama bu iki tuplesin (50, 50, 3, -5) bir şeye benzeyeceği anlaşılıyor. İlk değeri 1. değere ve 2. ila 2.'ye eklemek ve sonuçta ortaya çıkan bir tuple dönmek yerine.

Şimdiye kadar bu oldukça yorucu yöntemi kullanıyorum: koordinat = (koordinat [0] + değiştir [0], koordinat [1] + değiştir [1])

Aynı uzunluktaki iki kopyanın değerlerini bir araya getirmek için daha iyi, daha özlü bir yöntem nedir? Tupllerin keyfi bir uzunluktan veya özellikle bir önceki yöntemi daha da yorucu hale getirecek uzun bir uzunluğa sahip olmaları durumunda nasıl yapılacağını bilmek önemlidir.


16
2017-07-23 05:15


Menşei




Cevaplar:


Eh, bir yol olurdu

coord = tuple(sum(x) for x in zip(coord, change))

Çok fazla matematik yapıyorsanız, kullanarak araştırmak isteyebilirsiniz. NumPyçok daha güçlü dizi desteği ve daha iyi performansa sahip.


23
2017-07-23 05:29



Numpy önermek için +1 - Alice Purcell


Listeyi anlama muhtemelen daha okunabilir, ama burada başka bir yol var:

>>> a = (1,2)
>>> b = (3,4)
>>> tuple(map(sum,zip(a,b)))
(4,6)

11
2017-07-23 05:26



Anlama / üreteci ifadesini daha okunabilir buluyorum, ama eminim ki zihinleri daha çok "lispily" olan insanlar harita çözümünü daha net bulacaktır. - John Y
Ben kendimce çok tatlıyım, ama çoğunlukla liste anlamalarını tercih ediyorum, çünkü Haskell de benim düşünceme göre yabancıdan uzak. - Alex Martelli
Zip bunun için gerçekten gerekli: >>> operatör ithalatı ekle >>> a = (1, 2) >>> b = (3, 4) >>> tuple (harita (ekle, a, b)) ( 4, 6) >>> - Russel Winder


Bu, Python'u kendim öğrendiğim gibi devam eden bir çalışma. Burada sınıfları kullanabilir miyiz, daha sonra bazı işlemleri basitleştirebiliriz. Koordinatları saklamak için bir koordinat sınıfı kullanmayı öneriyorum. Ekleme ve çıkarma işlemini geçersiz kılar, böylece sadece + ve - operatörlerini kullanarak toplama ve çıkarma işlemini yapabilirsiniz. Tuple temsilini yerleşik bir işlevle alabilirsiniz.

Sınıf

class coord(object):    
    def __init__(self,x,y):
        self.x = x
        self.y = y

    def __add__(self,c):
        return coord(self.x + c.x, self.y + c.y)

    def __sub__(self,c):
        return coord(self.x - c.x, self.y - c.y)

    def __eq__(self,c): #compares two coords
        return self.x == c.x and self.y == c.y

    def t(self): #return a tuple representation.
        return (self.x,self.y)

kullanım

c1 = coord(4,3) #init coords
c2 = coord(3,4)

c3 = c1 + c2    #summing two coordinates. calls the overload __add__
print c3.t()    #prints (7, 7)
c3 = c3 - c1
print c3.t()    #prints (3, 4)
print c3 == c2  #prints True

diğer operatörleri de genişletmek için koordinatınızı geliştirebilirsiniz (daha büyük, daha büyük ..).

Bu versiyonda hesaplamalarınızı yaptıktan sonra, sadece coord.t () 'i söyleyerek tuplleri bekleyen pygame yöntemlerini çağırabilirsiniz. Yine de tuple formunu döndürmek için bir işleve sahip olmanın daha iyi bir yolu olabilir.


3
2017-07-23 06:29





"+" Ve "+ =" davranışınızı elde etmek için kendi sınıfınızı tanımlayabilir ve __add__() yöntem. Aşağıdaki eksik bir örnektir:

# T.py
class T(object):
    def __init__(self, *args):
        self._t = args
    def __add__(self, other):
        return T(*([sum(x) for x in zip(self._t, other._t)]))
    def __str__(self):
        return str(self._t)
    def __repr__(self):
        return repr(self._t)

>>> from T import T
>>> a = T(50, 50)
>>> b = T(3, -5)
>>> a
(50, 50)
>>> b
(3, -5)
>>> a+b
(53, 45)
>>> a+=b
>>> a
(53, 45)
>>> a = T(50, 50, 50)
>>> b = T(10, -10, 10)
>>> a+b
(60, 40, 60)
>>> a+b+b
(70, 30, 70)

EDIT: Daha iyi bir yol buldum ...

T'yi sınıfın bir alt sınıfı olarak tanımlayın ve __new__ ve __add__ yöntemleri. Bu, sınıfla aynı arabirimi sağlar tuple (ama farklı davranışlarda __add__), yani T sınıfının örnekleri, bir tuple beklenen herhangi bir şeye aktarılabilir.

class T(tuple):
    def __new__(cls, *args):
        return tuple.__new__(cls, args)
    def __add__(self, other):
        return T(*([sum(x) for x in zip(self, other)]))
    def __sub__(self, other):
        return self.__add__(-i for i in other)

>>> a = T(50, 50)
>>> b = T(3, -5)
>>> a
(50, 50)
>>> b
(3, -5)
>>> a+b
(53, 45)
>>> a+=b
>>> a
(53, 45)
>>> a = T(50, 50, 50)
>>> b = T(10, -10, 10)
>>> a+b
(60, 40, 60)
>>> a+b+b
(70, 30, 70)
>>> 
>>> c = a + b
>>> c[0]
60
>>> c[-1]
60
>>> for x in c:
...     print x
... 
60
40
60

3
2017-07-23 06:41



T türünüzden tuple dönüştürmek için hala bir fonksiyona ihtiyacınız olmaz. Çünkü bir tipe ihtiyacınız olan yerde bir + b kullanamazsınız. T tipi bir örnek döndürecektir. - Pradeep
@Sizzler: "Yeni" versiyonun endişelerinizi çözdüğünü düşünüyorum. - mhawke
Bu cevap için +1. Pythonic. - Pradeep
Bu harika, kullanarak daha da iyi yapardım zip_longest (aksi takdirde, kısa vektörü eklediğinizde bilgi kaybedersiniz) ve değişiyorsa repr (hala tuple'dan farklı olduğu için). Ayrıca tanımlamanıza gerek yok __new__ hiç, sadece tanımla __init__! - ilya n.
@ilya n: __new__ aynı nesne oluşturma arabirimini sağlamak için geçersiz kılınmış tupleaksi halde üzerinden örnek oluşturamazsınız t = T(1,2,3). örneğin deneyin class T(tuple): pass ve sonra t = T(1,2,3) sana vereceğim TypeError: tuple() takes at most 1 argument (3 given). Görmek docs.python.org/reference/datamodel.html#object.__new__ - mhawke


İki sentim, umarım bu yardımcı olur

>>> coord = (50, 50)
>>> change = (3, -5)
>>> tuple(sum(item) for item in zip(coord, change))
(53, 45)

1
2017-07-23 05:20



Kullanacağım şey buydu, ancak bunu biçimlendirirseniz daha net olacaktır. Cevabınız Bilinmeyen'den daha geneldir, ancak onun gibi biçimlendirilmelidir. - John Y
@John, üzgünüm, kötüyüm. Düğmeye tıklamadan önce ilk satırı ekledim, belki de biçimi bozdu. @Triptych, teşekkürler! - sunqiang


John Y'nin bahsettiği gibi, bu numpy kullanarak oldukça kolaydır.

import numpy as np

x1 = (0,3)
x2 = (4,2)
tuple(np.add(x1,x2))

1
2018-05-27 00:15