LINUX.ORG.RU

правильное наследование в python

 ,


0

1

Всем привет. Уж простите за мой откровенный тупняк, но что-то не могу додуматься. В общем в чём соль. У меня есть три класса. 2 наследуются от 1 главного. Всё лежит в одном файле. Как мне правильно разнести эти классы по файлам, т.е. модулям, и наследоваться от главного класса внутри отдельного файла?

Надеюсь понятно описал.

Всем заранее спасибо за помощь.

Ответ на: комментарий от peregrine

Ну это понятно. Смотри. Есть 1 файл, в котором идёт выполнение, например

class A(object):
    def __init__(self):
        self.asd = 123

и так далее.

В класс A я хочу добавить переменную B, которая является классом B, находящимся в другом файле, при этом наследоваться он должен от А.

mahalaka ★★ ()
Ответ на: комментарий от mahalaka

Ты что, хочешь множественное наследование или просто чтобы элемент класса был классом?

Есть у тебя 3 класса, назовем их A, B, C. A это общий для всех классов класс или у тебя другая схема?

peregrine ★★★★★ ()
Последнее исправление: peregrine (всего исправлений: 1)
Ответ на: комментарий от peregrine

Хочу чтобы элемент класса был классом, наследованным от класса, который его вызывает. Чё-то такое. Короче чтобы класс А вызывал функции, которые находятся в классе Б, а класс Б бы наследовался от класса А, и при этом находился в другом модуле.

mahalaka ★★ ()
Ответ на: комментарий от mahalaka

Ты схематично нарисуй что ты хочешь и станет понятно. Пока мне кажется ты просто в голове не представляешь четкой картины что и отчего должно наследоваться.

Я бы не страдал с циклическими зависимостями и разрулил бы всё попроще. А то выходит что у тебя класс А должен наследоваться от Б, а Б от А. Это — дурная идея вне зависимости от ЯП. Ну или просто дергай методы другого класса как ты делаешь с обычными модулями.

peregrine ★★★★★ ()
Ответ на: комментарий от peregrine

Эх. Ну вот что-то такое примерно: Есть a.py, в нём класс A:

class A(object):
    def __init__(self, a):
        self.asd = 123

есть b.py

#from a import A
from test import class_a

class B(class_a):
    def __init__(self):
        self.qwerty = 'hllo'
    def go(self):
        #print(A.asd)
        print(self.asd)

который должен наследоваться от класса A, который инициализируется в test.py

ну и собственно test.py:

import a
import b

class_a = a.A(123)
class_b = b.B()

class_b.go()

mahalaka ★★ ()
Ответ на: комментарий от mahalaka

Вот тут уже понятнее что ты хочешь. Хотя мне все равно не нравится что ты пытаешься сделать (я бы сделал отдельно A_BASE от которого бы наследовал всё остальное и уже в унаследованном от него A инициализировал B и C, но если питон позволяет такое наследование как ты хочешь, то норм.) По теме не путай класс и объект, это разные вещи в общем случае. Я медленно читаю и пишу, так что последний коммент пока не видел.

peregrine ★★★★★ ()
Последнее исправление: peregrine (всего исправлений: 1)
Ответ на: комментарий от peregrine

я бы сделал отдельно A_BASE от которого бы наследовал всё остальное и уже в унаследованном от него A инициализировал B и C

Можешь примерно расписать как это бы выглядело?

mahalaka ★★ ()
Ответ на: комментарий от peregrine

Позволять-то позволяет, когда пространство A, B и C в одном файле. То есть если я в test.py это всё объединю это будет работать. А если раскидать по разным модулям то до меня не доходит как импортнуть объект инициализированного класса и наследоваться от него.

mahalaka ★★ ()
Ответ на: комментарий от mahalaka

К сожалению, такая идея в принципе не работоспособна, т.к. в class B требуется инициализация класса а. Т.е. класс B должен принимать все аргументы класса А и быть самодостаточным.

peregrine ★★★★★ ()
Ответ на: комментарий от mahalaka

Так а что мешает его раскидать по файлам? Если нужно именно для тестирования, так для этого бери и импортируй все классы и перед тестированием наполняй их данными. Всё же есть. Нет нужды пробовать наследоваться от существующих объектов.

conformist ★★★ ()
Ответ на: комментарий от mahalaka

Но ты можешь сделать так: a.py

class ClassA(object):
    def __init__(self, a):
        self.asd = a
        self.bc = "something"
b.py
from a import ClassA

