微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Python:如何初始化NamedTuple类

如何解决Python:如何初始化NamedTuple类

我想创建一个类,并且我不想在新建后修改属性,所以我选择了NamedTuple

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

所以我希望我可以重写__init__方法

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

是否有任何优雅的代码可以做到?

我的实际情况是初始化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()

解决方法

装饰器

您可以使用装饰器来帮助您。

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__并将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_name
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,您可以从该类更改它,但不能从实例更改),并且不接受其他新属性。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?