Pertanyaan Bagaimana cara menginisialisasi instance dari subclass tuple dengan Python? [duplikat]


Kemungkinan Duplikat:
Menggabungkan Python tuple dengan beberapa argumen __init__ 

Saya ingin mendefinisikan kelas yang mewarisi dari tuple, dan saya ingin dapat memberi contoh menggunakan sintaks yang tidak didukung oleh tuple. Untuk contoh sederhana, katakanlah saya ingin mendefinisikan kelas MyTuple yang mewarisi dari tuple, dan yang dapat saya instantiasikan dengan memberikan dua nilai, x dan y, untuk membuat tuple (saya) (x, y). Saya sudah mencoba kode berikut:

class MyTuple(tuple):
    def __init__(self, x, y):
        print("debug message")
        super().__init__((x, y))

Tetapi ketika saya mencoba, misalnya, MyTuple(2, 3) Saya mendapat kesalahan: TypeError: tuple() takes at most 1 argument (2 given). Sepertinya saya __init__ fungsi itu bahkan tidak disebut (berdasarkan kesalahan yang saya dapatkan dan pada kenyataannya "pesan debug" saya tidak dicetak).

Jadi, apa cara yang tepat untuk melakukan ini?

Saya menggunakan Python 3.2.


8
2017-09-29 12:24


asal


Jawaban:


class MyTuple(tuple):
    def __new__(cls, x, y):
        return tuple.__new__(cls, (x, y))

x = MyTuple(2,3)
print(x)
# (2, 3)

Salah satu kesulitan menggunakan super adalah Anda tidak mengontrol metode kelas mana dari nama yang sama yang akan dipanggil berikutnya. Jadi semua metode kelas harus berbagi tanda panggilan yang sama - setidaknya jumlah item yang sama. Karena Anda mengubah jumlah argumen yang dikirim ke __new__, Anda tidak dapat menggunakan super.


Atau seperti yang disarankan Lattyware, Anda bisa mendefinisikan namatuple,

import collections
MyTuple = collections.namedtuple('MyTuple', 'x y')

p = MyTuple(2,3)
print(p)
# MyTuple(x=2, y=3)
print(p.x)
# 2

12
2017-09-29 12:40



pendekatan lain adalah merangkum sebuah tuple daripada mewarisi darinya:

>>> class MyTuple(object):
    count = lambda self, *args: self._tuple.count(*args)
    index = lambda self, *args: self._tuple.index(*args)
    __repr__ = lambda self: self._tuple.__repr__()
    # wrap other methods you need, or define them yourself,
    # or simply forward all unknown method lookups to _tuple
    def __init__(self, x, y):
        self._tuple = x,y


>>> x = MyTuple(2,3)
>>> x
(2, 3)
>>> x.index(3)
1

Seberapa praktis ini, tergantung pada seberapa banyak kemampuan dan modifikasi yang Anda butuhkan, dan apakah Anda perlu memilikinya isinstance(MyTuple(2, 3), tuple).


1
2017-09-29 13:14