Форум программистов, компьютерный форум, киберфорум
Наши страницы
Python
Войти
Регистрация
Восстановить пароль
 
Рейтинг 5.00/5: Рейтинг темы: голосов - 5, средняя оценка - 5.00
fswl
0 / 0 / 0
Регистрация: 13.02.2010
Сообщений: 40
#1

Работа с классами

12.01.2016, 12:33. Просмотров 911. Ответов 11
Метки нет (Все метки)

Здравствуйте, такой вопрос, как указать в функции тип аргументов и как потом эти значения этих аргументов использовать в других функциях.

пример

есть класс Аbc

Python
1
2
3
4
5
class Abc:
       def __init__(self, a,b):
                self.a=a
                self.b=b
                self.c=0
И есть класс Deg

Python
1
2
3
class Deg:
        def __init__(self,a):
             self.a=a
есть в этом классе метод create, который на вход получает поле элементы которого являются экземплярами класса Аbc

теперь в другом методе calculate данного класса мне необходимо высчитать и заполнить поля self.с для экземпляров инициализированных в предыдущем методе.

Как это сделать?

я пробовал в методе create создать глобальную переменную(global V), в которую записал входное поле аргументов, а потом в методе calculate вызвать ее и присвоить значение атрибута self.c (что-то типа V[i].c= ), но в ответ Питон понятно дело говорит что элемент списка не имеет такого атрибута.

Отсюда и вопрос, как заранее определить тип элементов входного поля как экземпляры класса Abc и как потом в других методах к ним обращаться?


Спасибо.
0
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
12.01.2016, 12:33
Ответы с готовыми решениями:

Работа с классами о объектами
Создайте следующую программу. Напишите код, описывающий класс Animal: ...

Разбираюсь с классами
Дошел в изучении питона до ооп, как-то сложновато дается тема, если честно, вот...

Операции с классами
Есть задача: Напишите класс Amoeba, описывающий амёб. Каждая амёба имеет цвет...

Написать программу для библиотеки с классами и объектами
Реализовать работу библиотеки (книга, автор, читатель, прокат). Напишите...

Подскажите где ошибка, в первом примере всё работает, но с классами отказ
import glob import sys import os import pprint if sys.platform ==...

11
alex925
2665 / 2277 / 627
Регистрация: 19.03.2012
Сообщений: 8,826
12.01.2016, 12:38 #2
Цитата Сообщение от fswl Посмотреть сообщение
Отсюда и вопрос, как заранее определить тип элементов входного поля как экземпляры класса Abc и как потом в других методах к ним обращаться?
В python не надо определять тип переменных или аргументов для того, чтобы с ними работать.
0
fswl
0 / 0 / 0
Регистрация: 13.02.2010
Сообщений: 40
12.01.2016, 12:44  [ТС] #3
Цитата Сообщение от alex925 Посмотреть сообщение
В python не надо определять тип переменных или аргументов для того, чтобы с ними работать.
да, я это знаю, но это ведь не обязательное правило, а просто удобство что типы можно не определять.

просто не понимаю как из своей ситуации выйти, как объяснить программе что у меня на входе не поле со вложенными списками, а поле с экземплярами другого класса, чтобы я потом мог свободно с атрибутами этих экземпляров работать, а не получать в ответ ошибки типа той что я привел в описании
0
alex925
2665 / 2277 / 627
Регистрация: 19.03.2012
Сообщений: 8,826
12.01.2016, 13:04 #4
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Abc:
    def __init__(self, a, b):
        self.a = a
        self.b = b
        self.c = 0
 
 
class Deg:
    def __init__(self):
        self.instances_abc = []
 
    def create(self, *args):
        self.instances_abc.extend(args)
 
    def calculate(self):
        for i in self.instances_abc:
            i.c = i.a + i.b
 
 
inst1 = Abc(1, 2)
inst2 = Abc(3, 4)
inst3 = Abc(5, 6)
 
d = Deg()
d.create(inst1, inst2, inst3)
d.calculate()
 
# Здесь проверяем, что поменялся атрибут с
for i in range(1, 4):
    print(getattr(globals()['inst{}'.format(i)], 'c'))
