Python:将类成员函数传递给另一个类的回调

时间:2018-04-04 04:14:03

标签: python callback raspberry-pi robot

我可以将A类传递给B类,以便B可以使用A&#39的成员函数运行回调吗?

我正在尝试为我正在构建的机器人编写Python leg class。我使用Raspberry Pi作为主计算机,使用Martin O' Hanlon的KY040旋转编码器库KY040来检测腿的每1/4圈。为此,我观察了几次点击中的第一次,短时间睡眠,停止伺服,现在已经实现了1/4的旋转。在独立的,无螺纹的代码中,这种方法很好,但是创建类是一个挑战。

感谢您的时间。

详细说明: 螺纹标记循环监视布尔值(quarterTurn)以表示必须执行旋转。

def run(self):
    print "leg running"
    while self._running:
        sleep(.0001)
        if self.quarterTurn:
            print "quarterTurn is: " + str(self.quarterTurn)
            self.qTurn(self.quarterCount)

qTurn访问pwm控制器以激活电机,并将quarterTurn重置为false。

def qTurn(self, quarters):
    count = 0

    while count < quarters:
        sleep(.0001)
        self.setMotor(self.maxPulse)

        if self.ClickedOnce:
            count = count + 1
            sleep(.17)
            self.parkMotor()
            sleep(.04)
            self.clickedOnce = False

    self.quarterTurn = False

诀窍在于O&#39; Hanlon的类已经有线程了。一方面,它很方便,另一方面,它使我的课更复杂。 KY040使用回调函数来提供反馈,但在我的班级中使用它是我的麻烦的来源。

我需要回调来修改我的leg类中的boolean,但是这个函数只能由KY040类调用,它试图将自己传递给函数。

def rotaryChange(self, pin):
    self.clickedOnce = True

由于代码是开源的(谢谢你,O&#39; Hanlon),我想我可以修改KY040的构造函数让我把我的leg类传递给它,这样我就可以修改正确的数据了。 / p>

O&#39; Hanlon的原始构造者:

def __init__(self, clockPin, dataPin, switchPin=None, rotaryCallback=None, switchCallback=None,rotaryBouncetime=250, switchBouncetime=300):
    # persist values
    self.clockPin = clockPin
    self.dataPin = dataPin
    self.switchPin = switchPin
    self.rotaryCallback = rotaryCallback
    self.switchCallback = switchCallback
    self.rotaryBouncetime = rotaryBouncetime
    self.switchBouncetime = switchBouncetime

    #setup pins
    GPIO.setup(clockPin, GPIO.IN)
    GPIO.setup(dataPin, GPIO.IN)

    if None != self.switchPin:
        GPIO.setup(switchPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)

我添加了一个&#34;主机&#34;变量,我传给腿类:

def __init__(self, clockPin, dataPin, switchPin=None, rotaryCallback=None, switchCallback=None, host=None, rotaryBouncetime=250, switchBouncetime=300):
    # persist values
    self.clockPin = clockPin
    self.dataPin = dataPin
    self.switchPin = switchPin
    self.rotaryCallback = rotaryCallback
    self.switchCallback = switchCallback
    self.rotaryBouncetime = rotaryBouncetime
    self.switchBouncetime = switchBouncetime

    # My Change
    self.host = host

    #setup pins
    GPIO.setup(clockPin, GPIO.IN)
    GPIO.setup(dataPin, GPIO.IN)

    if None != self.switchPin:
        GPIO.setup(switchPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)

修改后的构造函数将被调用:

self.encoder = KY040(self.clockPin, self.dataPin, rotaryCallback=self.rotaryChange, host=self)

O&#39; Hanlon的回调现在通过主持人:

def _clockCallback(self, pin):
        # My change
        self.rotaryCallback(pin, self.host)

我的新回调:

def rotaryChange(pin, host):
    host.clickedOnce = True

不幸的是,在确保修改后的代码与安装脚本一起安装后,它似乎并没有承认我的新添加内容。我运行我的程序并收到以下错误:


    Traceback (most recent call last):
    File "ctf.py", line 18, in 
      LR = leg.leg(lr_chan, lr_max, lr_park, lr_clk, lr_data);
    File "/home/[user]/hexacrescentapod/leg.py", line 47, in __init__
      self.encoder = KY040(self.clockPin, self.dataPin, 
    rotaryCallback=self.rotaryChange, host=self)
    TypeError: __init__() got an unexpected keyword argument 'host'

感谢你花时间在这个冗长的问题上。

2 个答案:

答案 0 :(得分:1)

初看起来,您的新回调似乎缺少self字段?

原始功能是

def rotaryChange(self, pin):
    self.clickedOnce = True

但您的实施是:

def rotaryChange(pin, host):
    host.clickedOnce = True

如果此函数位于类中,则需要具有self参数

答案 1 :(得分:1)

由于你的措辞,这有点令人困惑。您实际上是在尝试传递,或者正如您所做的那样传递该类的实例吗?在

中定义了哪个类rotaryChange

无论如何,看起来你真正要做的就是将self.rotaryChange作为回调传递。

这已经有效,没有任何变化。 self.rotaryChange是一个绑定方法,意味着它知道self在创建时是什么,并在调用它时传递它。通过示例可能更容易看到这一点:

>>> class Spam:
...     def eggs(self):
...         pass
>>> spam = Spam()
>>> spam
<__main__.Spam at 0x119947630>
>>> spam.eggs
<bound method Spam.eggs of <__main__.Spam object at 0x119947630>>

请注意,它是spam对象的绑定方法。当您致电spam.eggs()时,该spam个对象将作为self参数传递。

这意味着您无需传递host,因为它已作为self提供。而且,由于这是您使用host进行的唯一操作,因此您无需首先传递host。这意味着您可以将所有更改还原为库代码。

需要将回调方法定义为正确的方法,self作为第一个参数。但就是这样。然后你可以将rotaryCallback=self.rotaryChange传递给构造函数,一切都会正常工作。