LINUX.ORG.RU

А можно объединить классы уже после инициализации? Или импортировать атрибуты?

 


0

1

Это наркомания, я понял что никто так не делает:

Подгружать ребенка можно динамически:

        lib = __import__('class_name')
        self.class_child = lib.class_name()

На уровне экземляра класса или на уровне объекта класса?

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

AntonI ()
Последнее исправление: AntonI (всего исправлений: 1)

Смотри-ка, ты сам придумал прототипное наследование.

Я думаю, проще это делать не в __init__, а в __new__. Тогда можно там же создать новый класс, наследующийся от обоих.

proud_anon ★★★★★ ()

А можно объединить классы уже после инициализации?

Обычно в динамических языках такое возможно /и много более/.

Владимир

anonymous ()
Ответ на: комментарий от Virtuos86

Я кот для себя пишу. А у тебя опять нулевая аргументация, вместо того сказать как сделать правильно. Нах ты вообще отвечаешь?

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

Ну тогда объект класса набивать. И в чем проблема? Цикл по атрибутам class2 и напихать их в class1. Или может можно сразу на уровне словарей это сделать… м.б. только завернуть придется.

Я в py3 не лазил а как в py2 не помню, м.б. можно и в список родителей его подсунуть, но это неточно.

AntonI ()
Ответ на: комментарий от steemandlinux

А это не костылестроение?

Три костыля а сверху дощечка - уже табуретка!

На фоне постановки Вашей исходной задачи это не выглядит котылестроением ни разу.

AntonI ()
Ответ на: комментарий от Virtuos86

AntonI

Я понял что я какую-то дичь придумал в попытке уменьшить кот.

class class1(object):
    def __init__(self, class_name): 
        lib = __import__(class_name)
        self.class_child = lib.class_name

    def set_name(self):
        self.class_child.set_name()
        self.name = self.class_child.name

с = class1('class_name')
c.set_name()
name = c.name
Ну или 
class_child = c.class_child, а инит оставить только для импорта, что наверное логичнее, учитывая что в классах абсолютно идентичный API.

Совсем башка сварилась от жары

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

Это модуль импортируется, а из него я второй строкой вызываю класс. Да я забыл вызов добавить lib.class_name() :(

Т.е. названия модулей разные, а классы внутри одинаковые.

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

Понятно. Но я свой пример переделать не могу: в питоне, к сожалению, модульная система завязана на файловую систему, т.е. модуль — это файл, поэтому в одном примере несколько модулей описать невозможно. Большая промашка со стороны Гвидо :(.

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

А что предлагают пользоваться if else?

Для чего?

Для атрибутов есть setattr, hasattr, а для классов что?

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

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

Для чего?

Вот например библиотеки с единым API. Выбираются по данным из БД.

https://github.com/coingecko/cryptoexchange/tree/master/lib/cryptoexchange/ex...

Какие между этими сущностями можно проводить аналогии вообще??

Вызвать атрибут по строковому аргументу я могу с помощью getattr, как загрузить класс по строковому аргументу?

method = getattr(object_name, string)
method()

Как вызвать класс аналогичным способом?

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

Вот например библиотеки с единым API. Выбираются по данным из БД.

if else

Эм, ветвление в зависимости от условий осуществляется с помощью условного оператора, if-elif-else. Ну, еще можно словарь заюзать, наподобие такого:

def error(*a, **kwa): print("ERROR")

cmds = {
    "pull": lambda: print("pull"),
    "put" : lambda msg: print("put %s" % msg),
}

cmds["pull"]()                              # если команды `pull` нет, то будет выброшено исключение KeyError, и программа аварийно завершится
 
cmds.get("put", error)("<log>")  # если команды `put` нет, то будет вызвана "аварийная" команда

cmds.get("putt", error)()             # см. выше ^

Вызвать атрибут по строковому аргументу я могу с помощью getattr, как загрузить класс по строковому аргументу?

Чтобы получить значение объекта по его идентификатору, тебе нужно знать неймспейс, в котором он находится. getattr у тебя тоже требует неймспейс атрибута — объект, которому он принадлежит.

Если тебе известен модуль, в котором находится класс, то getattr можно применять и к модулю:

import time
print(getattr(time, 'time'))
Если класс находится в текущем модуле, то globals()['classname'], а если в локальном неймспейсе, то:
def f():
    class C(object): pass
    print(locals()['C'])

f()

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

Эм, ветвление в зависимости от условий осуществляется с помощью условного оператора, if-elif-else.

Я хотел красиво :(

Так-то я тоже методы лямбдой дергаю:

map(lambda a: xml_tag_parse(a[0], a[1]), tag_tuples)

Чтобы получить значение объекта по его идентификатору, тебе нужно знать неймспейс,

Я знаю, просто не знал как по-другому пример привести.

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

Я хотел красиво :(

Не судьба, в питоне нет для такого средств.

map(lambda a: xml_tag_parse(a[0], a[1]), tag_tuples)])

А не «красивее» будет list comprehension использовать?

[xml_tag_parse(a0, a1) for (a0, a1) in tag_tuples]

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

for in вроде быстрее чем map+lambda?

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

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

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

Virtuos86 ★★★★★ ()

Я пока только изучаю пайтон, но возникает вопрос: какие средства требуют динамеческого наследования (если я правильно понял задачу)?

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

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

Есть же еще реверсивный доступ к init

Типа в ребенке сделать:

[code] class Class2(object): def init(self, class1):
self.c1 = class1 [/code]

И все нужные атрибуты экспортировать как self.c1. =

В итоге общий интерфейс без self.class1 = self.class1.class2 костылей получается.

Но я все равно упираюсь в if elif else лапшу.

steemandlinux ★★★★★ ()

Я не очень понимаю, какую задачу ты пытаешься решить. Но почему для динамического создания класса ты не используешь официальный способ динамического создания класса? Через new_class = type("NewClassName", (BaseClass,), {"new_method": ...} который. Так ты можешь собрать нужный тебе класс функцией и в эту функцию передать твой базовый импортированный класс.

Aswed ★★★★★ ()
Последнее исправление: Aswed (всего исправлений: 1)

Да и в принципе ты можешь сделать что-то типа

def make_class(base_class):
    class MyClass(base_class):
        ...
    return MyClass

Это, конечно, такой себе код, но все же лучше, чем руками выставлять child атрибуты

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

Я кот для себя пишу. А у тебя опять нулевая аргументация, вместо того сказать как сделать правильно. Нах ты вообще отвечаешь?

Моя причёска – птица,
Твой довод не годиться.

Какой смысл вообще в классах, когда прототипы рулят?

anonymous ()