LINUX.ORG.RU

Можно ли в питоне конкатенировать имена переменных или методов?

 ,


0

3

Приветствую.

В PHP можно создавать динамические имена переменных в рантайме.

for ($i = 1; $i <= 5; $i++) {
test$i = 1;
}

В итоге мы получим test1, test2, test3, test4, test5 которые будут равны 1.

Возможны ли такие фокусы в python ?

for i in range(5):
  TESTi = 1

Или что еще лучше с именами методов

for i in range(5):
  self.NAMEi.method()

Если с методами, то можно хоть чучелом массивом

for i in range(5):
  self.NAME[i].method()

Юзкейс.

Есть цикл. В цикле перечисляются объекты с методами. В моем случае, скрывать не буду, это кнопки GTK с обработчиками clicked, ссылающимися на функцию. Функции можно передать произвольные данные. Но потом нужно поменять свойство объекта, а чудаки из gtk4 не удосужились снабдить виджет идентификатором по которому потом к этому виджету можно будет обратиться. То что gtk4 убог я в принципе осознавал, но вопрос касается только способностей питона именовать объекты на лету.

Спасибо.

★★★★★

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

Можно, разными способами.

exec, eval, get/setattr и прямая работа со словарями обьектов/пространствами имён.

В питоне можно даже вверх по стеку лазить и там шерудить, а ещё monkey патчи делать.

Это же питон…

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

Это говнокод в большинстве случаев. Что мешает вместо пачки переменных использовать обычный или ассоциативный массив?

self.names = {}

for i in range(5):
  self.names[i] = 1

И да, не надо путать переменные и свойства объекта.

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

Используй dict вместо list либо изначально создавай list нужного размера. Ну или используй методы списка, которые увеличивают список.

https://docs.python.org/3/tutorial/datastructures.html

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

Насколько я понял ты хочешь что-то типа такого?

class App:
    def __init__(self):
        self.names = []

    def add_button(self, button)
        self.names.append(button)


app = App()
for i in range(10)
    app.add_button(Gtk.Button())


app.names[7].method()

self.names можно поменять со списка на словарь с названиями, так будет удобнее и быстрее в некоторых случаях.

class App:
    def __init__(self):
        self.names = {}

    def add_button(self, name, button)
        self.names[name] = button


app = App()
app.add_button('settings', Gtk.Button())
app.names['settings'].method()
masa
()
Последнее исправление: masa (всего исправлений: 6)

можно использовать например для создание имён переменных синонимичных некоторым значениям из перечисления без необходимости каждый раз предварять при задании значений перенных этого перечисления

при этом сами значения таких переменных будут не просто номерами констант но останутся из перечисления вида NameEnum.Name

т.е можно пользоватся для задания значения имени var именем moduleOfDefEnum.Name

и тогда значением var стало moduleOfDef.NameEnum.Name

чисто для уменьшения когнитивной цены обозрения сырца где часто упоминается значения из перечисления

qulinxao3 ★★
()

Возможны ли такие фокусы в python ?

Да

Или что еще лучше с именами методов

Можно и так

Если с методами, то можно хоть чучелом массивом

for i in range(5):
  self.NAME[i].method()

Хоть чучелом, хоть тушкой:

class test0():
    def method(self):
            print(0)

class test1():
    def method(self):
        print(1)

class test2():
    def method(self):
        print(2)


class Example():
    NAMES = []
    
    def __init__(self):
        self.NAMES.append(test0())
        self.NAMES.append(test1())
        self.NAMES.append(test2())

    def check(self):
        for i in range(3):
            exec(f"self.NAMES[{i}].method()")
            
            
example = Example()
example.check()
Obezyan
()

Аплодирую комментаторам, которые смогли понять ОП и даже дать какой-то совет. Я так и не понял, что ТС надо. Учитывая, что правильная формулировка задачи как минимум помогает найти решение, его затруднения не удивительны.

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

Если бы я знал как правильно сформулировать задачу, я бы сюда не заходил =)

Есть цикл переменной длины.

Каждая итерация выводит кнопку, рисуемую вызовом класса.

