【问题标题】:Python class inheritance/Logic gate & circuit examplePython类继承/逻辑门和电路示例
【发布时间】:2014-04-24 03:26:36
【问题描述】:

我目前正在自学 Python,并且正在阅读“使用算法和数据结构解决问题”(Brad Miller,David Ranum)。我偶然发现了继承的基本示例。虽然我可以看到它的作用,但我需要一个解释,如何它实际上是如何工作的。代码如下:

class LogicGate:

    def __init__(self,n):
        self.name = n
        self.output = None

    def getName(self):
        return self.name

    def getOutput(self):
        self.output = self.performGateLogic()
        return self.output


class BinaryGate(LogicGate):

    def __init__(self,n):
        LogicGate.__init__(self,n)

        self.pinA = None
        self.pinB = None

    def getPinA(self):
        if self.pinA == None:
            return int(input("Enter Pin A input for gate "+self.getName()+"-->"))
        else:
            return self.pinA.getFrom().getOutput()

    def getPinB(self):
        if self.pinB == None:
            return int(input("Enter Pin B input for gate "+self.getName()+"-->"))
        else:
            return self.pinB.getFrom().getOutput()

    def setNextPin(self,source):
        if self.pinA == None:
            self.pinA = source
        else:
            if self.pinB == None:
                self.pinB = source
            else:
                print("Cannot Connect: NO EMPTY PINS on this gate")


class AndGate(BinaryGate):

    def __init__(self,n):
        BinaryGate.__init__(self,n)

    def performGateLogic(self):

        a = self.getPinA()
        b = self.getPinB()
        if a==1 and b==1:
            return 1
        else:
            return 0

class OrGate(BinaryGate):

    def __init__(self,n):
        BinaryGate.__init__(self,n)

    def performGateLogic(self):

        a = self.getPinA()
        b = self.getPinB()
        if a ==1 or b==1:
            return 1
        else:
            return 0

class UnaryGate(LogicGate):

    def __init__(self,n):
        LogicGate.__init__(self,n)

        self.pin = None

    def getPin(self):
        if self.pin == None:
            return int(input("Enter Pin input for gate "+self.getName()+"-->"))
        else:
            return self.pin.getFrom().getOutput()

    def setNextPin(self,source):
        if self.pin == None:
            self.pin = source
        else:
            print("Cannot Connect: NO EMPTY PINS on this gate")


class NotGate(UnaryGate):

    def __init__(self,n):
        UnaryGate.__init__(self,n)

    def performGateLogic(self):
        if self.getPin():
            return 0
        else:
            return 1


class Connector:

    def __init__(self, fgate, tgate):
        self.fromgate = fgate
        self.togate = tgate

        tgate.setNextPin(self)

    def getFrom(self):
        return self.fromgate

    def getTo(self):
        return self.togate


def main():
   g1 = AndGate("G1")
   g2 = AndGate("G2")
   g3 = OrGate("G3")
   g4 = NotGate("G4")
   c1 = Connector(g1,g3)
   c2 = Connector(g2,g3)
   c3 = Connector(g3,g4)
   print(g4.getOutput())

main()

我对@9​​87654323@ 类__init__ 中的tgate.setNextPin(self) 语句最怀疑。是方法调用吗?如果是,为什么在UnaryGateBinaryGate(self, source) 中的setNexPin 函数实际需要两个参数时,只用一个参数调用它? fromgate 变量如何最终成为 source 参数?这句话是否真的“初始化”了什么?

接下来困扰我的事情是,例如,当我在声明g4.getOutput() 之前print(type(g4)) 时,我得到<class '__main__.OrGate'>,但是当g4.getOutput() 启动时,函数开始相互调用,直到调用getPin 函数,如果我将 print (self.pinA) 放在 return self.pinA.getFrom().getOutput() 之前,我会得到 <__main__.Connector object at 0x2b387e2f74d0>,尽管 self.Pin 是来自 g4 OrGate 实例的变量。一个类实例中的一个变量如何成为另一个类的对象,而不是继承它?这有没有setNextPin()函数的作用?

有人可以向我解释一下吗,因为我是 OOP 的新手,并且对这段代码感到非常困惑。谢谢。

