针对动态创建的对象进行类型检查
Type checking against dynamically created objects
我想对方法的输入和输出执行一些动态类型检查。我想出的解决方案如下。基本上,在超类的 __init__
函数中,我通过对输入和输出进行一些动态类型检查来更新子类方法。请注意,类型检查应基于用户在实例化期间定义的属性 (AlgorithmAttribute
)。我想知道是否有更好的解决方案。
import abc
import six
import attr
from typing import Dict, Text
@attr.s
class AlgorithmAttribute(object):
inputs = attr.ib(type=Dict[Text, int])
outputs = attr.ib(type=Dict[Text, int])
class BaseHandler(six.with_metaclass(abc.ABCMeta, object)):
def __init__(self, alg):
self.alg = alg
self.out = self.__getattribute__('prepare')
self.__setattr__('prepare', self.temp)
def temp(self, a, b):
result = self.out(a, b)
# Verifies inputs.
if set(a.keys()) == set(self.alg.inputs.keys()):
print('Inputs correct!')
# Verifies outputs.
if set(result.keys()) == set(self.alg.outputs.keys()):
print('Outputs correct!')
return result
@abc.abstractmethod
def prepare(self, a):
pass
class SubHandler(BaseHandler):
def __init__(self, alg):
super(SubHandler, self).__init__(alg)
def prepare(self, a:Dict[Text, int], b:Dict[Text, int]) -> Dict[Text, int]:
return {'c': 33}
alg = AlgorithmAttribute(inputs={'a': 2, 'b': 3}, outputs={'c': 10})
sh = SubHandler(alg)
sh.prepare({'a': 20, 'b': 200}, b={'c': 20, 'd': 200})
我不是很清楚为什么你要验证 prepare()
的第一个参数反对 inputs
或者将带有未使用值的字典传递给 AlgorithmAttribute
有什么意义,但更多在我看来,Pythonic 方式是放弃 类 并使用 decorator:
from dataclasses import dataclass
from typing import Dict, Text
@dataclass
class AlgorithmAttribute(object):
inputs: Dict[Text, int]
outputs: Dict[Text, int]
def validate_inputs_outputs(validation_params: AlgorithmAttribute):
def wrap(func):
def wrapped_func(*args, **kwargs):
result = func(*args, **kwargs)
# Verifies inputs.
if set(args[0].keys()) == set(validation_params.inputs.keys()):
print('Inputs correct!')
# Verifies outputs.
if set(result.keys()) == set(validation_params.outputs.keys()):
print('Outputs correct!')
return result
return wrapped_func
return wrap
@validate_inputs_outputs(AlgorithmAttribute(inputs={'a': 2, 'b': 3}, outputs={'c': 10}))
def prepare(a:Dict[Text, int], b:Dict[Text, int]) -> Dict[Text, int]:
return {'c': 33}
prepare({'a': 20, 'b': 200}, b={'c': 20, 'd': 200})
我想对方法的输入和输出执行一些动态类型检查。我想出的解决方案如下。基本上,在超类的 __init__
函数中,我通过对输入和输出进行一些动态类型检查来更新子类方法。请注意,类型检查应基于用户在实例化期间定义的属性 (AlgorithmAttribute
)。我想知道是否有更好的解决方案。
import abc
import six
import attr
from typing import Dict, Text
@attr.s
class AlgorithmAttribute(object):
inputs = attr.ib(type=Dict[Text, int])
outputs = attr.ib(type=Dict[Text, int])
class BaseHandler(six.with_metaclass(abc.ABCMeta, object)):
def __init__(self, alg):
self.alg = alg
self.out = self.__getattribute__('prepare')
self.__setattr__('prepare', self.temp)
def temp(self, a, b):
result = self.out(a, b)
# Verifies inputs.
if set(a.keys()) == set(self.alg.inputs.keys()):
print('Inputs correct!')
# Verifies outputs.
if set(result.keys()) == set(self.alg.outputs.keys()):
print('Outputs correct!')
return result
@abc.abstractmethod
def prepare(self, a):
pass
class SubHandler(BaseHandler):
def __init__(self, alg):
super(SubHandler, self).__init__(alg)
def prepare(self, a:Dict[Text, int], b:Dict[Text, int]) -> Dict[Text, int]:
return {'c': 33}
alg = AlgorithmAttribute(inputs={'a': 2, 'b': 3}, outputs={'c': 10})
sh = SubHandler(alg)
sh.prepare({'a': 20, 'b': 200}, b={'c': 20, 'd': 200})
我不是很清楚为什么你要验证 prepare()
的第一个参数反对 inputs
或者将带有未使用值的字典传递给 AlgorithmAttribute
有什么意义,但更多在我看来,Pythonic 方式是放弃 类 并使用 decorator:
from dataclasses import dataclass
from typing import Dict, Text
@dataclass
class AlgorithmAttribute(object):
inputs: Dict[Text, int]
outputs: Dict[Text, int]
def validate_inputs_outputs(validation_params: AlgorithmAttribute):
def wrap(func):
def wrapped_func(*args, **kwargs):
result = func(*args, **kwargs)
# Verifies inputs.
if set(args[0].keys()) == set(validation_params.inputs.keys()):
print('Inputs correct!')
# Verifies outputs.
if set(result.keys()) == set(validation_params.outputs.keys()):
print('Outputs correct!')
return result
return wrapped_func
return wrap
@validate_inputs_outputs(AlgorithmAttribute(inputs={'a': 2, 'b': 3}, outputs={'c': 10}))
def prepare(a:Dict[Text, int], b:Dict[Text, int]) -> Dict[Text, int]:
return {'c': 33}
prepare({'a': 20, 'b': 200}, b={'c': 20, 'd': 200})