Форум программистов, компьютерный форум, киберфорум
Python для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.54/13: Рейтинг темы: голосов - 13, средняя оценка - 4.54
0 / 0 / 0
Регистрация: 16.02.2012
Сообщений: 51

Как в отладчике просмотреть содержимое списка?

06.12.2013, 22:50. Показов 2951. Ответов 23
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Python 2.7.2. Имеется скрипт, считывающий данные из внешних файлов и определенным образом их обрабатывающий, отлаженый и часто использованный, при этом при обработке вполне валидных для него по структуре файлов, при работе с некоторыми из них выдается такая ошибка.
Python
1
UnboundLocalError: local variable referenced before assignment
Это при том что выдается она, как это выглядит, произвольно — для других файлов аналогичной структуры все работает, тестировал функции по отдельности — все работает корректно. Если попробовать огласить «проблемную» переменную принудительно глобальной, находит следующую с такой же ошибкой.
Существуют ли какие-то особенности, которые могли бы привести к появлению сообщения о такой ошибке, когда дело на самом деле в другом? Посоветуйте пожалуйста, как можно еще подиагностировать работу скрипта в данной ситуации. Есть ли способ промониторить все значения переменных по ходу выполнения скрипта (создать какой-то лог)?

Добавлено через 10 минут
upd
Если обойти проблемы с локальными переменными начинает также неадекватно (что подтверждается тестированием функций по отдельности и корректной работой с другим файлами) выдавать list index out of range

Добавлено через 7 минут
Python
1
2
3
4
5
6
7
8
9
10
11
12
[['GROUP', 'FLUX', 'RAD-DIFF', 'AX-DIFF', 'TOT-DIFF', 'REMOVAL', 'ABSORPTION', 'NU-FISS', 'FISS', 'TRANSP', 'TOTAL'], ['1', '3.977888E+01', '1.425138E+00', '1.425138E+00', '1.425138E+00', '1.331315E-02', '1.207110E-02', '3.878784E-03', '1.419409E-03', '2.338955E-01', '2.932495E-01'], ['2', '5.682828E+00', '3.718616E-01', '3.718616E-01', '3.718616E-01', '1.690244E-03', '9.147231E-02', '9.343243E-02', '3.425082E-02', '8.963909E-01', '9.934033E-01'], ['0SCATTERING', 'MATRIX', '(SELFSCATTERING', 'UNCORRECTED)', '+', 'SELFSCATTERING', 'CORRECTED', 'BY', 'TRANSP', 'TOTAL'], ['1', '2'], ['1', '2.678652E-01', '1.331315E-02', '2.085112E-01']]
[]
Traceback (most recent call last):
  File "…", line 227, in <module>
    fun1(root, fatype, cr_stance, wt_cases, wt_xlist, wt_outfn)
  File "…", line 150, in b_process
    reslist.append(preprocess(root, burnup, fatype, cr_stance, cases, x_list))
  File "…", line 137, in fun2
    reslist1.append(derline(seek_get(fn, spatt, count), get_Ef(fn, efpatt)))
  File "…", line 55, in derline
    ml1, ml2, ml3 = matrix[1], matrix[2], matrix[5]
IndexError: list index out of range
вот, собственно, лог консоли, явно видно что укладываются индексы в рейндж и существуют элементы списка с такими индексами. Как понимать поведение скрипта в такой ситуации?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
06.12.2013, 22:50
Ответы с готовыми решениями:

Просмотреть порядок вызова функций в отладчике vs 2013
Собственно, вопрос - как? У меня есть проект на си, с огромным количеством файлов и функций. Нужно посмотреть что в каком порядке...

В отладчике невозможно просмотреть значения свойств некоторых объектов
Доброго времени суток. Столкнулся с проблемой невозможности просмотра значений свойств объектов в отладке. При добавлении оного в...

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

23
561 / 484 / 168
Регистрация: 14.02.2012
Сообщений: 1,561
06.12.2013, 23:05
Цитата Сообщение от you_fail_me Посмотреть сообщение
явно видно что укладываются индексы в рейндж и существуют элементы списка с такими индексами.
Не сказал бы. Можете попробовать остановить скрипт на этом мосте при помощи отладчика
Python
1
import pdb; pdb.set_trace()
Дальше уже смотреть состояние переменных и анализировать поведение скрипта. При разработке надо было учитывать возможные ошибки, перехватывать их и тогда таких проблем сейчас не было бы...
0
0 / 0 / 0
Регистрация: 16.02.2012
Сообщений: 51
06.12.2013, 23:34  [ТС]
Цитата Сообщение от ВАСИЛЕВС Посмотреть сообщение
Не сказал бы.
Не могли бы обьяснить, почему? Видно же, сколько там элементов
0
4866 / 3288 / 468
Регистрация: 10.12.2008
Сообщений: 10,570
06.12.2013, 23:37
Цитата Сообщение от you_fail_me Посмотреть сообщение
Посоветуйте пожалуйста, как можно еще подиагностировать работу скрипта в данной ситуации.
делай без дебаггера