P.S Что такое "a" для класса Deg и зачем оно нужно при инициализации я не понял, по этому убрал (вот по этому нужно всему в программе давать нормальные названия, а не использовать просто буквы алфавита!).

Цитата Сообщение от fswl Посмотреть сообщение
да, я это знаю, но это ведь не обязательное правило, а просто удобство что типы можно не определять.
В python не необязательно указывать типы, а их нельзя определить (синтаксически нельзя).
В python 3 появилась конечно аннотация типов. Мы можем указать, что тут ожидаем в такой-то переменной заданный нами тип, но это сделано для улучшения читаемости кода (улучшения подсказок ide) и удобства программиста, а интерпретатор на эти указания типов вообще не смотрит. Мы можем объявить аргумент как строку и передать туда список и ни какой ошибки не будет.
Python
1
2
3
4
5
>>> def example(data: str):
...     print(data)
...     
>>> example([])
[]
0
fswl
0 / 0 / 0
Регистрация: 13.02.2010
Сообщений: 40
12.01.2016, 13:07  [ТС] #5
Цитата Сообщение от alex925 Посмотреть сообщение
P.S Что такое "a" для класса Deg и зачем оно нужно при инициализации я не понял, по этому убрал (вот по этому нужно всему в программе давать нормальные названия, а не использовать просто буквы алфавита!).
ок, понял замечание, думал что лучше не перегружать вопроc, а писать абстрактно, но видимо это только запутывает.

вот код который у меня в программе

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
class Vertex:
    def __init__(self,id,name):
        self.id=id
        self.name=name
        self.minDistance=0
 
class Dijkstra:
    def __init__(self,vertexes):
        self.vertexes=vertexes
 
    def createGraph(self, vertexes, edgesToVertexes):
 
    def computePath(self, sourceId):
в методе creategraf на входе я получаю список вершин графа(поле элементов класса Vertex) и ребер. Поле определяющее вершины выглядит так [[0,"R"],[1,"B"],[2,"G"],[3,"O"],[4,"P"]] - номер вершины и ее имя.

в методе computePath мне надо сделать вычисления и заполнить атрибут minDistance у всех вершин.

для этого я определяю глобальную переменную Versh в методе creategraf
Python
1
2
global versh
versh=vertexes
потом в методе computePath пытаюсь к ней обратиться чтобы заполнить атрибут minDistance

Python
1
versh[i].minDistance=
но Питон выдают ошибку, что у элемента поля versh нет атрибута minDistance
0
alex925
2665 / 2277 / 627
Регистрация: 19.03.2012
Сообщений: 8,826
12.01.2016, 13:25 #6
Цитата Сообщение от fswl Посмотреть сообщение
для этого я определяю глобальную переменную Versh
Глобальные переменные это зло и былокод, не используй их. Я тебе уже показал, как надо.

Добавлено через 5 минут
Кстати, плохая идея сделать вершину в виде класса. Тебе нужно будет создавать множество экземпляров класса, а это затратная операция, программа будет медленно работать.
Для работы с графами есть уже готовые библиотеки, где уже есть все (networkx). В этом же как раз и прелесть python, почти все уже есть готовое.

