首页 > 解决方案 > 不使用闭包的替代解决方案

问题描述

我有一个类Data,我想使用下面的 api 进行过滤。

# Example: filter using where
inpt = {"a":np.array((1,2,3,4,2,5,6,2,3,3,2,1)), 
         "b":np.random.rand(12)}
data = (Data(inpt)
        .where(col("a").equals(3)) # This is how where should be called. 
       )
data

我可以使用另一个类来实现这一点,该类Expr处理Data.where()使用闭包中的所有功能。无法Expr访问Data.

问题:有人可以为我提供不涉及闭包的替代方法。我的目标是学习新的方法/方向。

这是我的代码:

from __future__ import annotations
from typing import Dict, Any
import numpy as np

class Data:
    def __init__(self, data: Dict):
        self._data = data
        
    def where(self, e: Expr) -> Data:
        idx = e.collect(self)
        for k,v in self._data.items():
            self._data[k] = v[idx]
        return self
    
    def __repr__(self):
        return str(self._data)

class Expr:
    def __init__(self):
        self.fs = []
        
    
    def col(self, s: str) -> Self:
        f = lambda x: x._data[s]
        self.fs.append(f)
        return self

    def equals(self, el: Any) -> Self:
        f = lambda x: x == el
        self.fs.append(f)
        return self
        

    def collect(self, x: Data) -> Data:
        args = x
        for f in self.fs:
            args = f(args)
        return args
    
def col(s: str) -> Expr:
    return Expr().col(s)

标签: python-3.xclosures

解决方案


我真的不明白重点。也许如果你举一个你实际尝试做的例子?

如果您已经知道正确的密钥,则可以直接检查。如果您想找到正确的键,pythonic 方法是使用列表推导。

In [2]: inpt = {
   ...:     "a": (1,2,3,4,2,5,6,2,3,3,2,1),
   ...:     "b": 3,
   ...: }

In [3]: inpt["a"] == 3
Out[3]: False

In [4]: inpt["b"] == 3
Out[4]: True

In [5]: [key for key, value in inpt.items() if value == 3][0]
Out[5]: 'b'

In [8]: from typing import Sequence

In [9]: [key for key, value in inpt.items() if isinstance(value, Sequence) and 3 in value][0]
Out[9]: 'a'




推荐阅读