更新 V2: 好吧,我在空闲时间写了一些代码并提出了这个想法。它有效,但我不知道为什么。这些代码之间的区别是什么让它真正起作用?
类基础:
def __init__(self):
self.prevention = [
'targetDeceleration',
'collisionPrevention',
]
self.correct = []
self.incorrect = []
def mapping(self, signal: list, data: list or np.ndarray, idx_list: list, filename: str, support: list = None):
def outer_wrapper(func):
def inner_wrapper(*args):
for idx, sig in enumerate(signal):
print(sig)
if support:
print(support[idx])
for idx_triplet in idx_list:
eth_idx, spi_idx, _ = idx_triplet
is_correct = func(sig, eth_idx, spi_idx, support)
if is_correct:
print('Correct')
self.correct.append(sig)
else:
print('Incorrect')
self.incorrect.append(sig)
print(filename)
return inner_wrapper
return outer_wrapper
@abstractmethod
def mapping_check(self):
pass
AEB 类(基础):
def __init__(self):
super().__init__()
def mapping_check(self):
data = np.full((4,), 5)
idx_list = [
[1, 1, 1]
]
fname = 'FILENAME'
@Base.mapping(
self,
signal=self.prevention,
data=data,
idx_list=idx_list,
filename=fname,
support=['idTarget', 'syncId']
)
def prevention_mapping(self, sig: list, eth_idx: int, spi_idx: int) -> bool:
return eth_idx == spi_idx
prevention_mapping()
更新:
@Functionality.mapping_functionality
def id_target_object_fcm_mapping(eth_signal, spi_idx, eth_idx) -> bool:
# FCF_VD_KEYS from A to E
idx_A = FCF_VD_KEYS.index('A')
idx_E = FCF_VD_KEYS.index('E')
fcf_vd_keys = FCF_VD_KEYS[idx_A: idx_E + 1]
# Check ETH and SPI mapping
for key in fcf_vd_keys:
# Check SPI mapping
PDD_469_1_1 = FCF_VD_IDS['FCV'][spi_idx] == FCF_VD_IDS[key][spi_idx]
PDD_469_1_2 = FCF_VD_ALERTS[key][spi_idx] == 43605
PDD_469_1 = PDD_469_1_1 and PDD_469_1_2
if PDD_469_1:
# Check for appropriate idTargetObjectFCMCam values
PDD_469_2 = eth_signal[eth_idx] == FCF_VD_IDS[key][spi_idx]
if PDD_469_2:
return True
# Check for default value
IS_DEFAULT = eth_signal[eth_idx] == 0
if IS_DEFAULT:
return True
# Otherwise return incorrect mapping
return False
def mapping_functionality(self):
def inner_wrapper(function, eth_signal, pickle_data, idx_list, file_name, support_signal=None):
print('inner wrapper')
for idx, sig in enumerate(eth_signal):
# Get ETH signal to be mapped
eth_signal = Functionality.get_eth_signal(sig, pickle_data)
# Load support signal
if support_signal:
support_signal = Functionality.get_eth_signal(support_signal[idx], pickle_data)
for spi_idx, eth_idx, _ in idx_list:
# Boolean storing info whether ETH was mapped correctly to the SPI signal
# Update output
is_mapping_correct = function(eth_signal, spi_idx, eth_idx, support_signal)
if is_mapping_correct:
if self.result[sig] != self.incorrect:
self.result[sig] = self.correct
else:
self.result[sig] = self.incorrect
if sig not in self.corrupted_files[file_name]:
self.corrupted_files[file_name][sig] = []
self.corrupted_files[file_name][sig].append([spi_idx, eth_idx])
return inner_wrapper
不幸的是,在尝试运行代码后:
id_target_object_fcm_mapping(self.id_target_object_fcm_sig, pickle_data, idx_list, file_name)
我收到错误,mapping_functionality() 错过了 file_name 参数。我该如何解决?
所以基本上我想包装这个函数:
@Functionality.mapping_functionality(
self=self,
eth_signal=self.id_target_object_fcm_sig,
pickle_data=pickle_data,
idx_list=idx_list,
file_name=file_name,
)
def id_target_object_fcm_mapping(eth_signal, spi_idx, eth_idx, *args) -> bool:
# FCF_VD_KEYS from A to E
idx_A = FCF_VD_KEYS.index('A')
idx_E = FCF_VD_KEYS.index('E')
fcf_vd_keys = FCF_VD_KEYS[idx_A: idx_E + 1]
# Check ETH and SPI mapping
for key in fcf_vd_keys:
# Check SPI mapping
PDD_469_1_1 = FCF_VD_IDS['FCV'][spi_idx] == FCF_VD_IDS[key][spi_idx]
PDD_469_1_2 = FCF_VD_ALERTS[key][spi_idx] == 43605
PDD_469_1 = PDD_469_1_1 and PDD_469_1_2
if PDD_469_1:
# Check for appropriate idTargetObjectFCMCam values
PDD_469_2 = eth_signal[eth_idx] == FCF_VD_IDS[key][spi_idx]
if PDD_469_2:
return True
# Check for default value
IS_DEFAULT = eth_signal[eth_idx] == 0
if IS_DEFAULT:
return True
# Otherwise return incorrect mapping
return False
进入一个将遍历索引并根据包装函数的布尔值更新电子表格的函数:
def mapping_functionality(self, eth_signal, pickle_data, idx_list, file_name, support_signal=None):
for idx, sig in enumerate(eth_signal):
# Get ETH signal to be mapped
eth_signal = Functionality.get_eth_signal(sig, pickle_data)
# Load support signal
if support_signal:
support_signal = Functionality.get_eth_signal(support_signal[idx], pickle_data)
def outer_wrapper(function):
# Iterate over signal indices
for spi_idx, eth_idx, _ in idx_list:
# Boolean storing info whether ETH was mapped correctly to the SPI signal
@wraps(function)
def inner_wrapper():
is_mapping_correct = function(eth_signal, spi_idx, eth_idx, support_signal)
# Update output
if is_mapping_correct:
if self.result[sig] != self.incorrect:
self.result[sig] = self.correct
else:
self.result[sig] = self.incorrect
if sig not in self.corrupted_files[file_name]:
self.corrupted_files[file_name][sig] = []
self.corrupted_files[file_name][sig].append([spi_idx, eth_idx])
return inner_wrapper
return outer_wrapper
不幸的是在尝试调用该函数后:
id_target_object_fcm_mapping()
我收到以下错误:
TypeError: 'NoneType' object is not callable
我该如何解决这个问题?
答案 0 :(得分:1)
由于您没有提供有关类对象的信息以及您尝试执行的操作,因此很难理解您的代码行为是否会如预期的那样进行修复。
通常,最好简化问题并将其作为 SO 上的可重现示例提供。
假设您的潜在问题是标题所暗示的,
<块引用>如何将带参数的函数包装成带参数的包装器?
这里是通过装饰器传递参数的一般结构如下。希望这会有所帮助 -
def decorator_function(n):
def outer_wrapper(f):
def inner_wrapper(*args, **kwargs):
out = f(*args, **kwargs)**n
return out
return inner_wrapper
return outer_wrapper
@decorator_function(4) #<- Decorator with argument
def function(x, m):
return x/m
print(function(10,3))
print((10/3)**4)
123.45679012345681
123.45679012345681
原始函数采用 x
除以 m
。包装器接受 n
并将其作为原始函数输出的幂,因此,(x/m)^n
编辑: 只是为了添加创建嵌套装饰器函数的 lambda 函数方法,因为我个人觉得它们更具可读性(很奇怪吧?)
decorator = lambda n:lambda f:lambda *args, **kwargs: f(*args, **kwargs)**n
@decorator(4)
def function(x, m):
return x/m
function(10,3)
123.45679012345681
你可以很容易地看到这里发生了什么 -
lambda n:lambda f:lambda *args, **kwargs: f(*args, **kwargs)**n
# | | |________________| | |
# | | original function | |
# | |___________________________________________| |
# | wrapper takes in f and returns inner lambda |
# |_______________________________________________________________|
# outer function takes n parameter and returns wrapper