Если уж прям свербит как хочется все сделать самому, то почитай вот это http://aliev.me/runestone/Graphs/Objectives.html, там есть и примеры и объяснения.
0
fswl
0 / 0 / 0
Регистрация: 13.02.2010
Сообщений: 40
12.01.2016, 13:29  [ТС] #7
Цитата Сообщение от alex925 Посмотреть сообщение
Я тебе уже показал, как надо.
если кратко, то ты просто в классе создал дополнительный атрибут и предлагаешь использовать его как "глобальную переменную"?
0
alex925
2665 / 2277 / 627
Регистрация: 19.03.2012
Сообщений: 8,826
12.01.2016, 13:39 #8
Цитата Сообщение от fswl Посмотреть сообщение
и предлагаешь использовать его как "глобальную переменную"?
Это называется атрибут экземпляра класса и да я предлагаю хранить данные в самом логичном для этого месте.
0
fswl
0 / 0 / 0
Регистрация: 13.02.2010
Сообщений: 40
12.01.2016, 21:09  [ТС] #9
Цитата Сообщение от alex925 Посмотреть сообщение
Кстати, плохая идея сделать вершину в виде класса.
Цитата Сообщение от alex925 Посмотреть сообщение
Если уж прям свербит как хочется все сделать самому
свербит не у меня, а у препода. Вершина в виде класса так же прописана в условии задачи, как и наличие методов createGraf и ComputePath и их функционал
Цитата Сообщение от alex925 Посмотреть сообщение
Я тебе уже показал, как надо.
попробовал сделать как ты написал, все равно возвращает ошибку. По итогу вернулся к тому с чего начал... надо как-то объяснить программе что поле на входе метода createGraph состоит из экземпляров класса Vertex. Возможно я неправильно понял ваш пример.

вот нынешний код у меня:

Python
1
2
3
4
5
6
7
class Vertex:
    def __init__(self,id,name):
        self.id=id
        self.name=name
        self.minDistance=0 
        self.previousVertex=None 
        self.edges=[]
Python
1
2
3
4
class Dijkstra:
    def __init__(self,vertexes):
        self.vertexes=vertexes
        self.allvertexes=[]
Python
1
2
3
def createGraph(self, vertexes, edgesToVertexes): 
        
        self.allvertexes.extend(vertexes)
Python
1
2
3
def computePath(self, sourceId):
       for i in self.allvertexes:
            i.minDistance =5
Python
1
2
3
dijkstra = Dijkstra([[0,"R"],[4,"P"]])
dijkstra.createGraph([[0,"R"],[1,"B"],[2,"G"],[3,"O"],[4,"P"]],[[0,1,5],[0,2,10],[0,3,8],[1,4,7],[1,2,3],[3,4,2]])
dijkstra.computePath(3)
на строчку i.minDistance = 5 в методе computePath интерпретатор выдает ошибку AttributeError: 'list' object has no attribute 'minDistance'

Цитата Сообщение от alex925 Посмотреть сообщение
Тебе нужно будет создавать множество экземпляров класса
вот похоже именно в это я и уперся, метод воспринимает поле на входе не как поле экземпляров класса, а как поле двух-элементных списков
0
alex925
2665 / 2277 / 627
Регистрация: 19.03.2012
Сообщений: 8,826
12.01.2016, 21:52 #10
Цитата Сообщение от fswl Посмотреть сообщение
попробовал сделать как ты написал, все равно возвращает ошибку
Покажи что сделал и тогда будем говорить конкретно. Ты говоришь о каких-то абстрактных ошибках, которых я не вижу.
Цитата Сообщение от fswl Посмотреть сообщение
вот похоже именно в это я и уперся, метод воспринимает поле на входе не как поле экземпляров класса, а как поле двух-элементных списков
Во 1 тут какой-то дикий набор слов, во 2 что ты питону сказал делать то он и сделал. У тебя проблема чисто в том, что ты не понимаешь, что говоришь и что делаешь.

Покажи, что ты сделал по аналогии с моим примером и лучше выложи оригинальное задание.
0
fswl
0 / 0 / 0
Регистрация: 13.02.2010
Сообщений: 40
12.01.2016, 22:54  [ТС] #11
Цитата Сообщение от alex925 Посмотреть сообщение
У тебя проблема чисто в том, что ты не понимаешь, что говоришь и что делаешь.
понимаю и то и другое. просто в условии задания придуманы эти самые рамки, как например создание Вершины как класса. Сделаны эти рамки для того чтобы студенты не брали готовые решения из интернета
Цитата Сообщение от alex925 Посмотреть сообщение
Покажи, что ты сделал по аналогии с моим примером
я как раз в своих листингах это и сделал.

Задание: Реализация алгоритма Дийкстры
Требования:
Python
1
2
3
4
5
class Edge:
    def __init__(self,source,target,weight):
        self.source=source начало ребра
        self.target=target конец ребра
        self.weight=weight вес ребра