Цитата Сообщение от you_fail_me Посмотреть сообщение
что подтверждается тестированием функций по отдельности и корректной работой с другим файлами
тестируешь руками чтоли ?

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

Цитата Сообщение от you_fail_me Посмотреть сообщение
Если попробовать огласить «проблемную» переменную принудительно глобальной
не, сначала делай вывод на экран, чтобы отследить, докуда программа работает, а на какой строке падает
когда место определил, начинай выводит на экран все переменные, которые там
причём все, даже не относящиеся к проблеме
если есть цикл, то все шаги цикла

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

если же у тебя есть юнит-тесты, то при разработке они не пропустят баг изначально
0
0 / 0 / 0
Регистрация: 16.02.2012
Сообщений: 51
06.12.2013, 23:45  [ТС]
Цитата Сообщение от accept Посмотреть сообщение
тестируешь руками чтоли ?
да, он не настолько большой и это не такая серьезная работа, просто автоматизация операций для себя.

Цитата Сообщение от accept Посмотреть сообщение
не, сначала делай вывод на экран, чтобы отследить, докуда программа работает, а на какой строке падает
когда место определил, начинай выводит на экран все переменные, которые там
причём все, даже не относящиеся к проблеме
если есть цикл, то все шаги цикла
Ну по сути так и сделал — дошел до ошибки (list index out of range), добавил перед выполнением операций с тем списком вывод его, что прилагается в первом посте. И теперь мне непонятно, каким же оно там образом out of range если видно что список состоит из элементов с нулевого по пятый
0
4866 / 3288 / 468
Регистрация: 10.12.2008
Сообщений: 10,570
07.12.2013, 06:28
Цитата Сообщение от you_fail_me Посмотреть сообщение
да, он не настолько большой и это не такая серьезная работа, просто автоматизация операций для себя.
дело не в размерах
вот ты говоришь, что протестировал функции, чтобы убедиться что программа работает; следовательно, когда ты исправишь этот баг, что ты будешь делать ? правильно, снова тестировать эти функции; а как ты нашёл этот баг ? правильно, случайно нашёл; а если случайно найдётся ещё баг, что ты будешь делать ? правильно, всё то же самое с начала и до конца

итого, сколько времени ты потратил ? три часа, а мог бы три секунды

Цитата Сообщение от you_fail_me Посмотреть сообщение
добавил перед выполнением операций с тем списком вывод его
но там выводится два списка
0
0 / 0 / 0
Регистрация: 16.02.2012
Сообщений: 51
07.12.2013, 15:52  [ТС]
Цитата Сообщение от accept Посмотреть сообщение
но там выводится два списка
У меня в данный момент складывается впечатление, что на первом проходе цикла создание того списка срабатывает нормально, а дальше он не заполняется и остается пустым, каким он создавался. Как посоветуете проверить эту мысль, какие бывают типичные причины такой дисфункции?
0
4866 / 3288 / 468
Регистрация: 10.12.2008
Сообщений: 10,570
07.12.2013, 16:01
приведи функцию, которую отлаживаешь
0
0 / 0 / 0
Регистрация: 16.02.2012
Сообщений: 51
07.12.2013, 17:30  [ТС]
Python
1
2
3
4
5
6
7
8
9
10
11
12
def seek_get(fname, spatt, count):
    matrix, found, remaining = [], False, count
    with open(fname, 'r') as inp:
        for line in inp:
            if found:
                if remaining == 0:
                    break
                matrix.append(line.split())
                remaining -= 1
            if line.startswith(spatt):
                found = True            
    return matrix
далее другая функция берет список, возвращаемый этой (он в первом посте кстати) и берет из него некоторые элементы. При этом возникает list index out of range.

Добавлено через 40 минут
Повторюсь что отдельно она все возвращает нормально.
Python
1
2
3
4
5
6
7
def derline(matrix, ef):
    res, mlf1, mlf2 = [], [], []
    ml1, ml2, ml3 = matrix[1], matrix[2], matrix[5]
    for i in range(len(ml1)):
        mlf1.append(float(ml1[i]))
        mlf2.append(float(ml2[i]))
    sig_s = float(ml3[2])
