Имя не определено. усердно изучайте python ex48

#python

Вопрос:

Я перепечатал код из книги learn python hard way ex48, и я получаю имя ошибки «parse_subj» не определено. Я поискал в гугле обычные решения для такого рода ошибок, но этого не произошло.

 
user_sentence = [('verb', 'run'), ('direction', 'north')]
class Sentence(object):

    def __init_(self, subj, verb, obj):
        self.subject = subj[1]
        self.verb = verb[1]
        self.object = obj[1]


    def peek(word_list):
        if word_list:
            word = word_list[0]
            return word
        else:
            return None
    #took the word and get out from list - if it is expecting type return word, if not - None
    def match(word_list, expecting):
        if word_list:
            word = word_list.pop(0)
            if word[0] == expecting:
                return word
            else:
                return None
        else:
            return None

    def skip(word_list, word_type):
        while peek(word_list) == word_type:
            match(word_list, word_type)

    def parse_verb(word_list):
        skip(word_list, 'stop_words')
        next_word = peek(word_list)

        if next_word == 'verb':
            return match(word_list, 'verb')
        else:
            raise ParserError('Expected a verb')

    def parse_obj(word_list):
        skip(word_list, 'stop_words')
        next_word = peek(word_list)

        if next_word == 'nouns':
            return match(word_list, 'nouns')
        elif next_word == 'direction':
            return match(word_list, 'direction')
        else:
            raise ParserError('Expected an obj')

    def parse_subj(word_list):
        skip(word_list, 'stop_words')
        next_word = peek(word_list)

        if next_word == 'pron':
            return match(word_list, 'pron')
        elif next_word == 'verb':
            return ('noun', 'player')
        else:
            raise ParserError('Expected an subj')

    def parse_sentence(word_list):
        subj = parse_subj(word_list)
        verb = parse_verb(word_list)
        obj = parse_obj(word_list)
        return Sentence(subj, verb, obj)

example = Sentence.parse_sentence(user_sentence)
print(example)
 

Я попытался поиграть с самим собой и вызвать класс предложения в другой переменной, но это не сработало. Я даже скопировал код из pdf-книги, и он все равно не работал

Комментарии:

1. Вам нужно перепроверить код, с которого вы скопировали. Если предполагается, что эти функции являются методами класса, все они должны иметь self в качестве первого параметра, и ваш вызов на parse_subj(word_list) самом деле должен быть self.parse_subj(word_list) . Хотя это не единственная проблема с кодом.

2. Оказалось, что в исходном коде все функции находились вне предложения класса. Вот почему все предлагаемые решения для исправления моего кода указывали на необходимость самостоятельного аргументирования

Ответ №1:

В коде Python существует так называемая Глобальная область. Это относится ко всем функциям и переменным, которые не находятся внутри какого-либо класса или какой-либо функции.

Когда вы просто говорите parse_subj , интерпретатор будет искать этот метод в глобальной области. Но ваш метод на самом деле находится внутри класса Sentence . Вам нужно явно указать интерпретатору, который parse_subj находится внутри Sentence класса, а не в глобальной области. Вы делаете это либо , говоря self.parse_subj , где self находится первый параметр parse_subj метода, представляющий экземпляр Sentence созданного вами класса. Либо это, либо вы используете то, что известно как неограниченный вызов, где вы явно указываете Sentence.parse_subj , чтобы сообщить интерпретатору, где находится метод.

Я не советую использовать второй подход, но он выглядит логичным, поскольку ни у одного из методов вашего класса даже нет self параметра, за исключением инициализатора вверху. Вам нужно будет выполнить добавление всего кода Sentence. перед каждым вызовом метода в Sentence классе.

Ответ №2:

Во-первых, word_list-это не список, как вы предполагали, в большинстве ваших методов это экземпляр example

Во-вторых, поскольку методы, которые вы пытаетесь вызвать, являются частью этого экземпляра, вот как вы должны их вызывать: self.word_list и вот как должны быть ваши параметры: self, word_list в правильном порядке

В-третьих, вместо example = Sentence.parse_sentence(user_sentence) того, чтобы делать

 example = Sentence("example_subj", "example_verb", "example_obj")
example.parse_sentence(user_sentence)
 

в конце концов, вот окончательный код:

 user_sentence = [('verb', 'run'), ('direction', 'north')]
class Sentence(object):

    def __init_(self, subj, verb, obj):
        self.subject = subj[1]
        self.verb = verb[1]
        self.object = obj[1]


    def peek(self, word_list):
        if word_list:
            word = word_list[0]
            return word
        else:
            return None
    #took the word and get out from list - if it is expecting type return word, if not - None
    def match(self, word_list, expecting):
        if word_list:
            word = word_list.pop(0)
            if word[0] == expecting:
                return word
            else:
                return None
        else:
            return None

    def skip(self, word_list, word_type):
        while self.peek(word_list) == word_type:
            self.match(word_list, word_type)

    def parse_verb(self, word_list):
        self.skip(word_list, 'stop_words')
        next_word = self.peek(word_list)

        if next_word == 'verb':
            return self.match(word_list, 'verb')
        else:
            raise ParserError('Expected a verb')

    def parse_obj(self, word_list):
        self.skip(word_list, 'stop_words')
        next_word = self.peek(word_list)

        if next_word == 'nouns':
            return match(word_list, 'nouns')
        elif next_word == 'direction':
            return self.match(word_list, 'direction')
        else:
            raise ParserError('Expected an obj')

    def parse_subj(self, word_list):
        self.skip(word_list, 'stop_words')
        next_word = self.peek(word_list)

        if next_word == 'pron':
            return self.match(word_list, 'pron')
        elif next_word == 'verb':
            return ('noun', 'player')
        else:
            raise ParserError('Expected an subj')

    def parse_sentence(self, word_list):
        subj = self.parse_subj(word_list)
        verb = self.parse_verb(word_list)
        obj = self.parse_obj(word_list)
        return Sentence(subj, verb, obj)

