TypeError:未绑定方法

2024-09-06 11:35:00 浏览数 (1)

TypeError: unbound method 错误通常发生在类方法被调用时,但没有正确绑定到实例。这通常意味着你试图在类本身上调用一个实例方法,或者没有使用正确的方式创建类实例。

1、问题背景

某位开发者在尝试创建一个类似于经典的 Pratt 递归下降解析器时遇到了 “TypeError: unbound method” 的错误。在简化了代码之后,开发者发现问题出在对中缀运算符的处理上,具体来说是 infix_led 函数没有正确绑定到 symbol 类的实例。

2、解决方案:

有两种解决方案:

方法1:tokenize() 函数中,每当遇到一个非数字的运算符时,不直接生成一个 symbol 类,而是生成一个 symbol() 的实例。这确保了每个运算符都有一个单独的实例,可以绑定各自的 led 函数。

方法2: 使用 types.MethodType 函数将 infix_led 函数绑定到 symbol 类的实例上。这是一种更显式的绑定方式,也确保了每个运算符都有一个单独的实例,可以绑定各自的 led 函数。

代码示例:

代码语言:javascript复制
class Symbol_base(object):
    """ A base class for all symbols"""
    id = None # node/token type name
    value = None #used by literals
    first = second = third = None #used by tree nodes
​
    def nud(self):
        """ A default implementation for nud """
        raise SyntaxError("Syntax error (%r)." % self.id)
​
    def led(self,left):
        """ A default implementation for led """
        raise SyntaxError("Unknown operator (%r)." % self.id)
​
    def __repr__(self):
        if self.id == "(name)" or self.id == "(literal)":
            return "(%s %s)" % (self.id[1:-1], self.value)
        out = [self.id, self.first, self.second, self.third]
        out = map(str, filter(None,out))
        return "("   " ".join(out)   ")"
​
​
symbol_table = {}
def symbol(id, bindingpower=0):
    """ If a given symbol is found in the symbol_table return it.
        If the symblo cannot be found theni create the appropriate class
        and add that to the symbol_table."""
    try:
        s = symbol_table[id]
    except KeyError:
        class s(Symbol_base):
            pass
        s.__name__ = "symbol:"   id #for debugging purposes
        s.id = id
        s.lbp = bindingpower
        symbol_table[id] = s
    else:
        s.lbp = max(bindingpower,s.lbp)
    return s
​
​
def infix(id, bp):
    """ Helper function for defining the symbols for infix operations """
    def infix_led(self, left):
        self.first = left
        self.second = expression(bp)
        return self
    symbol(id, bp).led = infix_led
​
​
#define all the symbols
infix(" ", 10)
symbol("(literal)").nud = lambda self: self #literal values must return the symbol itself
symbol("(end)")
​
token_pat = re.compile("s*(?:(d )|(.))")
​
def tokenize(program):
    for number, operator in token_pat.findall(program):
        if number:
            symbol = symbol_table["(literal)"]
            s = symbol()
            s.value = number
            yield s
        else:
            symbol = symbol_table.get(operator)
            if not symbol:
                raise SyntaxError("Unknown operator")
            yield symbol()
    symbol = symbol_table["(end)"]
    yield symbol()
​
​
def expression(rbp = 0):
    global token
    t = token
    token = next()
    left = t.nud()
    while rbp < token.lbp:
        t = token
        token = next()
        left = t.led(left)
    return left
​
​
def parse(program):
    global token, next
    next = tokenize(program).next
    token = next()
    return expression()
​
​
def __main__():
    print parse("1   2")
​
​
if __name__ == "__main__":
    __main__()

在这个代码示例中,tokenize() 函数生成 Symbol_base 类的实例,并且使用 types.MethodType() 函数将 infix_led 函数绑定到每个实例上。这样就确保了每个运算符都有一个单独的实例,并且他们的 led 函数都正确绑定到了各自的实例上。

如果你遇到 TypeError: unbound method 错误,请确保你正确地实例化类,并通过实例调用方法。如果确实需要通过类调用方法,请使用 @classmethod@staticmethod 装饰器。

希望这个解释和解决方案对你有所帮助。

0 人点赞