метод связанного списка против функций - PullRequest
0 голосов
/ 16 ноября 2018

Я пытаюсь понять, почему функция работает как внешняя функция, но не будет работать, если я переместу ее в класс как метод.

Быстро я создал класс связанного списка:

class Link:
    """A linked list."""
    empty = ()

    def __init__(self, first, rest=empty):
        assert rest is Link.empty or isinstance(rest, Link)
        self.first = first
        self.rest = rest

    def __str__(self):
        string = '<'
        while self.rest is not Link.empty:
            string += str(self.first) + ', '
            self = self.rest
        return string + str(self.first) + '>'

поэтому, когда я пытаюсь создать функцию с именем stretch, чтобы я мог:

def stretch(s, repeat=0):
    """Replicate the kth element k times, for all k in s."""
    if s is not Link.empty:
        stretch(s.rest, repeat+1)
        for i in range(repeat):
            s.rest = Link(s.first, s.rest)

Это сработало:

a = Link(3, Link(4, Link(5, Link(6))))
print(a)  # >>> <3, 4, 5, 6>
stretch(a)
print(a)  # >>> <3, 4, 4, 5, 5, 5, 6, 6, 6, 6>

Однако, когда я пытаюсьсоздайте эту функцию как метод класса:

def stretch(self, repeat=0):
    """Replicate the kth element k times, for all k in a linked list."""
    if self is not Link.empty:
        self.rest.stretch(repeat+1)
        for i in range(repeat):
            self.rest = Link(self.first, self.rest) 

Теперь она не будет работать:

b = Link(3, Link(4, Link(5, Link(6))))
b.stretch()
print(b)
# >>> AttributeError: 'tuple' object has no attribute 'stretch'

Я понимаю, что когда b доберется до последнего элемента, b.rest будетбыть пустым кортежем, но в методе написано if self is not Link.empty, он не должен ничего выполнять.Почему это дает мне сообщение об ошибке?

Спасибо!

Ответы [ 2 ]

0 голосов
/ 16 ноября 2018

Первая функция работает независимо от того, является ли s, переданный stretch, объектом Link или Link.empty.

Вторая функция-член не работает, когда объект Link.empty, потому что Link.empty - это кортеж, у которого нет метода. Вы никогда не попадете в функцию, в которой ваш if поймает это.

Вам нужно переместить if на улицу перед вызовом.

0 голосов
/ 16 ноября 2018

Проблема возникает на линии self.rest.stretch(repeat+1).Поскольку вы не передаете второй параметр конструктору в Link(3, Link(4, Link(5, Link(6)))), значение по умолчанию () используется для инициализации поля self.rest, и значение этого поля никогда не изменяется после этого.Таким образом, self.rest.stretch(repeat+1) на самом деле ().stretch(repeat+1).Естественно, (), пустой кортеж, не имеет атрибута stretch.

Первая функция работает, потому что у нее нет оператора-нарушителя.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...