example = Sentence.parse_sentence(user_sentence)
print(example)
 

Ответ №3:

Быстрый ответ на ваш вопрос заключается в том, что при обращении к методу parse_subj внутри класса, вы должны вызвать его в зависимости от его типа, например, если это метод экземпляра, вам нужно определить экземпляр класса, прежде чем обращаться к этому методу, при условии, что данный метод должен быть написан, чтобы принять self (относится к экземпляру объекта) в качестве первого аргумента.

Для меня фактический ответ на ваш вопрос-пропустить этот класс предложений, так как он очень сложный. Это все равно что научиться умножать, не понимая, как работает сложение. Вы должны понимать, как работают эти 3 типа методов в классе:

  1. Статический метод — оформленный @staticmethod , может быть вызван с помощью самого класса или экземпляра класса
  2. Метод класса — оформлен @classmethod , принимает cls в качестве первого аргумента, где cls ссылается на сам класс, может быть вызван с использованием самого класса или экземпляра класса
  3. Метод экземпляра — без декоратора, принимает self в качестве первого аргумента, где self ссылается на объект класса, может быть вызван только с использованием экземпляра класса

Возможно, вас заинтересует приведенный ниже код, который просто выводит текст.

 class Sample:
    outer_var = "my outer var"

    def __init__(self, var):
        print(f"__init__ var = {var}")
        self.inner_var = var

    @staticmethod
    def this_is_static_method(var3):
        print("==========")
        print(f"this_is_static_method")

        try: print(f"tSample.outer_var = {Sample.outer_var}")
        except Exception: print("tERROR!!! Cannot access Sample.outer_var")

        try: print(f"tSample.inner_var = {Sample.inner_var}")
        except Exception: print("tERROR!!! Cannot access Sample.inner_var")

        print(f"tvar3 {var3}")

    @classmethod
    def this_is_class_method(cls, var3):
        print("==========")
        print(f"this_is_class_method type(cls) {type(cls)} cls {cls}")

        try: print(f"tcls.outer_var = {cls.outer_var}")
        except Exception: print("tERROR!!! Cannot access cls.outer_var")

        try: print(f"tcls.inner_var = {cls.inner_var}")
        except Exception: print("tERROR!!! Cannot access cls.inner_var")

        print(f"tvar3 {var3}")
        return cls(var3)

    def this_is_instance_method(self, var3):
        print("==========")
        print(f"this_is_instance_method type(self) {type(self)} self {self}")

        try: print(f"tself.outer_var = {self.outer_var}")
        except Exception: print("tERROR!!! Cannot access self.outer_var")

        try: print(f"tself.inner_var = {self.inner_var}")
        except Exception: print("tERROR!!! Cannot access self.inner_var")

        print(f"tvar3 {var3}")

print("nnUSING THE CLASS DIRECTLYnn")

Sample.this_is_static_method(111)
Sample.this_is_class_method(222)
try: Sample.this_is_instance_method(333)
except Exception: print("==========nERROR!!! Cannot access Sample.this_is_instance_method")

print("nnUSING AN INSTANCE OBJECTnn")

sample_instance = Sample(444)
sample_instance.this_is_static_method(555)
sample_instance.this_is_class_method(666)
sample_instance.this_is_instance_method(777)
 

Выход:

 USING THE CLASS DIRECTLY


==========
this_is_static_method
    Sample.outer_var = my outer var
    ERROR!!! Cannot access Sample.inner_var
    var3 111
==========
this_is_class_method type(cls) <class 'type'> cls <class '__main__.Sample'>
    cls.outer_var = my outer var
    ERROR!!! Cannot access cls.inner_var
    var3 222
__init__ var = 222
==========
ERROR!!! Cannot access Sample.this_is_instance_method


USING AN INSTANCE OBJECT


__init__ var = 444
==========
this_is_static_method
    Sample.outer_var = my outer var
    ERROR!!! Cannot access Sample.inner_var
    var3 555
==========
this_is_class_method type(cls) <class 'type'> cls <class '__main__.Sample'>
    cls.outer_var = my outer var
    ERROR!!! Cannot access cls.inner_var
    var3 666
__init__ var = 666
==========
this_is_instance_method type(self) <class '__main__.Sample'> self <__main__.Sample object at 0x1551aff90730>
    self.outer_var = my outer var
    self.inner_var = 444
    var3 777