我想要创建一个类,而且我不希望它的属性在new之后被修改,所以我选择了NamedTuple,
但我希望它能在初始化后立即做些事情,
所以我希望我能覆盖__init__方法,
但是如果我这样做,我将遇到AttributeError:无法覆盖NamedTuple属性
有任何优雅的代码可以做到这一点吗?
我的实际情况是初始化ttk的样式,如下所示。
import tkinter as tk
from tkinter import ttk
from typing import NamedTuple
class TTKStyle(NamedTuple):
    LF_NORMAL = f'Normal.TLabelframe'
    def init_style(self):
        style = ttk.Style()
        style.configure(self.LF_NORMAL, background='#FFFF00')
        style.configure(f'{self.LF_NORMAL}.Label', foreground='red', background='blue', font=('courier', 15, 'bold'))
root = tk.Tk()
ttk_style = TTKStyle()
ttk_style.init_style()  # <-- I don't want to write this line.
lf_exif = ttk.LabelFrame(root, text='EXIF Tag', style=ttk_style.LF_NORMAL)
lf_exif.pack()
tk.Label(lf_exif, text='ExifVersion').pack()
root.mainloop()发布于 2020-10-06 08:18:31
装潢工
你可以用装饰师帮你。
from typing import NamedTuple, Type
def init_namedtuple(init_func_name):
    def wrap(class_obj: Type[NamedTuple]):
        def new_instance(*args, **kwargs):
            instance_obj = class_obj(*args, **kwargs)
            init_func = getattr(instance_obj, init_func_name)
            if init_func:
                init_func()
            return instance_obj
        return new_instance
    return wrap
@init_namedtuple('init_style')
class TTKStyle(NamedTuple):
    ...__slots__
或者您可以使用普通类并添加__slots__并将init函数直接放在__init__ (see class Person3)上,例如:
from typing import NamedTuple
class Person(NamedTuple):
    NAME: str
    SCIENTIFIC_NAME = 'Homo sapiens'
class Person2:
    __slots__ = ()
    NAME: str
    SCIENTIFIC_NAME = 'Homo sapiens'
class Person3:
    __slots__ = ()
    NAME: str
    SCIENTIFIC_NAME = 'Homo sapiens'
    def __init__(self, name: str):
        self.__class__.NAME = name
        ...
class Person4:
    __slots__ = ('_name', '_scientific_name')
    def __init__(self, name: str):
        self._name = name  # Technically, the way is not really read-only, but a conventional is so. 
        self._scientific_name = 'Homo sapiens'
    @property
    def name(self):
        return self._name
    @property
    def scientific_name(self):
        return self._scientific_namefor person in (Person('Carson'), Person('Carson2')):
    print(person.NAME)  # output: Carson, Carson2
for person in (Person4('Carson3'), Person4('Carson4')):
    print(person.name)  # output: Carson3, Carson4
if "it's ok but weird":
    unknown_person = Person2()
    unknown_person.__class__.NAME = '???'
    print(unknown_person.NAME)
for person in [Person3('Marry'), Person3('Marry2')]:
    # BE CAREFUL! IF YOU USE THE CLASS ATTRIBUTE, THEN ALL THE INSTANCES IS SHARED THIS VARIABLE.
    print(person.NAME)  # both output is: Marry2上述所有属性的类都是只读的(对于2和3,您可以从类中更改它,但不能更改实例),并且不接受其他新属性。
https://stackoverflow.com/questions/64221912
复制相似问题