Dalam Python 3.4+, mengapa saya harus menggunakan namestuple di atas SimpleNamespace ketika tidak menggunakan dict, mereka tampak sangat mirip


11

Pada satu titik atau lain Anda mungkin menemukan fungsi dengan banyak argumen. Terkadang masuk akal untuk menggabungkan beberapa argumen menjadi super-argumen. Saya sering melakukan ini dengan dikte, tetapi sekarang saya mencari cara yang lebih baik untuk melakukannya.

Saya ingin berbelok ...

def do_something(ax, ay, az, bu, bv, c):
    # Do something

... menjadi ...

def do_something(a, b, c):
    # Do something

... di mana adan bberisi subvariasinya.

Salah satu cara untuk melakukan ini adalah dengan melakukan:

A = namedtuple('A', 'x, y, z')
a = A(ax, ay, az)
B = namedtuple('B', 'u, v')
b = B(bu, bv)

Namun, ini tampaknya lebih sederhana:

a = SimpleNamespace(x=ax, y=ay, z=az)
b = SimpleNamespace(u=bu, v=bv)

Apa kekurangannya? Fakta bahwa adan btidak diketik dengan baik? Mereka bukan objek A dan B?

(Btw, jangan khawatir tentang nama variabel. Saya biasanya tidak menggunakan nama variabel pendek.)


1
Tidak ada kekurangannya, itu hanya hal yang berbeda. Untuk pemula, nama domain tidak dapat diubah sementara ruang nama bisa berubah. Apakah bisa berubah lebih baik atau lebih buruk daripada tidak bisa diubah? Tergantung pada apa yang Anda butuhkan atau inginkan, dalam banyak kasus itu tidak masalah. Fungsi Anda mungkin akan bekerja dengan objek apa pun dengan atribut yang diperlukan, cara membuatnya terserah pemanggil.
Berhentilah melukai Monica

@Goyo Terima kasih. "Kelemahan" adalah cara kikuk mengatakannya. Saya tidak bermaksud mengatakan bahwa yang satu secara inheren lebih baik daripada yang lain. Hanya menginginkan pro dan kontra. Terima kasih lagi.
André Christoffer Andersen

1
bukankah seharusnya baris ke-4 terlihat seperti "b = B (bu, bv)"?
Alen Siljak

@AlenSiljak Ya itu seharusnya. Saya akan memperbaikinya sekarang.
André Christoffer Andersen

Jawaban:


21

SimpleNamespacepada dasarnya hanya fasad yang bagus di atas kamus. Ini memungkinkan Anda untuk menggunakan properti alih-alih kunci indeks. Ini bagus karena sangat fleksibel dan mudah dimanipulasi.

Kelemahan dari fleksibilitas itu adalah bahwa ia tidak menyediakan struktur apa pun. Tidak ada yang menghentikan seseorang untuk menelepon SimpleNamespace(x=ax, y=ay)(dan del a.zbeberapa saat kemudian). Jika instance ini diteruskan ke fungsi Anda, pengecualian terjadi ketika Anda mencoba mengakses bidang.

Sebaliknya, namedtuplememungkinkan Anda membuat tipe terstruktur. Jenis akan memiliki nama dan akan tahu bidang apa yang seharusnya dimiliki. Anda tidak akan dapat membuat instance tanpa masing-masing bidang itu dan mereka tidak dapat dihapus nanti. Selain itu, instance tidak dapat diubah, jadi Anda akan tahu bahwa nilai di a.xakan selalu sama.

Terserah Anda untuk memutuskan apakah Anda membutuhkan fleksibilitas yang SimpleNamespacememberi Anda, atau jika Anda lebih suka memiliki struktur dan jaminan yang disediakan oleh namedtuple.


2

Saya sangat suka jawaban tentang terstruktur versus tidak, jadi saya hanya memberikan contoh nyata di bawah ini.

SimpleNamespaceakan menerima kunci yang dimulai dengan _. Jika Anda mencari cara cepat dan mudah untuk mengubah, katakanlah, JSON Anda tidak mengontrol menjadi objek dengan nama bidang, ini sangat berguna:

d = {"_id": 2342122, "text": "hi there!"} # Elasticsearch gives this id!
e = SimpleNamespace(**d) # works
Name = namedtuple("Name", sorted(d)) # ValueError so we can't do Name(**d)

Perhatikan di atas bahwa Anda dapat melihat bahwa namedtuplememberi kami objek tambahan yang SimpleNamespacetidak akan pernah ada. Masing SimpleNamespace- masing benar-benar "kepingan salju yang unik", sedangkan namedtupleada tanpa pernah menjadi instantiated dengan nilai-nilai konkret. Di mana pun Anda membutuhkan abstraksi yang menggeneralisasi nilai-nilai konkret, Anda mungkin harus memilihnya.


1

Ringkasan dari SimpleNamespace

Ini memungkinkan untuk menginisialisasi atribut sambil membangun objek:

sn = SimpleNamespace(a=1, b=2)

Ini memberikan dibaca

repr(): eval(repr(sn)) == sn

Ini menimpa perbandingan default. Alih-alih membandingkan dengan id(), itu membandingkan nilai atribut.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.