crie um tipo de nome nomeado personalizado com recursos extras

Eu gostaria de criar meu próprio tipo de componente nomeado duplo, que possui alguns recursos extras. Digamos que criamos uma classe:

from collections import namedtuple
MyClass = namedtuple('MyClass', 'field1 field2')

É imutável, legível e simples. Agora eu posso criar instâncias do MyClass:

myobj = MyClass(field1 = 1, field2 = 3.0)
print(myobj.field1, myobj.field2)

Meu requisito extra é que, quando a instância for criada, eu gostaria de verificar sefield1 éint tipo efield2 éfloat. Por exemplo, se o usuário tentar criar uma instância MyClass:

obj = MyClass(field1 = 1, field2 = 3.0) # instantiates ok
obj1 = MyClass(field1 = 'sometext', field2 = 3.0) # raises TypeError

Eu tentei fazer um nomeado duplo personalizado que pode validar tipos de dados (MyClass deve ser imutável), algo como:

MyClass = modifiednamedtuple('MyClass', 'field1 field2', (int, float) )

mas ficou preso :(.namedtuple é function (não pode ser uma classe base para o nome nomeado modificado), meus experimentos com metaclasses falharam.

Alguma dica ou sugestão?

ok, eu vim com uma solução que pode não ser "limpa" ou pitônica. Funciona exceto que meus objetos não são imutáveis. Como torná-los imutáveis? Alguma sugestão de como torná-lo mais limpo e redutível?

Aqui está o meu código:

def typespecificnamedtuple(name, *attr_definitions):

    def init(self, *args, **kwargs):
        valid_types = dict(attr_definitions) # tuples2dict
        for attr_name, value in kwargs.items():
            valid_type = valid_types[attr_name]
            if not isinstance(value, valid_type):
                raise TypeError('Cannot instantiate class '+ self.__name__+
                    '. Inproper datatype for '+ attr_name + '=' + str(value)+ 
                        ', expected '+str(valid_type) )
            setattr(self, attr_name, value)


    class_dict = {'__init__' : init, '__name__' : name}
    for attr_def in attr_definitions:
        class_dict[attr_def[0]] = attr_def[1] # attr_def is ('name', <type int>)

    customType = type(name, (object, ), class_dict )
    return customType

if __name__ == '__main__':
    MyClass = typespecificnamedtuple('MyClass', ('value', int), ('value2', float)  )
    mc = MyClass(value = 1, value2 = 3.0)
    mc.something = 1    # this assigment is possible :( how to make immutable?
    print(mc.__name__, mc.value, mc.value2, mc.something)
    mc1 = MyClass(value = 1, value2 = 'sometext')   # TypeError exception is raised

e saída do console .:

MyClass 1 3.0 1
Traceback (most recent call last):
  File "/home/pawel/workspace/prices/prices.py", line 89, in <module>
    mc1 = MyClass(value = 1, value2 = 'sometext')   # TypeError exception is raised
  File "/home/pawel/workspace/prices/prices.py", line 70, in init
    ', expected '+str(valid_type) )
TypeError: Cannot instantiate class MyClass. Inproper datatype for value2=sometext, expected <class 'float'>

questionAnswers(2)

yourAnswerToTheQuestion