Нажатие этой кнопки дергает произвольную функцию, которая делает некоторые действия.

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

for i in range(1, 11):
         self.button = Gtk.Button.new()
         self.button.set_label('test'+str(i))
         self.button.connect("clicked", self.onclick)
         self.set_child(self.button)


def onclick(self, button):
        self.button.set_label('Эту кнопку нажали') <<< ладно, эту проблему в принципе я решил
        self.ДРУГИЕ_КНОПКИ.set_label('А эти кнопки остались не нажаты');
windows10 ★★★★★
() автор топика
Ответ на: комментарий от Virtuos86

Тоже динамически генерировали имена методов объектов?

Я просто не думал что GTK будет настолько угребищным, что у его объектов не будет поля для произвольного идентификатора.

windows10 ★★★★★
() автор топика

Текст программы - это метаинформация по отношению к выполняющемуся коду. Поэтому довольно странно хотеть её изменения в рантайме. Модифицировать код во время выполнения раньше было немодно.

чудаки из gtk4 не удосужились снабдить виджет идентификатором по которому потом к этому виджету можно будет обратиться.

Я подозреваю, что виджет является объектом GObject. Значит в нём можно хранить пользовательские данные. В том числе и идентификаторы.

Shushundr ★★★★
()
Ответ на: комментарий от windows10
def select(from_, where):
    op, some_obj = where
    return filter(lambda compared_obj: op(some_obj, compared_obj), from_)

class Poock(object):
    def __init__(self):
        self.buttons = []
        for i in range(1, 11):
            btn = Gtk.Button.new()
            self.buttons.append(btn)
            btn.set_label("test" + str(i))
            btn.connect('clicked', self.onclick)
            self.set_child(btn)

    def onclick(self, btn):
        btn.set_label("Эту кнопку нажали")
        import operator
        btns = select(from_=self.buttons, where=(operator.is_not, btn))
        for button in btns: button.set_label("А эти кнопки остались не нажаты")
Virtuos86 ★★★★★
()
Последнее исправление: Virtuos86 (всего исправлений: 1)
Ответ на: комментарий от mrjaggers

Да что здесь не понимать ?

Есть 10 или 20 объектов со свойствами.

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

Вариантов тут всего два: либо давать каждому объекту предсказуемый идентификатор и дергать по нему, либо давать каждому объекту предсказуемое имя и дергать по нему.

И конечно же я рукожоп, потому что программировать на питоне начал четыре дня назад. Профессионалы пилят Gnome.

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

скорее ещё во времена паскаля при печати отладочной переменных не хватала автоподстановки имени переменной в выдаче при выводе её значений

на тот момент в копмилируемых языках(в том же си) это через макросы