эта функция беретнекоторые данные из списка, возвращаемого предыдущей,а эта:
Python
1
2
3
4
5
6
7
8
9
def preprocess(root, b, type, stance, cases, x_list):
    spatt = 'pattern1'
    efpatt = 'pattern2'
    count = 6
    reslist1 = []
    for cn in cases:
        cfn = 'n1-'+type+'-'+b+'-'+cn+'.out'
        for fn in glob.iglob(os.path.join(os.path.abspath(root), b, stance, cfn)):
            reslist1.append(derline(seek_get(fn, spatt, count), get_Ef(fn, efpatt)))
является следующим этапом обработки и при выполнении этой строки вылетает ошибка

Добавлено через 11 минут
в 7-й строке вместо bp естественно должно быть и есть b это просто опечатался когда сюда вставлял, не обращайте внимания
0
4866 / 3288 / 468
Регистрация: 10.12.2008
Сообщений: 10,570
07.12.2013, 22:10
Цитата Сообщение от you_fail_me Посмотреть сообщение
Python
1
2
3
4
5
6
7
8
9
10
11
12
def seek_get(fname, spatt, count):
    matrix, found, remaining = [], False, count
    with open(fname, 'r') as inp:
        for line in inp:
            if found:
                if remaining == 0:
                    break
                matrix.append(line.split())
                remaining -= 1
            if line.startswith(spatt):
                found = True            
    return matrix
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
def seek_get(fname, spatt, count):
    matrix, found, remaining = [], False, count
    with open(fname, 'r') as inp:
        for line in inp:
            if found:
                if remaining == 0:
                    break
                matrix.append(line.split())
                remaining -= 1
            if line.startswith(spatt):
                found = True
    print 'matrix', matrix
    raw_input()
    return matrix
Цитата Сообщение от you_fail_me Посмотреть сообщение
Python
1
2
3
4
5
6
7
8
9
def preprocess(root, b, type, stance, cases, x_list):
    spatt = 'pattern1'
    efpatt = 'pattern2'
    count = 6
    reslist1 = []
    for cn in cases:
        cfn = 'n1-'+type+'-'+b+'-'+cn+'.out'
        for fn in glob.iglob(os.path.join(os.path.abspath(root), b, stance, cfn)):
            reslist1.append(derline(seek_get(fn, spatt, count), get_Ef(fn, efpatt)))
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def preprocess(root, b, type, stance, cases, x_list):
    spatt = 'pattern1'
    efpatt = 'pattern2'
    count = 6
    reslist1 = []
    for cn in cases:
        cfn = 'n1-'+type+'-'+b+'-'+cn+'.out'
        for fn in glob.iglob(os.path.join(os.path.abspath(root), b, stance, cfn)):
            s = seek_get(fn, spatt, count)
            print 'seek_get:', s
            g = get_Ef(fn, efpatt)
            print 'get_Ef:', g
            d = derline(seek_get(fn, spatt, count), get_Ef(fn, efpatt))
            print 'derline', d
            raw_input()
            reslist1.append(derline(seek_get(fn, spatt, count), get_Ef(fn, efpatt)))
0
0 / 0 / 0
Регистрация: 16.02.2012
Сообщений: 51
08.12.2013, 15:39  [ТС]
Не пойму, зачем ты мне подописывал везде вывод переменных. Я уже давно пробовал и так и смотрел в отладчике. К чему это? Поведение переменных описано в вышеизложенных постах

Добавлено через 1 минуту
И обращаясь к тому кто переименовал тему скажу что дело здесь не в том как в отладчике просмотреть список...
0
4866 / 3288 / 468
Регистрация: 10.12.2008
Сообщений: 10,570
08.12.2013, 15:51
Цитата Сообщение от you_fail_me Посмотреть сообщение
Не пойму, зачем ты мне подописывал везде вывод переменных.
чтобы ты всё это запустил
чтобы ты не своё что-то там запускал, а вот это вот

Цитата Сообщение от you_fail_me Посмотреть сообщение
Я уже давно пробовал и так и смотрел в отладчике.
ты бы уже нашёл баг, если бы смотрел правильно

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

Цитата Сообщение от you_fail_me Посмотреть сообщение
И обращаясь к тому кто переименовал тему скажу что дело здесь не в том как в отладчике просмотреть список...
ты не умеешь пользоваться отладчиком, потому что его достаточно для нахождения бага
ты спрашиваешь "а как ещё можно найти баг, если не в отладчике?"

я предлагаю не пользоваться отладчиком, пока не умеешь им пользоваться, и просмотреть все переменные вручную, как это делали до создания отладчиков
потому что этот способ одинаков для всех языков, а отладчики везде разные
0
0 / 0 / 0
Регистрация: 16.02.2012
Сообщений: 51
08.12.2013, 19:34  [ТС]
Цитата Сообщение от accept Посмотреть сообщение
в вышеизложенных постах у тебя пустой список, про который ты говоришь, что в нём есть все элементы
Посмотри еще раз на первую строку лога консоли в стартовом посте. Явно не пустой список, не правда ли?

Добавлено через 1 час 16 минут
Выявил проблему — при выполнении цикла прохода по всем необходимым файлам, с каждого из которых функция seek_get считывает необходимую информацию и возвращает в виде списка, доходя до определенного файла список не заполняется, возвращается пустым. Проверил структуру файла, на котором список перестает заполняться — структура в порядке, файл ничем не отличается от тех, с которыми все срабатывает. В чем может крыться причина такого поведения? Что посоветуете проверить?
0
4866 / 3288 / 468
Регистрация: 10.12.2008
Сообщений: 10,570
08.12.2013, 21:22
Цитата Сообщение от you_fail_me Посмотреть сообщение
Посмотри еще раз на первую строку лога консоли в стартовом посте. Явно не пустой список, не правда ли?
а с чего ты взял, что сообщение относится к нему ?
там два списка вывелось, первый заполнен (и он отработал), а второй пустой

Цитата Сообщение от you_fail_me Посмотреть сообщение
Выявил проблему
возьми первый код из этих
и убедись, что матрица не заполняется
0
0 / 0 / 0
Регистрация: 16.02.2012
Сообщений: 51
08.12.2013, 21:34  [ТС]
Цитата Сообщение от accept Посмотреть сообщение
возьми первый код из этих
и убедись, что матрица не заполняется
Убедился — не заполняется. Идеи?
0
4866 / 3288 / 468
Регистрация: 10.12.2008
Сообщений: 10,570
08.12.2013, 21:43
Цитата Сообщение от you_fail_me Посмотреть сообщение
Убедился — не заполняется.
приведи пример структуры
0
0 / 0 / 0
Регистрация: 16.02.2012
Сообщений: 51
08.12.2013, 21:47  [ТС]
Цитата Сообщение от accept Посмотреть сообщение
приведи пример структуры
Кликните здесь для просмотра всего текста
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 
01 of 2  1.205490E+02  1.205490E+02
 2 of 2  4.777231E+00  4.777231E+00
 
 
 HOMOGENEIZED CROSS SECTIONS FOR CELL  1TO 79
 GROUP   FLUX       RAD-DIFF     AX-DIFF     TOT-DIFF   REMOVAL    ABSORPTION    NU-FISS       FISS   TRANSP     TOTAL
  1 6.657478E+01 1.827072E+00 1.827072E+00 1.827072E+00 5.034504E-03 1.009324E-02 5.967117E-03 2.344354E-03 1.824413E-01 2.205368E-01
  2 3.109760E+00 6.338671E-01 6.338671E-01 6.338671E-01 2.267711E-03 1.054826E-01 1.426061E-01 5.764487E-02 5.258726E-01 5.726650E-01
0SCATTERING MATRIX (SELFSCATTERING UNCORRECTED)   +   SELFSCATTERING CORRECTED BY TRANSP   TOTAL
           1           2
  1 2.054090E-01 5.034504E-03 1.673135E-01
  2 2.267711E-03 4.649146E-01 4.181222E-01
BURNUP LIBRARY ON UNIT 14 NOT CREATED
 
 
 HOMOGENEIZED CROSS SECTIONS FOR REGIONS  1 TO 69
 GROUP   FLUX       RAD-DIFF     AX-DIFF     TOT-DIFF   REMOVAL    ABSORPTION    NU-FISS       FISS   TRANSP     TOTAL
  1 5.048927E+01 1.841476E+00 1.841476E+00 1.841476E+00 4.814341E-03 1.133117E-02 6.236413E-03 2.449468E-03 1.810143E-01 2.238865E-01
  2 2.147033E+00 6.313626E-01 6.313626E-01 6.313626E-01 2.391211E-03 1.211817E-01 1.534558E-01 6.202157E-02 5.279586E-01 5.895360E-01
0SCATTERING MATRIX (SELFSCATTERING UNCORRECTED)   +   SELFSCATTERING CORRECTED BY TRANSP   TOTAL
           1           2
  1 2.077410E-01 4.814341E-03 1.648687E-01
  2 2.391211E-03 4.659631E-01 4.043857E-01

seek_get ищет по шаблону
Code
1
« HOMOGENEIZED CROSS SECTIONS FOR CELL»
и считывает следующий за этим заголовком блок данных.
0
4866 / 3288 / 468
Регистрация: 10.12.2008
Сообщений: 10,570
08.12.2013, 21:49
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def seek_get(fname, spatt, count):
    matrix, found, remaining = [], False, count
    with open(fname, 'r') as inp:
        for line in inp:
            if found:
                if remaining == 0:
                    break
                matrix.append(line.split())
                remaining -= 1
            print '<0>'.format(line)
            raw_input()
            if line.startswith(spatt):
                print 'found: <{0}><{1}>'.format(line, spatt)
                raw_input()
                found = True
    return matrix
0
0 / 0 / 0
Регистрация: 16.02.2012
Сообщений: 51
08.12.2013, 22:01  [ТС]
Цитата Сообщение от accept Посмотреть сообщение
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def seek_get(fname, spatt, count):
    matrix, found, remaining = [], False, count
    with open(fname, 'r') as inp:
        for line in inp:
            if found:
                if remaining == 0:
                    break
                matrix.append(line.split())
                remaining -= 1
            print '<0>'.format(line)
            raw_input()
            if line.startswith(spatt):
                print 'found: <{0}><{1}>'.format(line, spatt)
                raw_input()
                found = True
    return matrix
Это ничего не дает. В чем смысл этих модификаций? В консоль выводится только
Code
1
2
found: < HOMOGENEIZED CROSS SECTIONS FOR CELL  1TO 79
>< HOMOGENEIZED CROSS SECTIONS FOR CELL>
Добавлено через 6 минут
Я так понимаю, ты хотел дописать чтобы выводилось сообщение о том, что шаблон найден, и сколько строк считано после него. Ну выводятся, но новой информации из этого никакой нет — как я уже и писал, считав некоторое количество раз из файлов успешно, перестает считывать.
0
4866 / 3288 / 468
Регистрация: 10.12.2008
Сообщений: 10,570
08.12.2013, 22:10
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def seek_get(fname, spatt, count):
    matrix, found, remaining = [], False, count
    with open(fname, 'r') as inp:
        for line in inp:
            if found:
                print 'remaining:', remaining
                if remaining == 0:
                    break
                print 'append <{0}>'.format(line)
                raw_input()
                matrix.append(line.split())
                remaining -= 1
            if line.startswith(spatt):
                found = True
    return matrix
Добавлено через 29 секунд
Цитата Сообщение от you_fail_me Посмотреть сообщение
В чем смысл этих модификаций?
сначала нужно локализовать баг
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
08.12.2013, 22:10
Помогаю со студенческими работами здесь

Как просмотреть содержимое БД приложения
Здравствуйте! В приложении есть БД, которая прописывается в самом коде (создание и т.п). Можно ли как нибудь на нее посмотреть отдельным...

Как просмотреть содержимое директории?
Здравствуйте, подскажите пожалуйста, как в Lazarus просмотреть все файлы, имеющиеся в директории включая подпапки, чтобы вывести их,...

Как просмотреть содержимое регистров
Начал изучать NASM под линукс подскажите пожалуйстака как просматривать содержимое регистров и выполнять программу пошагово

Как в VBA просмотреть содержимое папок?
Как в VBA просмотреть содержимое папок, типа dirlistbox есть что-нибудь??

Как просмотреть содержимое параметров функции main?
Здравствуйте. Честно, повсюду на этом форуме и не только искал информацию о параметрах функции main в C++/CLI. Почти ничего не нашел, к...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Первый деплой
lagorue 16.01.2026
Не спеша развернул своё 1ое приложение в kubernetes. А дальше мне интересно создать 1фронтэнд приложения и 2 бэкэнд приложения развернуть 2 деплоя в кубере получится 2 сервиса и что-бы они. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь постоянного тока с R, L, C, k(ключ), U, E, J. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа, решает её и находит токи на L и напряжения на C в установ. режимах до и. . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Изучаю kubernetes
lagorue 13.01.2026
А пригодятся-ли мне знания kubernetes в России?
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru