Я хотел бы создать собственный тип встроенного namedtuple, который имеет некоторые дополнительные функции. Предположим, мы создали класс:создать собственный тип namedtuple с дополнительными функциями
from collections import namedtuple
MyClass = namedtuple('MyClass', 'field1 field2')
Это неизменный, читаемый и простой. Теперь я могу создавать экземпляры MyClass:
myobj = MyClass(field1 = 1, field2 = 3.0)
print(myobj.field1, myobj.field2)
Моего дополнительное требование при создании экземпляра я хотел бы проверить, если field1
является int
типа и field2
является float
. Например, если пользователь попытается создать MyCLASS экземпляр:
obj = MyClass(field1 = 1, field2 = 3.0) # instantiates ok
obj1 = MyClass(field1 = 'sometext', field2 = 3.0) # raises TypeError
Я попытался сделать настроенную namedtuple, что можно проверить типы данных (MyClass должны быть неизменны) что-то вроде .:
MyClass = modifiednamedtuple('MyClass', 'field1 field2', (int, float))
но застрял :(. namedtuple
является функцией (не может быть BaseClass для modifiednamedtuple), мои эксперименты с метаклассами не удалось.
Любые советы или предложения?
ОК, я придумал решение, которое может быть не «чистым» или питоническим. Он работает, за исключением того, что мои объекты не являются неизменными. Как сделать их неизменными? Любые предложения, как сделать его более чистым и переконфигурированным?
Вот мой код .:
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
и консольный выход .:
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'>
Что это с 'namedtuple', что вы хотите получить ? Размер? Неизменность? Типичным способом проверки значений атрибутов является свойство * *, но здесь может быть более понятной фабричная функция. – jonrsharpe
Вы хотите * генерировать измененные именованные кортежи * или достаточно одного класса? Другими словами, 'namedtuple' является фабрикой классов, должен ли' modifiednamedtuple' быть фабрикой классов * слишком *? –