Python
1
2
3
4
5
6
7
class Vertex:
    def __init__(self,id,name):
        self.id=id
        self.name=name
        self.minDistance=0 минимальное расстояние до данной вершины из вершины, которая используется в методе computePath
        self.previousVertex=None предыдущая вершина, через которую идет кратчайшее расстояние до данной вершины(Vertex)
        self.edges=[] список ребер содержащих данную вершину
Python
1
2
3
4
5
6
7
class Dijkstra:
    def __init__(self,vertexes):
        self.vertexes=vertexes
 
    def createGraph(self, vertexes, edgesToVertexes): метод создает граф из заданных вершин. Vertexes - поле объектов типа Vertex.edgesToVertexes - поле объектов типа Edge
 
    def computePath(self, sourceId): метод высчитывает кратчайшие расстояния из данной вершины(sourceId) до всех остальных и заполняет для всех этих вершин атрибут minDistance
и т.д.

сама программа имеет вид
Python
1
2
3
dijkstra = Dijkstra([[0,"R"],[4,"P"]])
dijkstra.createGraph([[0,"R"],[1,"B"],[2,"G"],[3,"O"],[4,"P"]],[[0,1,5],[0,2,10],[0,3,8],[1,4,7],[1,2,3],[3,4,2]])
dijkstra.computePath(3)
в методе createGraf я создаю граф в виде матрицы смежности;

в методе computePath я высчитываю кратчайшие расстояния до требуемой вершины и записываю их в список вида [1,2,0,4,5].

Теперь мне надо заполнить атрибут minDistance у всех вершин. По вашему совету избавился от глобальных переменных и теперь делаю так

в класс Dijkstra добавляю атрибут self.allvertexes=[].

в метод createGraf добавил строчку self.allvertexes.extend(vertexes).

В методе computePath пытаюсь к этому атрибуту обратиться
Python
1
2
3
for i in self.allvertexes:
            i.minDistance = short_path[n] #short_path - это поле с высчитанными кратчайшими расстояниями
            n+=1
и вот на этом месте при запуске программы выскакивает ошибка
i.minDistance = short_path[n]
AttributeError: 'list' object has no attribute 'minDistance'
0
sKotenok
359 / 330 / 39
Регистрация: 29.03.2011
Сообщений: 837
13.01.2016, 11:44 #12
Лучший ответ Сообщение было отмечено fswl как решение

Решение

fswl,
1. Для начала, нужно проверить, что у полученного обьекта есть необх. свойство (duck typing в python приветствуется):
Python
1
2
3
4
5
6
def computePath(self, sourceId):
       for i in self.allvertexes:
            if hasattr(i, 'miniDistance'):
                i.minDistance =5
            else:
                # Обработка ошибки.
Или то же самое, но с try-catch:
Python
1
2
3
4
5
       for i in self.allvertexes:
            try:
                i.minDistance =5
            except AttributeError as err:
                # Обработка ошибки.
2. Теперь нужно подумать, что с этой ошибкой делать. Для начала можно выбрасывать более внятный эксепшн:
Python
1
2
# Обработка ошибки.
raise AttributeError('All objects in self.allvertexes need to be a Vertex instances, you set: {0}'.format(type(i)))
Можно создавать экземпляр Vertex из имеющихся в i данных.

Вот только, делать это всё лучше по месту, где данные в класс попадают:

Python
1
2
3
4
5
6
7
8
def createGraph(self, vertexes, edgesToVertexes): 
        for v in vertexes:
            if not isinstance(v, Vertex):
                try:
                    v = Vertex(v[0], v[1])
                except KeyError, IndexError:
                    raise TypeError('Each vertex must be a Vertex instance or iterable with two values: (vetex index, vertex name), you set: {0}'.format(repr(v)))
            self.allvertexes.append(v)
1
13.01.2016, 11:44
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
13.01.2016, 11:44

Работа с классами
Составить описание объектного типа TMatr, что обеспечивает размещение матрицы...

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

Работа с классами
Есть задание, создать 2 класса. Один с данными но без методов, а второй...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru