使用字典实例化具有 属性 自定义类型的对象
Instantiate an object with a property of custom type using dictionary
我的设计中还有其他一些嵌套的 classes,我正在使用字典实例化一个对象,该字典本身是从 JSON 文件转换而来的。在 JSON 文件中,我有嵌套关系,例如 Employee
和 Education
列表(1 到多)。为了简单起见,我用下面的例子来说明我的问题:
我定义了以下 classes:
def ensure_type(value, types):
if (isinstance(value, list)): # when value is a list
for element in value:
ensure_type(element, types)
return value
elif isinstance(value, dict):
for k,v in value.items(): # when value is a dict
ensure_type(v, types)
return value
elif isinstance(value, types):
return value
else:
raise TypeError('Value {value} is {value_type}, but should be {types}!'.format(value=value, value_type=type(value), types=types))
class Education:
def __init__(self, **kwargs):
print('im here')
self.school_name = ensure_type(kwargs.get('school_name'), str)
class Employee:
def __init__(self, **kwargs):
self.fname = ensure_type(kwargs.get('fname'), str)
self.education = ensure_type(kwargs.get('education'), Education)
我使用我的自定义函数 ensure_type
.
验证 type
我想使用以下方法实例化一个员工:
if __name__ == "__main__":
emp_dict = {'fname': 'Bob', 'education': [{'school_name':'foo'}, {'school_name':'bar'}]}
employee1 = Employee(**emp_dict)
当我尝试上述方法时,出现以下错误:
File "test.py", line 32, in <module>
employee1 = Employee(**emp_dict)
File "test.py", line 26, in __init__
self.education = ensure_type(kwargs.get('education'), Education)
File "test.py", line 5, in ensure_type
ensure_type(element, types)
File "test.py", line 9, in ensure_type
ensure_type(v, types)
File "test.py", line 14, in ensure_type
raise TypeError('Value {value} is {value_type}, but should be {types}!'.format(value=value, value_type=type(value), types=types))
TypeError: Value foo is <class 'str'>, but should be <class '__main__.Education'>!
当我使用以下行更新员工 class 时:
self.education = Education(kwargs.get('education'))
我收到以下错误:
Traceback (most recent call last):
File "testt.py", line 32, in <module>
employee1 = Employee(**emp_dict)
File "testt.py", line 26, in __init__
self.education = Education(kwargs.get('education'))
TypeError: __init__() takes 1 positional argument but 2 were given
如果你能指导我如何解决这个问题,我将不胜感激。
注意:
最初我定义了类似于以下的构造函数:
def __init__(self, iterable=(), **kwargs):
self.__dict__.update(iterable, **kwargs)
这是一种非常强大和灵活的方法,但是 我需要一些(或全部)属性是 required
即,用户必须在实例化时提供它们的值一个 Employee
对象。这就是我选择不采用上述方法的原因。
我认为以下代码说明了如何避免该错误。它修改 ensure_type()
函数,因此如果列表的元素不是正确的类型 (kind
),它会执行进一步检查以查看该元素是否是一个 dict
可以用于构造类型的实例。它还会用创建的实例替换字典,但您是否希望发生这种情况尚不清楚。
如果您希望字典发生类似的事情,您需要对字典中的每个值做一些非常相似的事情。
注意: 代码至少需要 Python 3.8,因为它使用了 :=
assignment expression(又名“海象运算符”).
def ensure_type(value, kind):
if (isinstance(value, list)):
# Make sure elements of list are instances of kind or can be
# used to create an instance of one.
for i, element in enumerate(value):
try:
ensure_type(element, kind)
except TypeError:
# Unless element is dict that can be used to create an
# instance of kind.
if(not isinstance(element, dict) or
not isinstance(inst := kind(**element), kind)):
raise
else:
value[i] = inst # Replace element with instance (OPTIONAL)
return value
elif isinstance(value, dict):
for k,v in value.items():
# Make sure the value of each item in dict is an instance of kind.
ensure_type(v, kind)
return value
elif isinstance(value, kind):
return value
else:
raise TypeError(
'Value {value} is {value_type}, but should be {kind}!'.format(
value=value, value_type=type(value), kind=kind))
class Printable: # Added to print test results.
""" Class which can print a represenation of itself. """
def __repr__(self):
typename = type(self).__name__
args = ', '.join("%s=%r" % item for item in vars(self).items())
return '{typename}({args})'.format(typename=typename, args=args)
class Education(Printable):
def __init__(self, **kwargs):
# print("I'm here")
self.school_name = ensure_type(kwargs.get('school_name'), str)
class Employee(Printable):
def __init__(self, **kwargs):
self.fname = ensure_type(kwargs.get('fname'), str)
self.education = ensure_type(kwargs.get('education'), Education)
if __name__ == "__main__":
emp_dict = {'fname': 'Bob',
'education': [{'school_name':'foo'}, {'school_name':'bar'}]}
employee1 = Employee(**emp_dict)
print(employee1)
输出:
Employee(fname='Bob', education=[Education(school_name='foo'), Education(school_name='bar')])
我的设计中还有其他一些嵌套的 classes,我正在使用字典实例化一个对象,该字典本身是从 JSON 文件转换而来的。在 JSON 文件中,我有嵌套关系,例如 Employee
和 Education
列表(1 到多)。为了简单起见,我用下面的例子来说明我的问题:
我定义了以下 classes:
def ensure_type(value, types):
if (isinstance(value, list)): # when value is a list
for element in value:
ensure_type(element, types)
return value
elif isinstance(value, dict):
for k,v in value.items(): # when value is a dict
ensure_type(v, types)
return value
elif isinstance(value, types):
return value
else:
raise TypeError('Value {value} is {value_type}, but should be {types}!'.format(value=value, value_type=type(value), types=types))
class Education:
def __init__(self, **kwargs):
print('im here')
self.school_name = ensure_type(kwargs.get('school_name'), str)
class Employee:
def __init__(self, **kwargs):
self.fname = ensure_type(kwargs.get('fname'), str)
self.education = ensure_type(kwargs.get('education'), Education)
我使用我的自定义函数 ensure_type
.
type
我想使用以下方法实例化一个员工:
if __name__ == "__main__":
emp_dict = {'fname': 'Bob', 'education': [{'school_name':'foo'}, {'school_name':'bar'}]}
employee1 = Employee(**emp_dict)
当我尝试上述方法时,出现以下错误:
File "test.py", line 32, in <module>
employee1 = Employee(**emp_dict)
File "test.py", line 26, in __init__
self.education = ensure_type(kwargs.get('education'), Education)
File "test.py", line 5, in ensure_type
ensure_type(element, types)
File "test.py", line 9, in ensure_type
ensure_type(v, types)
File "test.py", line 14, in ensure_type
raise TypeError('Value {value} is {value_type}, but should be {types}!'.format(value=value, value_type=type(value), types=types))
TypeError: Value foo is <class 'str'>, but should be <class '__main__.Education'>!
当我使用以下行更新员工 class 时:
self.education = Education(kwargs.get('education'))
我收到以下错误:
Traceback (most recent call last):
File "testt.py", line 32, in <module>
employee1 = Employee(**emp_dict)
File "testt.py", line 26, in __init__
self.education = Education(kwargs.get('education'))
TypeError: __init__() takes 1 positional argument but 2 were given
如果你能指导我如何解决这个问题,我将不胜感激。
注意: 最初我定义了类似于以下的构造函数:
def __init__(self, iterable=(), **kwargs):
self.__dict__.update(iterable, **kwargs)
这是一种非常强大和灵活的方法,但是 我需要一些(或全部)属性是 required
即,用户必须在实例化时提供它们的值一个 Employee
对象。这就是我选择不采用上述方法的原因。
我认为以下代码说明了如何避免该错误。它修改 ensure_type()
函数,因此如果列表的元素不是正确的类型 (kind
),它会执行进一步检查以查看该元素是否是一个 dict
可以用于构造类型的实例。它还会用创建的实例替换字典,但您是否希望发生这种情况尚不清楚。
如果您希望字典发生类似的事情,您需要对字典中的每个值做一些非常相似的事情。
注意: 代码至少需要 Python 3.8,因为它使用了 :=
assignment expression(又名“海象运算符”).
def ensure_type(value, kind):
if (isinstance(value, list)):
# Make sure elements of list are instances of kind or can be
# used to create an instance of one.
for i, element in enumerate(value):
try:
ensure_type(element, kind)
except TypeError:
# Unless element is dict that can be used to create an
# instance of kind.
if(not isinstance(element, dict) or
not isinstance(inst := kind(**element), kind)):
raise
else:
value[i] = inst # Replace element with instance (OPTIONAL)
return value
elif isinstance(value, dict):
for k,v in value.items():
# Make sure the value of each item in dict is an instance of kind.
ensure_type(v, kind)
return value
elif isinstance(value, kind):
return value
else:
raise TypeError(
'Value {value} is {value_type}, but should be {kind}!'.format(
value=value, value_type=type(value), kind=kind))
class Printable: # Added to print test results.
""" Class which can print a represenation of itself. """
def __repr__(self):
typename = type(self).__name__
args = ', '.join("%s=%r" % item for item in vars(self).items())
return '{typename}({args})'.format(typename=typename, args=args)
class Education(Printable):
def __init__(self, **kwargs):
# print("I'm here")
self.school_name = ensure_type(kwargs.get('school_name'), str)
class Employee(Printable):
def __init__(self, **kwargs):
self.fname = ensure_type(kwargs.get('fname'), str)
self.education = ensure_type(kwargs.get('education'), Education)
if __name__ == "__main__":
emp_dict = {'fname': 'Bob',
'education': [{'school_name':'foo'}, {'school_name':'bar'}]}
employee1 = Employee(**emp_dict)
print(employee1)
输出:
Employee(fname='Bob', education=[Education(school_name='foo'), Education(school_name='bar')])