getter setter作为python类中的函数,给出“未找到属性";错误 [英] getter setter as function in python class giving "no attribute found" error

查看:84
本文介绍了getter setter作为python类中的函数,给出“未找到属性";错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

import operator
import re
from ply import lex, yacc

class Lexer(object):

    tokens = [
        'COMMA',
        'TILDE',
        'PARAM',
        'LP',
        'RP',
        'FUNC'
    ]

    # Regular expression rules for simple tokens
    t_COMMA = r'\,'
    t_TILDE = r'\~'
    t_PARAM = r'[^\s\(\),&:\"\'~]+'

    def __init__(self, dict_obj):
        self.dict_obj = dict_obj

    def t_LP(self, t):
        r'\('
        return t

    def t_RP(self, t):
        r'\)'
        return t

    def t_FUNC(self, t):
        # I want to generate token for this FUNC from the keys of model map
        # For eg: r'key1|key2'
        r'(?i)FUNC'
        return t

    # Define a rule so we can track line numbers
    def t_newline(self, t):
        r'\n+'
        t.lexer.lineno += len(t.value)

    # A string containing ignored characters (spaces and tabs)
    t_ignore = ' \t'

    # Error handling rule
    def t_error(self, t):
        print("Illegal character '%s' on line %d, column %d" % (t.value[0], t.lexer.lineno, t.lexer.lexpos))
        t.lexer.skip(1)

    # Build the lexer
    def build_lexer(self, **kwargs):
        self.lexer = lex.lex(module=self, **kwargs)
        return self.lexer

class Parser(object):

    tokens = Lexer.tokens

    def __init__(self, **kwargs):
        self.parser = yacc.yacc(module=self, **kwargs)
        self.lexer = None
        self._dict_obj = None
        self.error = ""
        self.result = ""

    @property
    def dict_obj(self):
        return self._dict_obj

    @dict_obj.setter
    def dict_obj(self, dict_obj):
        self._dict_obj = dict_obj
        self.lexer = Lexer(self._dict_obj).build_lexer()

    # Handles LP expression RP
    def p_expression(self, p):
        """
        expression : LP expression RP
        """

    # Handles TILDE PARAM - call search
    def p_tilde_param(self, p):
        """
        expression : TILDE PARAM
        """     
        p[0] = p[2]
        return p[0]

    # Handles ANY LP PARAM RP - call search
    def p_expression_any(self, p):
        """
        expression : FUNC LP PARAM RP
        """
        p[0] = p[3]
        return p[0]

    # Error handling rule
    def p_error(self, p):
        if p:
            stack_state_str = " ".join([symbol.type for symbol in self.parser.symstack[1:]])
            self.error = "Syntax error at %s, type %s, on line %d, Parser state: %s %s . %s" % (
                p.value, p.type, p.lineno, self.parser.state, stack_state_str, p
            )
        else:
            self.error = "SYNTAX ERROR IN INPUT"

    def get_result(self, input_):
        input_ = input_.strip()
        if input_:
            self.result = self.parser.parse(input_, lexer=self.lexer)      
            return self.result
        else:
            raise ValueError("EMPTY EXPRESSION ERROR")

def parser(input_):
    par_obj = Parser()
    par_obj.dict_obj = {
      'key1' : 'value1',
      'key2'   : 'value2'
    }
    return par_obj.get_result(input_)

result = parser("~hello")

上面是使用ply库的词法分析器和解析器的代码.我刚刚将所有代码封装为类形式.我面临的问题:

Above is the code of lexer and parser using ply library. I have just encapsulated all of my code in the class form. Problems which i am facing:

1.)我正在尝试将dict_obj传递给解析器类.我不知道我在做错什么,并得到类似这样的错误:

1.) I'm trying to pass a dict_obj to the parser class. I don't know what i am doing wrong and getting an error like :

AttributeError: 'Parser' object has no attribute 'dict_obj'

2.)我要做什么?

