获取一个实例以在默认情况下对其求值

2024-04-27 01:11:19 发布

您现在位置:Python中文网/ 问答频道 /正文

我有以下AND类:

class GATE:
    def __init__(self, *args, **kwargs):
        inputs = args or list(kwargs.values())
        assert (len(inputs) >= 2), "Must have two or more inputs for a gate."
        self.inputs = [int(i) for i in inputs]
    # def __repr__(self):
    #     return str(self.output)


class AND(GATE):
    @property
    def output(self):
        return int(all(self.inputs))      

我希望能够做到以下几点:

AND(1,1)

并返回1。不仅要打印该值,还要对其进行实际计算,以便我可以执行以下操作:

AND(1,AND(0,1))

我该如何以Python式的方式来做这件事?否则,我必须:

>>> AND(1,AND(0,1).output).output
0

Tags: orandselfforoutputreturninitdef
3条回答

根据Ch3steR的建议,您可以使用以下方法来获得更均匀的回报:

AND = GATE.AND

class GATE:
    def AND(self, *args, **kwargs):
        inputs = list(args or kwargs.values())
        return int(all(inputs))      
    def OR...

AND=GATE().AND

>>> AND(1,AND(0,1))
0

您还可以潜在地将其从类中拉出,并使其成为一个函数,正如其他注释所建议的那样,这将使其更加简单:

def AND(*args, **kwargs):
    inputs = list(args or kwargs.values())
    return int(all(inputs))

>>> AND(1,AND(0,1))
0

调用返回的值(如AND(1, 0))不能既是AND类的实例,又是0号。要么得到实例,要么得到整数结果,但不能同时得到两者

或者不完全是两者兼而有之。您可以构建类,使实例在某些上下文中的行为类似于整数。例如,如果您添加了一个__int__方法,如果您将类传递给int(),则该类将可转换为整数

其他一些类型甚至可以更容易地转换为。如果期望所有的门都有一个二进制输出值01,那么您可以通过在类上实现__bool__方法来获得所需的(自动计算)。Python在计算对象是否为“truthy”时使用此方法。因此if AND(...)将按照您的预期进行评估,正如all([AND(...), AND(...)])(这对于实现AND类可能很方便)

请注意,布尔值TrueFalse分别等于整数10bool类是int的一个子类

下面是我如何使用__bool__(而不是output)创建您的类:

class Gate:
    def __init__(self, *args, **kwargs):
        self.inputs = args or list(kwargs.values()) # note, no int() calls made here
        assert (len(self.inputs) >= 2), "Must have two or more inputs for a gate."

    def __bool__(self):
        raise NotImplementedError()  # subclasses are expected to override this method

    def __repr__(self):
        return f"<{self.__class__.__name__}(*{self.inputs})=>{bool(self)}>"


class And(Gate):
    def __bool__(self):
        return all(self.inputs)

现在您可以执行类似于result = And(True, And(True, False))的操作,并将AND对象保存到result。但是bool(result)将为您提供值False。获取类的repr还将计算其布尔值(因此它可以在repr字符串中包含TrueFalse结果)

请注意,我们不会对给定的输入进行任何类型的转换(没有int()调用)。这意味着代码可以惰性地处理没有稳定值的其他类型的输入,例如基于读取磁盘上的文件或提示用户:

class Input:
    def __init__(self, prompt):
        self.prompt = prompt

    def __bool__(self):
        return bool(int(input(self.prompt)))

    def __repr__(self):
        return f"<Input: {self.prompt}>"

如果执行lazy_result = And(Input("A: "), Input("B: ")),则执行print(lazy_result)bool(lazy_result)将提示用户输入整数值,并计算所需的输出。请注意,由于all中的短循环,如果在第一个提示下输入0,它将不会要求第二个提示,因为它不需要知道B值来给出And的值!(在某些情况下,这可能是不可取的,因此您可能需要用不会短路的东西来替换all。)

以您想要的方式进行计算并不意味着从构造函数“返回”某些内容。这样看:如果你有一个直接的输入,你就处理它;如果你有一个门,你需要它的输出

请参阅如何执行此操作的版本:

class GATE:
    def __init__(self, *args,**kwargs):
        self.inputs = args or list(kwargs.values())
    @property
    def output(self):
        raise Exception('This should be overridden')

class AND(GATE):
    @property
    def output(self):
        result = True
        for i in self.inputs:
            if issubclass(i.__class__,Gate):
                result = result and i.output
            else:
                result = result and i
        return result

然后,您将运行的代码可以是:

AND(True,True).output

为了一个简单的门。也可以是

AND(AND(True,AND(False,False)),True).output

您可以得到所需的效果,即处理每个门的输出,而无需到处写入output

你可以更进一步,以reduce为基础,让GATE子代只需要定义用于reduce参数的lambda,但这是另一个问题

相关问题 更多 >