首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Python:如何初始化NamedTuple类

Python:如何初始化NamedTuple类
EN

Stack Overflow用户
提问于 2020-10-06 08:18:31
回答 1查看 818关注 0票数 1

我想要创建一个类,而且我不希望它的属性在new之后被修改,所以我选择了NamedTuple

但我希望它能在初始化后立即做些事情,

所以我希望我能覆盖__init__方法,

但是如果我这样做,我将遇到AttributeError:无法覆盖NamedTuple属性

有任何优雅的代码可以做到这一点吗?

我的实际情况是初始化ttk的样式,如下所示。

代码语言:javascript
运行
复制
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()
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-10-06 08:18:31

装潢工

你可以用装饰师帮你。

代码语言:javascript
运行
复制
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)上,例如:

代码语言:javascript
运行
复制
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_name
代码语言:javascript
运行
复制
for 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,您可以从类中更改它,但不能更改实例),并且不接受其他新属性。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64221912

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档