我想将此dict_obj传递给解析器类,然后也将其传递给lexer类,然后在标记器方法(t_FUNC)方法之一的lexer中使用它.在这种方法中,我的正则表达式将返回此dict obj的键.

I want to pass this dict_obj to the parser class and then pass it to the lexer class as well and then make use of it in the lexer one of the tokens methods (t_FUNC) method. In this method my regex will return keys of the this dict obj.

我认为我做错了什么,因此无法实现.请帮忙.

I think i'm doing something wrong and hence failing to implement it. Please help.

推荐答案

Parser对象的构造函数(__init__)中,您要求Ply在完全构造Parser对象之前生成解析器:

In your constructor (__init__) for the Parser object, you ask Ply to generate a parser before the Parser object is fully constructed:

def __init__(self, **kwargs):
    self.parser = yacc.yacc(module=self, **kwargs)
    # This is the critical line:
    self._dict_obj = None

为了从对象(yacc.yacc(module=self))构造解析器,Ply需要遍历对象的所有属性.例如,它需要找到所有解析器函数以提取其文档字符串以确定语法.

In order to construct a parser from the object (yacc.yacc(module=self)), Ply needs to iterate over all the object's attributes. For example, it needs to find all the parser functions in order to extract their docstrings in order to determine the grammar.

Ply使用内置的dir函数制作一个包含所有对象属性的字典.因为您的Parser对象具有自定义属性dict_obj,所以该键是从dir返回的,因此Ply尝试使用其值缓存该属性.但是,当它调用gettattr(module, 'dict_obj')时,将调用getter,并且getter尝试返回self._dict_obj.但是,尚未定义self._dict_obj,因此最终会引发错误:

Ply uses the dir built-in function to make a dictionary of all the object's attributes. Because your Parser object has a custom attribute dict_obj, that key is returned from dir and so Ply tries to cache that attribute with its value. But when it calls gettattr(module, 'dict_obj'), the getter is called, and the getter tries to return self._dict_obj. However, self._dict_obj has not yet been defined, so that ends up throwing an error:

AttributeError: 'Parser' object has no attribute '_dict_obj'

请注意,这不是不是您在问题中报告的错误消息;该错误表明没有属性dict_obj.也许那是复制粘贴错误.

Note that this is not the error message you reported in your question; that error says that there is no attribute dict_obj. Perhaps that was a copy-and-paste error.

如果将调用移至yacc.yacc到初始化程序的末尾,则该特定问题将消失:

If you move the call to yacc.yacc to the end of the initialiser, that particular problem goes away:

def __init__(self, **kwargs):
    self.lexer = None
    self._dict_obj = None
    self.error = ""
    self.result = ""
    self.parser = yacc.yacc(module=self, **kwargs)

但是,代码摘录中还有许多其他问题,使得很难验证此解决方案.这些包括:

However, there are a number of other problems in the code excerpt which make it difficult to verify this solution. These include:

  1. 没有LexerNmsysSearch.我以为你是说Lexer.

没有node_expression.我不知道那应该是什么,所以我只是删除了测试.

There is no node_expression. I have no idea what that is supposed to be so I just removed the test.

您的语法与您正在测试的输入不匹配,因此解析器会立即引发语法错误.我将输入更改为"(~hello)",以尝试产生可解析的内容.

Your grammar does not match the input you are testing, so the parser immediately throws a syntax error. I changed the input to "(~hello)" in an attempt to produce something parseable.

解析器操作未设置语义值,因此self.parse.parse()不返回任何值.这会导致get_result引发错误.

The parser actions do not set semantic values, so self.parse.parse() doesn't return any value. This causes get_result to throw an error.

那时候,我放弃了尝试从代码中产生任何有意义的东西的想法.为将来参考,请确保正确引用错误消息,并且可以运行问题中包含的示例代码.

At that point, I gave up on trying to produce anything sensible out of the code. For future reference, please ensure that error messages are quoted exactly and that sample code included in the question can be run.

这篇关于getter setter作为python类中的函数,给出“未找到属性";错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