Python AttributeError: объект класса не имеет атрибута

Когда я пытаюсь запустить код класса, который пишу, я получаю AttributeError, и я не знаю, почему. Конкретная ошибка выглядит следующим образом:

    self.marker = self.markers[marker[1:]]
AttributeError: 'TTYFigureData' object has no attribute 'markers'

Вот часть класса, который я пишу:

class TTYFigureData(object):
    """
    data container of TTYFigure
    """
    def __init__(
        self,
        x,                      # x values
        y,                      # y values
        marker          = "_.", # datum marker
        plot_slope      = True
        ):
        self.x          = x
        self.y          = y
        self.plot_slope = plot_slope
        self.set_marker(marker)
        self.markers = {
            "-" : u"None" ,
            "," : u"\u2219"
        }

    def set_marker(
        self,
        marker
        ):
        if marker in [None, "None", u"None", ""]:
            self.plot_slope = True
            self.marker = ""
        elif marker[0] == "_":
            self.marker = self.markers[marker[1:]]
        else:
            self.marker = marker

Где я ошибаюсь?


person d3pd    schedule 28.09.2015    source источник
comment
Стиль вашего кода несколько... идиосинкразичен (ужасно показался немного уничижительным), из-за чего его трудно понять. Однако обратите внимание, что вы вызываете self.set_marker до инициализации self.markers. Учитывая, что self.markers кажется фиксированным, почему бы не сделать его атрибутом класса?   -  person jonrsharpe    schedule 28.09.2015
comment
Пожалуйста, опубликуйте полную трассировку для ошибок Python. В этом случае, например, тот факт, что set_marker() вызывается из __init__, является важным ключом к пониманию того, что происходит не так, обратная трассировка покажет это.   -  person Martijn Pieters    schedule 28.09.2015
comment
@jonsharpe А, вот оно! Хорошо подмечено. Спасибо, что посмотрели. Код грубый, и я знаю, что подход с новой строкой для каждого аргумента функции не считается стандартным. Так ли уж плох этот подход, особенно для большого количества аргументов?   -  person d3pd    schedule 28.09.2015
comment
@MartijnPieters Спасибо за совет. Вы совершенно правы.   -  person d3pd    schedule 28.09.2015
comment
@ d3pd: да, например, очень трудно отличить список аргументов от тела метода. Обязательно прочтите руководство по стилю Python, в котором предлагаются лучшие альтернативы.   -  person Martijn Pieters    schedule 28.09.2015
comment
Не только это, но и выровненные пробелы вокруг значений/назначений по умолчанию - хуже, чем несоответствие, это на самом деле несовместимо. Если вы хотите задокументировать параметры (что хорошо!), сделайте это в строки документации — IDE и автоматические генераторы документации могут фактически использовать информацию, чего они обычно не могут делать со встроенными комментариями.   -  person jonrsharpe    schedule 28.09.2015


Ответы (2)


Ответ Мартина объясняет проблему и дает минимальное решение. Однако, учитывая, что self.markers кажется константой, я бы сделал его атрибутом класса, а не создавал его заново для каждого экземпляра:

class TTYFigureData(object):
    """Data container of TTYFigure."""

    MARKERS = {
        "-": u"None" ,
        ",": u"\u2219",
    }

    def __init__(self, x, y, marker='_.', plot_slope=True):
        """Document parameters here as required."""
        self.x = x
        self.y = y
        self.plot_slope = plot_slope
        self.set_marker(marker)

    def set_marker(self, marker):
        """See also here - usage guidance is also good."""
        if marker in [None, "None", u"None", ""]:
            self.plot_slope = True
            self.marker = ""
        elif marker[0] == "_":
            self.marker = self.MARKERS[marker[1:]]
        else:
            self.marker = marker

(обратите внимание также на изменение стиля в соответствии с официальным руководством )

person jonrsharpe    schedule 28.09.2015
comment
Спасибо за четкое решение и за руководство по изменению атрибута маркеров с атрибута экземпляра на атрибут класса. - person d3pd; 28.09.2015

В вашем методе __init__ вы вызываете self.set_marker() до установки self.markers:

self.set_marker(marker)
self.markers = {
    "-" : u"None" ,
    "," : u"\u2219"
}

Таким образом, когда set_marker() запускается, self.markers пока нет. Переместить вызов на строку ниже:

self.markers = {
    "-" : u"None" ,
    "," : u"\u2219"
}
self.set_marker(marker)
person Martijn Pieters    schedule 28.09.2015
comment
Большое спасибо за четкое решение. Глупо было промахиваться. - person d3pd; 28.09.2015