в лиспы вроде через `

в современном(уже лет как 7 если не) C# через name(var) - в жабе походу похожее псевдофункция которая возвращает именно имя переменной а не её значение

в современном питонии это достигается через вставку выражения возвращающее строку f’{var=}‘.split(’=’,1)[0]

это выражение при рефакторинге(переименнования переменной) - будет синхронно обновленно в отличии от явного строкового указания - классический буккипинг поддержания когерентости кода с не кодом (коменты строки и прочая)

ваще интерпретаторы тем хороши что можно на ходу генирировать файлы которые содержат более линейный код

т/е вынос проверки условий из кода исполнения на этап кода синтеза

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

возможно достаточно создать

«таблицу решений» либо словарём либо списком либо ещ> как

и в зависимости от условий менять в сём диспетчере каким обработчиком какое событие(состояние входа) отрабатывать

в общеизвестном GOTO Considered harmfull Дейкстры ровно об этом расхождение между статическим текстом программы и динамическим состоянием исполняемого процесса

поэтому проще состояние задавать обозоримой «таблицей» в которой менять значения и действовать сообразуясь с ней - чем динамически строить граф связанных сущсностей

в первом случае это более обозримо обычно

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

Радует, но я в принципе проверял на игрушечном примере (минутка рефлексии: выяснил, что забыл, какой метод добавляет объекты в хвост list; ужас, как подкрадывается старость 😐; хотя всё же тут же вспомнил без подглядывания).

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

Если есть много объектов, с которыми нужно что-то (с)делать одним разом, то само напрашивается объединение их в коллекцию данных; какую именно использовать зависит от вкуса и от удобства ее использования в конкретных задачах. Если же часто обращаешься к какому-то отдельному объекту, то наоборот имеет смысл выделить его в отдельную программную сущность.

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

Эта история в общем-то не про Питон, а про программирование.

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

как разтаки

модификация кода и стала тем что создало индустрию

прст оказалось что это настолько мощьное средством что проще низводить приёмы модификации в частные случаи динамического разименования

например исходно небыло индексных регистров а была сохранения в память в месте аргумента адреса в команде результата некоторого выражения (обычно как раз изменившегося на некоторую констранту нормированно это всегда очевидно единица) - оказалось изобретение индексации через какой либо источник( иную ячейку памяти, регистр и прочая) - т.е декаплинг динамического состояния процесса и статичного универсального текста программы явно не было изначально

ваще в широком смысле программа модифицирует саму себя и сейчас - но только в области явных данных - в этом случае изчезает необходимость знать как представленн сам код в исполняющей фазе

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

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

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

Не нет, а да. Ты пытаешься заниматься метапрограммированием.

Из-за того что ты не знаешь лиспа, и не понимаешь, что ты на самом деле пытаешься сделать, тебе это сложно понять.

В лиспе, вон, например, естественно, переменные можно «конкатенировать» и вообще делать с ними что угодно, и там символ(symbol), по сути идентификатор это один из базовых объектов языка.

Но т.к. у тебя не лисп, это все делается через жопу, если вообще делается. Ты пытаешься хакнуть возможности языка на котором пишешь. Если бы ты писал на лиспе - этой проблемы бы не было в принципе, т.к. эти возможности там встроены в саму систему.

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

Утро

Автор топика создает тему с вопросом:

Возможны ли такие фокусы в python ?

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

День

Никто. Абсолютно никто.

Вечер

@lovesan:

Вот это видимо пример того, когда человеку нужен лисп и метапрограммирование.

Из-за того что ты не знаешь лиспа, и не понимаешь, что ты на самом деле пытаешься сделать, тебе это сложно понять.

Это уже какой-то лиспогибиционизм бегать по темам и пытаться показать всем метапрограммирование из-под плаща. Как сектант («Здравствуйте, хотите ли вы поговорить о Лиспе?»), ей-богу.

Пора уже создавать тему «Lisp и его губительное влияние на неокрепшие мозги джунов».

Obezyan
()
Ответ на: комментарий от upcFrost

С этим я не спорю, больше похоже на то что автор делает pet-проект и попутно открывается для себя python и его границы.

Это как PHPшник узнав что есть «переменные переменные» обязательно впихнет куда-нибудь что-то типа:

$World = "a";
$Hello = "World";
$a     = "Hello";

$$$$$$$a . ' ' . $$$$$$$$a // Hello World

Обычный процесс «я познаю мир». А руки надо отрывать за попытки реализовывать на Lisp то что не просят, т.к. Python указан в условиях задачи.

Obezyan
()
Ответ на: комментарий от upcFrost

С точки зрения алгоритмического программирования, индекс объекта (а конкатенация в моем случае является разновидностью индекса) - единственно правильное обращение к определенному объекту впоследствии. Правильнее - только поддержка индекса самим объектом.

поэтому именно нечто вроде

объект[int индекс].действие1() {}

function blablabla(int index) { объект[index].действие2() }

является ожидаемой возможностью от языка.

А теперь будь добр, объясни, почему за изящное добавление объекту или переменной второй части\индекса - в проде руки отрывать нужно, а за дроч с созданием параллельного массива, в который вносятся все объекты цикла, с последующим дерганием этого массива специально добавленной функцией, ищущей переменную\объект переданной функции в заполненном массиве, потому что сраный язык не позволяет иного - нет.

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

Это уже какой-то лиспогибиционизм бегать по темам и пытаться показать всем метапрограммирование из-под плаща. Как сектант («Здравствуйте, хотите ли вы поговорить о Лиспе?»), ей-богу.

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

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

Так не будет.

Если тебя не устраивает работа сантехником - ты вполне волен уволиться.

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

Знаешь как ты должен был поступить если хотел чтобы писали правильно и на лиспе ?

Ты должен был сказать, оу бро, ты вот тут трахаешься, а на лиспе это выглядело бы изящно

for (i = 1; i <= 5; let i=i+1) begin
test[i].object();
end

И я бы с радостью пересел на лисп.

Но исходя из твоего ответа, в котором нет ничего кроме зависти - я рад что выбрал питон. Хотя бы сообщество адекватное.

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

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

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

Для человека с молотком все выглядит как гвоздь (с) Марк Твен

Перефразируя, для человека нормально знающего только Лисп все вокруг выглядит как список. Это очень узкая картина мира, такая же была у ярых Perlовиков, для которых все вокруг было текст и которые в итоге - вымерли. Тоже самое с Lisp. Языки либо живут и адаптируются к новым требованиям индустрии либо выдавливаются из нее.

Главная проблема Lisp в том что он тормоз. Попробуйте осознать это, Lisp это тормоз. Не по скорости работы, нет, по скорости разработки. Во многих сферах уже необходимо сделать БЫСТРО (eCommerce, продажи не ждут - PHP, JS) или проверить БЫСТРО несколько вариантов взяв готовые пакеты по вычислениям (ML и стык околонауки с коммерцией - Python), сделать БЫСТРО минимально жизнеспособный продукт (MVP) внедрить его и дорабатывать исходя из условий меняющейся среды (от web серверов до алгоритмической торговли - C++, C#, Java, .Net) и тд и тп.

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

Даже язык 1С лучше Lisp в тех задачах для которых он предназначен - автоматизация бух учета, учета вообще, управления и отчетности в ЛЮБЫХ сферах бизнеса. Просто потому что он предоставляет готовый набор объектов более высокого уровня абстракции чем список, с готовой бизнес-логикой под требуемые задачи. И в данном случае абсолютно не важно что 1С написан на С++, а могли упороться и написать на Lisp. Потому что при разработке самой платформы 1С точно также учитывались и сроки и возможности языка и поддержка когда и его изменения (переход с v7 на v8 на 1С сравним с переходом с v2 на v3 в Python).

Т.е. Lisp в подавляющем большинстве случаев проигрывает по совокупности факторов остальным языкам, причем в разных сферах он проигрывает разным языкам. А конструировать объекты более высокой абстракции на Lisp и создавать из них экосистему пытаясь догнать современные языки это заведомо проигрышная позиция для бизнеса т.к. время-деньги. Это доходит до абсурда когда сделать коряво на JS выкатить в прод сегодня в разы ВЫГОДНЕЕ для бизнеса чем выкатить завтра, но нормальное. Даже с учетом того что завтра придется переписывать все с нуля. Такова реальность современной разработки за денюжку и ради денежки.

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

Теперь о недостатках Lisp (реализаций). Возьмем для примера Ваш pet проект bike который реализует интероп с .Net через CLR. Он не работает ни в SBCL ни в CCL. Просто не работает под Linux. И никогда не заработает полноценно. Вы это знаете, я это знаю, но Вы почему-то забываете упомянуть об этом в своих сообщениях когда указываете его.

Можно тупо подавить выработку исключений чисел с плавающей точкой на стороне Lisp (SBCL) и оно заведется, но как тогда можно быть уверенным что 2.0 + 2.0 = 4.0 ? Или что не произошло деления теплого на мягкое или еще что? Исключения то отключены.

Можно сказать что это .Net 6 и 7 виноваты, но другие-то языки отлично работают с .Net CLR. Т.е. Lisp не справился с поставленной задачей.

Любой C++/C# программист может решить эту задачу, а Вы на Lisp - нет. Можно прятать в голову в песок и обзывать всех, а можно принимать объективную реальность на сухую. Выбор за Вами.

Obezyan
()