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

Python:将一个类成员函数传递给另一个类';s回调,python,callback,raspberry-pi,robot,Python,Callback,Raspberry Pi,Robot,我可以将类A传递到类B中,以便B可以使用A的成员函数运行回调吗 我正在尝试为我正在构建的机器人编写Python leg类。我使用树莓Pi作为主计算机,Martin O'Hanlon的KY040旋转编码器库检测腿部的每1/4旋转。为此,我观察几次点击中的第一次,短暂睡眠,停止伺服,现在已经实现了1/4的旋转。在独立的、无线程的代码中,这很好,但是创建一个类是一个挑战 谢谢你抽出时间 详情: 螺纹哨兵循环监视布尔值(四分之一圈),以表示必须执行旋转 def run(self): print

我可以将类A传递到类B中,以便B可以使用A的成员函数运行回调吗

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

谢谢你抽出时间

详情: 螺纹哨兵循环监视布尔值(四分之一圈),以表示必须执行旋转

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控制器以激活电机,并将四分之一圈重置为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'Hanlon),我想我可以修改KY040的构造函数,让我将leg类传递给它,以便修改正确的数据

O'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)
我添加了一个“host”变量,我将leg类传递到该变量中:

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'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'

感谢您花时间回答这个冗长的问题。

乍一看,您的新回调似乎缺少一个
self
字段

最初的功能是

def rotaryChange(self, pin):
    self.clickedOnce = True
但您的实施是:

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

如果这个函数位于一个类中,它需要有一个
self
参数

,由于您的措辞,这有点令人困惑。你是否真的像你说的那样试图传递一个类,或者像你看起来正在做的那样传递该类的一个实例?哪个类是
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>>
>类垃圾邮件:
...     def蛋(自我):
...         通过
>>>spam=spam()
>>>垃圾邮件
>>>鸡蛋
请注意,它是
spam
对象的绑定方法。调用
spam.eggs()
时,该
spam
对象将作为
self
参数传递

这意味着您不需要传入
主机
,因为它已经作为
self
提供。而且,由于这是您对
host
所做的唯一一件事,您首先不需要传递
host
。这意味着您可以恢复对库代码的所有更改


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

事实上,我也认为传递
self
是类成员的一项要求,但是,更改为第二个实现是我所能想到的防止KY040类将自身传递到
self
参数中的唯一方法。@gagegigle这是Python使用显式
self
的部分原因,因此总是很清楚传递的是谁的
self
。如果
KY040
中的代码没有调用
self.something
,其中
something
是类或子类中的方法名,则它不会传递自身。然而,存储在实例变量中的可调用项有时会令人困惑。您必须注意,
self.callback
是在
\uuuu init\uuuu
或其他一些方法体中分配的,以知道它不是一个方法,因此不会传递它自己的
self
@gagegigle当您不确定时,通常值得使用相同的模式构建一个玩具类,但其余的代码都不值得,所以您可以运行它并打印出所调用的内容。@abarnert非常感谢您。我会的。那很有趣。我会试试看,让你知道会发生什么。@gagegigle大多数Python教程都不介绍绑定方法,可能是因为它们看起来有点吓人,但它们非常有用,以至于教程经常使用它们,尽管它们从未解释过它们。有一点可以帮助你考虑,你可以写一个函数,只做代码>返回垃圾邮件。Eggs[()/<代码>,把它传递给一个变量,然后调用它,不管怎样,然后你可以通过绕过<代码>垃圾邮件。
>>> 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>>