【问题讨论】:

    标签: python class oop inheritance python-3.x


    【解决方案1】:

    关于您的第一个问题,tgate.setNextPin(self) 是一个方法调用。 tgate 是一个对象,可能是其中一种门类型的实例。当您访问instance.method 时,Python 会为您提供一个“绑定方法”对象,它的工作方式与函数非常相似,但在实际调用实例时会将实例作为第一个参数放入。所以,tgate.setNextPin(self) 真的是在打电话给type(tgate).setNextPin(tgate, self)

    您的第二个问题似乎反映了对属性是什么的误解。不要求对象的属性是其自己的类型。在各种LogicGate 子类中,pin/pinA/pinB 属性要么是 None(表示应该提示用户输入值)要么是 @ 的实例987654332@(或其他带有getFrom 方法的东西)。这些值都不是LogicGate 实例。

    至于您看到的Connector 实例来自哪里,它将是您创建的c1c3 值之一。 Connector 实例将自己安装到 tgate 参数的引脚上,setNextPin call 您在第一个问题中询问。我无法真正与您正在查看的 g4 门交谈,因为它似乎与在示例代码的 main() 函数中创建的 g4 变量不同(它是不同的类型),但我怀疑它按设计工作,只是有点混乱。尝试通过g4.pinA 访问pinX 属性,而不是在方法内部检查它们,这样您可能会少一些困惑。

    这里有一些输出代码可以帮助你更好地理解事物:

    # create a few gates
    g1 = AndGate("G1")
    g2 = OrGate("G2")
    
    # at this point, no connectors have been hooked up, so all pinX attrs are None:
    print("G1 pins:", g1.pinA, g1.pinB) # "None, None"
    print("G2 pins:", g2.pinA, g2.pinB) # "None, None"
    
    # test that the gates work independently of each other:
    print("G1 output:", g1.getOutput()) # will prompt for two inputs, then print their AND
    print("G2 output:", g2.getOutput()) # will prompt for two inputs, then print their OR
    
    # create a connection between the gates
    c1 = Connector(g1, g2) # connects output of g1 to first available pin (pinA) of g2
    
    # we can see that g2.pinA has changed
    print("G2 pins after connection:", g2.pinA, g2.pinB)
       # "<__main__.Connector object at SomeHexAddress>, None"
    
    # now, if we get g2's output, it will automatically request g1's output via the Connector
    print("G2 output:", g2.getOutput())
       # will prompt for 2 G1 inputs, and one G2 input and print (G1_A AND G1_B) OR G2_B
    

    如果您想更多地使用这些类,您可能需要为部分或全部类添加__str__(和/或__repr__)方法。 Python 使用__str__ 在必要时将类的实例转换为字符串(例如当您将其作为参数传递给printstr.format 时)。这是Connector 的快速__str__ 实现:

    def __str__(self):
        return "Connector between {} and {}".format(self.fgate.name, self.tgate.name)
    

    【讨论】:

    • 当我在在线可视化器中可视化我的代码时,当通过创建连接器对象c1 = Connector(g1,g3) 执行setNextPin 函数并调用tgate.setNextPin(self) 并创建框架时,self 指向OrGate (g3) 对象是tgate 参数,source 指向fgate 连接器对象。因此,传递的source 参数并不是真正的tgate,而是fgate。我仍然怀疑fgate 参数是如何在tgate.setNextPin(self) statement 中传递的。
    • 我不认为source 来自fgate(即g1),而是来自selfConnection.__init__ 中的调用。您的调用堆栈以main() 开头,它正在运行语句c1 = Connection(g1, g3)。接下来是运行tgate.setNextPin(self)Connection.__init__(&lt;c1&gt;, g1, g3)(我将c1 放在尖括号中,因为它还没有绑定到该名称)。解析为BinaryGate.setNextPin(g3, &lt;c1&gt;),这是堆栈的顶部。
    • 看看这个链接:goo.gl/nSpm4g,它显示了在执行tgate.setNextPin(self)、调用setNextPin函数和创建框架之后的代码可视化。 self 指向togate 连接器实例或G3 (OrGate) 实例,source 指向fromgate 连接器实例或G1 (AndGate) 实例。我仍然对此感到困惑,并希望你看看它。谢谢。
    • @Reloader:我认为您以某种方式误读了可视化。我在那里看到的一切都如我所料。在setNextPin 中,self 参数只有一个值,即名称属性为G3OrGate。不要被上一帧的self参数搞糊涂了,完全不相关!
    • 我看到蓝色箭头来自setNextPin 框架,self 参数(右箭头),与来自togate 连接器实例的箭头连接,它们连接在OrGate output 属性的位置。
    猜你喜欢
    • 1970-01-01
    • 2015-06-21
    • 2015-09-22
    • 1970-01-01
    • 2021-07-06
    • 1970-01-01
    • 2015-12-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多