Mendeklarasikan kelas/antarmuka Python menggunakan daftar nama atribut [duplikat]

Di Python, apakah ada cara untuk mendeklarasikan antarmuka seperti kelas dengan daftar atribut, selain dari namatuple? Saya ingin membuat mixin dari daftar nama atribut. Upaya terbaik saya sejauh ini adalah:

# module1.py (user facing)
CUSTOM_FIELDS = ['eye_color', 'shoe_size']


# module2.py (inside my framework)
from collections import namedtuple
from typing import Union


class BasePerson:
  name: Any
  age: Any

CustomMixin = namedtuple('CustomMixin', CUSTOM_FIELDS)

Person = Union[BasePerson, CustomMixin]


# module3.py (user facing)
def f(a: Person):
    # my objective is for IDEs like PyCharm to recognize a.eye_color and a.name
    a.eye_color
    a.name

Ini hampir sama, karena IDE mengenali atributnya. Tapi itu juga menunjukkan semua atribut lain untuk NamedTuple dan tuple (seperti _asdict, dll).

Saya membutuhkan pengguna untuk mendefinisikan atribut sebagai daftar bidang, bukan dengan sintaks kelas reguler. Pertama, untuk konsistensi dengan kerangka saya yang lain. Kedua, menggunakan sintaks kelas akan membuka sekaleng worm, karena Anda dapat melakukan segala macam hal di kelas yang tidak diizinkan oleh kerangka kerja saya.

Saya juga mencoba:

class CustomMixin:
  __slots__ = CUSTOM_FIELDS

Tapi PyCharm tidak mengenali ini. Saya juga melihat typing.Protocol tetapi itu juga memerlukan deklarasi kelas.


person Chris    schedule 18.02.2021    source sumber
comment
dataclasses.make_dataclass() dapat melakukan ini; lihat duplikatnya untuk gambaran umum tentang apa yang dilakukan modul dataclasses.   -  person Martijn Pieters    schedule 18.02.2021
comment
dataclass diperkenalkan setelah Python3.7   -  person Menglong Li    schedule 18.02.2021
comment
@MartijnPieters Jadi ini pada dasarnya seperti type(_, _, _) tetapi untuk kelas data, bukan?   -  person DeepSpace    schedule 18.02.2021
comment
@DeepSpace: ini sedikit lebih terlibat dari sekedar type(); input divalidasi, nama tanpa petunjuk tipe diberi petunjuk typing.Any, dan dekorator @dataclass() diterapkan pada hasil untuk menghasilkan metode seperti __init__ dan __repr__, bergantung pada argumen yang digunakan.   -  person Martijn Pieters    schedule 18.02.2021
comment
@DeepSpace: dan alih-alih memanggil type(), fungsinya menggunakan types.new_class(), untuk menangani metaclass khusus dengan benar.   -  person Martijn Pieters    schedule 18.02.2021
comment
@MenglongLi: backport resmi mendukung Python 3.6. Untuk rilis lama, gunakan attrs, yang mendukung Python 2.7, 3.5, dan yang lebih baru.   -  person Martijn Pieters    schedule 18.02.2021