class ClassB(ClassA):
    def __init__(self, a):
        self.qwerty = 'hello'
        super(ClassB, self).__init__(a)
    def go(self):
        print(self.asd)
        print(self.bc)
        print(self.qwerty)
test.py
#import a
import b

#class_a = a.ClassA(123)
class_b = b.ClassB(12)

class_b.go()
Результат вывода:
12
something
hello
Обрати внимание, что если раскомментировать class_a и всё что с ним связано, на то что хранится в классе b это никак не повлияет.

peregrine ★★★★★ ()
Ответ на: комментарий от mahalaka

Только учти, что у тебя там классы наследуются, а не объекты в объекты складываются. Это немного разные вещи. И поставь себе PyCharm, там подсказки по ошибкам и дебаггер очень классные и удобные.

peregrine ★★★★★ ()
Ответ на: комментарий от conformist

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

mahalaka ★★ ()
Последнее исправление: mahalaka (всего исправлений: 1)
Ответ на: комментарий от mahalaka

переменные становятся доступны из родительских классов

всё хуже. В данном случае он позволяет инициализировать в твоем классе то что инициализируется в родителе. Но инициализация происходит именно в наследнике и никак не связана с состоянием объектов родителей.

peregrine ★★★★★ ()
Ответ на: комментарий от mahalaka

Если тебе нужен asd из текущего экземпляра и он определен в инициализаторе:

class B(A):
    def __init__(self, ...):
        super().__init__(self, a)
        ...

    def go(self,):
        return self.asd
Если нужен asd из класса А вместо текущего экземпляра или же asd определено вне инициализатора:
class B(A):
    ...
    @classmethod
    def go(cls,):
        return cls.asd

mazdai ★★ ()
Ответ на: комментарий от mazdai

Как можно накостылить, я уже предоставил ссылку выше. Можно написать и более изощрённые способы, но я бы лучше уточнил, в чём конкретно проблема у ТС, т.к. пока методы решения проблемы не впечатляют.

conformist ★★★ ()
Ответ на: комментарий от conformist

но я бы лучше уточнил, в чём конкретно проблема у ТС, т.к. пока методы решения проблемы не впечатляют.

Поддержу, «разожрался код в одном модуле, хотел реализовать всё это дело в разных классах, и раскидать по разным файлам», не тянет на повод делать такое.

vvn_black ★★★★★ ()
Ответ на: комментарий от vvn_black

Что-то по количеству плясок вокруг всего этого мне тоже так кажется. Может посоветуете правильный путь тогда как разбивать большие модули на модули поменьше? Функциональный путь мне не особо нравится, т.к. тут тоже будет много мороки.

mahalaka ★★ ()
Ответ на: комментарий от mahalaka

Просто определи пустые методы, лучше - кидающие исключение в случае вызова, в классе A и вызывай их из него сколько влезет.

Потом в B и C просто наследуешь класс А, определяешь нормальные тела тех самых методов и все.

ЕМНИП, в питоне даже не обязательно объявлять такие методы в теле класса А, при этом в других его методах вполне допустимо вызывать «несуществующие методы».

shkolnick-kun ★★★ ()
Последнее исправление: shkolnick-kun (всего исправлений: 2)
Ответ на: комментарий от peregrine

вот, кстати, и у меня по этому поводу вопрос: есть класс, у которого куча методов. Хочется «разбить» этот класс, но так, чтобы по-прежнему вызывать все методы объекта простым object.methodN(), (N -> infinity), как это правильнее сделать?

Sahas ★★★★★ ()
Ответ на: комментарий от conformist

О каких методах решения можно говорить, не определив проблему? Это верно. setattr( лучше getattr(, поскольку под капотом класса могут производиться махинации с атрибутом, возвращаемым объектом из другого объекта/класса: если возвращается чужой, а операции производятся со своим, в итоге получится очевидно нежелательное/неопределенное поведение

mazdai ★★ ()
Последнее исправление: mazdai (всего исправлений: 1)
Ответ на: комментарий от vvn_black

Отличное решение, правда, если в наследуемых классах каша и нет определенной задачи, ими решаемой в рамках своих методов, это может создать охрененное количество проблем, поэтому я бы не посоветовал множественное наследование новичку в ООП

mazdai ★★ ()
Ответ на: комментарий от Sahas

а поскольку речь о питоне, где классы легко и непринужденно создаются через

cls=type(name, chain_of_classes, additional_props)
то ты можешь прям в райнтайме лепить нужные тебе комбинации классов ;)

genryRar ★★ ()