Страницы

Поиск по вопросам

понедельник, 3 декабря 2018 г.

Неявный импорт в python

Не могу разобраться в системе импортов. Почему когда я делаю:
import os.path
то мне доступен os.walk, который находится в os, хотя я явно не импортирую os? Почему-то со своими package такой финт не прокатывает. За счет чего это происходит?
upd
Я понимаю, что импорт вносит импортируемое в пространство имен модуля. поэтому определив модуль 'myutils.py' c
import requests
в другом модуле получается следущая картина
import myutils resp=myutils.requests.get('http://ya.ru') # работает resp2=requests.get('http://ya.ru') # NameError: name 'requests' is not defined
Есть какая то особенность в механизме import os в os.path? Я понимаю, что os.path есть часть os, а не 2 абсолютно отдельных package, но хочу точно понять механизм.


Ответ

Импорт в Питоне объединяет две операции
найти (загрузить и проинициализировать) модуль ввести новые имена в текущем окружении (как операция присваивания =)
На этапе поиска (пункт №1)—из спецификации import-конструкции
This name will be used in various phases of the import search, and it may be the dotted path to a submodule, e.g. foo.bar.baz. In this case, Python first tries to import foo, then foo.bar, and finally foo.bar.baz. If any of the intermediate imports fail, an ImportError is raised.
то есть import a.b.c импортирует модули a, a.b, a.b.c и более вложенный модуль не может быть импортирован успешно, если импорт неудачен для любого модуля выше.
На этапе присвоения имён (пункт №2)
If the module being imported is not a top level module, then the name of the top level package that contains the module is bound in the local namespace as a reference to the top level package. The imported module must be accessed using its full qualified name rather than directly
import a.b.c в Питоне делает доступным a имя в текущем пространстве имён (например, в глобальном пространстве имён модуля, который импортирует a.b.c) и присваивает атрибут: a.b и атрибут атрибута: a.b.c соответствующим загруженным модулям (аналог: a = sys.modules['a']; a.b = sys.modules['a.b']; ..).
Хотя вопрос с подводхом, потому что os не является Питон-пакетом (__path__ атрибут не установлен) и os.path является обычным атрибутом (таким же как os.walk) с той разницей, что os.path является модулем и os.py содержит хак: sys.modules['os.path'] = path (что разрешает import os.path конструкцию). import os сам по себе уже делает os.path доступным без import os.path

Перефразируя вопрос, используя более регулярный пример:
Почему когда я делаю: import os.pathimport html.parser то мне доступен os.walk html.escape, который находится в oshtml, хотя я явно не импортирую os html?
import html.parser импортирует как html так и (естественно) html.parser модули и так как html/__init__.py (выполняемый на этапе импорта html) определяет escape функцию, то html.escape() также доступна как если бы мы просто выполнили import html
Почему-то со своими package такой финт не прокатывает. За счет чего это происходит?
Если module.name после import module не работает, то это значит что ваш module/__init__.py не определяет name.
В сторону: работоспособность module.name не зависит от __all__. __all__ документирует какие имена являются публичными (формально имена доступные по from module import *), чтобы не добавлять к каждому имени, которое не является частью интерфейса, _ в начале (имена типа _name по умолчанию исключены из from module import *). Но это не запрещает явное обращение такое как module._name (этого следует избегать, но если очень хочется, то можно). В сторону: не используйте from module import * вне REPL или вне __init__.py файла (пример оправданного использования: asyncio/__init__.py—asyncio предоставляет "плоский" публичный интерфейс (имена доступны прямо как asyncio.name), не смотря на то что реализация распределена по многочисленным вложенным модулям).

Фиксированная нижняя граница при увеличении высоты блока

На странице в самом низу есть блок. При клике на него его высота увеличивается. Но прокрутка страницы остается на месте, а блок увеличивается вниз.


Примерно так: https://jsfiddle.net/b6wd5s4m/
Как сделать так, чтобы при раскрытии блока его нижняя граница была зафиксирована и оставалась у нижней границы экрана, а страница как бы прокручивалась вниз?


Ответ

Тогда так, доки - https://learn.javascript.ru/coordinates - https://learn.javascript.ru/metrics-window
var open_block = document.getElementById('open_block'); open_block.addEventListener('click', function() { open_block.classList.toggle('open_block'); var bot = open_block.getBoundingClientRect().bottom; window.scrollTo(0, bot); }); .block { margin-top: 300px; width: 100%; height: 100px; background-color: #04a513; transparent: 1s; } .open_block { height: 300px; transparent: 1s; }


Вопрос о создании Интерфейса для программ

Где-то краем уха услышал, что можно создать интерфейс для программы С++ на HTML (css+js). Это правда? Если, да, то можете кинуть пару обучающих книг(видео)?


Ответ

Хочу вначале уточнить, что задача распадается на две части. Первая - это непосредственно Ваша программа на C++, которая будет что-то делать и взаимодействовать с пользователем через HTML интерфейс. Для решения этой части есть билиотеки, например WT (см. ниже).
Вторая часть - это это рендеринг кода HTML в красивые кнопочки, закладочки, картинки, "галочки" и другие элементы интерфейса. Это очень серьезная и объемная задача. Ей занимается целая индустрия создания браузеров. В Вашем случае подойдет либо стандартный браузер в системе пользователя, который будет направлен на локальный адрес. Либо модуль готового движка типа Gecko, или Web-kit. В любом случае выбор за вами.
Библиотека WT. Ключевые возможности:
Поддержка основных браузеров (Firefox/Gecko, Internet Explorer, Safari, Chrome, Konqueror и Opera), а также браузеров простого HTML (Links, Lynx). Разработка и развёртывание на Unix/GNU Linux или Microsoft Windows (Visual Studio). Идентичное поведение как при поддержке JavaScript или Ajax, так и без таковой, насколько это возможно, посредством постепенной деградации (graceful degradation) или прогрессивного расширения (progressive enhancement). Интегрированная поддержка Юникода и локализации. Эффективный рендеринг и низкая латентность. Поддержка перемещения с помощью истории браузера (кнопки "назад"/"вперёд" и закладки), лаконичные URL при доступности истории HTML5, оптимизация для поисковиков и однообразное поведение сессий простого HTML или Ajax. Настраиваемые опции отслеживания сессий, либо посредством перезаписи URL, либо с помощью использования кук. и еще много всего "вкусного"...
Подробности на сайте (на русском)

PHP&HTML: подстановка введённых значений в поля при неудачной отправке формы

Мне нужно, чтобы при неудачной попытке отправить форму введённые значения сохранились в полях. Я видел, что это делают так:


"/>

Т. е. мы подставляем в поля значения массива $_POST, если таковые имеются.
Но у меня почему-то не работает, т. е. не происходит подстановки в поля. Скрипт request.php при запрете отправки всвязи с ошибками ввода возвращает на страницу с формой (его работа уже отлажена).
В чем может быть причина?


Ответ

Т.к. у вас запрос (action="request.php") идёт на другой файл, вижу несколько способов:
Яваскрипт (как я понял вам не подходит); Производить обработку в том же файле, откуда отправляете форму; Использовать куки (но их опять же, можно отключить); Использовать сессии.

Иконки классов в Android Studio


Скачал проект с bitbucket, открыл в AndroidStudio. Что означают такие иконки классов? Проект запускается нормально, никаких ошибок не выдает.


Ответ

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

Передать в метод, нужный компонент вектора.

В коде много вот такого, причем когда обрабатывается одна ось - не обязательно должна обрабатыватся другая.
AxisX = ((currentTouchPos.x - startTouchPos.x) / workZoneInPixX); AxisY = ((currentTouchPos.y - startTouchPos.y) / workZoneInPixY);
Отличаются только оси и чуть чуть название переменных. Как передать это в метод, чтобы обрабатывать все похожие запросы этим? Чтобы сократить и избежать дублирования кода Вижу это как то примерно вот так
float FormatXY(x_or_y) Axis = ((currentTouchPos.x_or_y - startTouchPos.x_or_y) / workZoneInPixX_or_Y); return Axis;
Но понятно, что таким образом я просто передам значения x или y, а мне бы передать именно параметр x компонент вектора или y компонент вектора, и как то подставить это в методе.
Чтобы в результате, код
AxisX = FormatXY(X)
Был эквивалентен коду
AxisX = ((currentTouchPos.x - startTouchPos.x) / workZoneInPixX);
А код
AxisX = FormatXY(Y)
Был эквивалентен коду
AxisY = ((currentTouchPos.y - startTouchPos.y) / workZoneInPixY);


Ответ

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

Ввод/вывод в консоли, C++

Здравствуйте.
Решил написать небольшую RPG-игру с псевдографикой в консоли. Для считывания нажатий клавиш использовал функцию GetAsyncKeyState из Windows.h
bool isKeyPressed(int virtualKeyCode) { short keyState = GetAsyncKeyState(virtualKeyCode); return ((keyState & 0x8000) > 0); }
В функции Update проверяю состояние клавиш и изменяю направления движения героя.
void Update() { if(_kbhit()) { if (isKeyPressed('W')) { unitsArr[heroIndex].changeMoveDirectionTo(0, -1); moveUnitTo(&unitsArr[heroIndex]); } else if (isKeyPressed('S')) { unitsArr[heroIndex].changeMoveDirectionTo(0, 1); moveUnitTo(&unitsArr[heroIndex]);
} else if (isKeyPressed('A')) { unitsArr[heroIndex].changeMoveDirectionTo(-1, 0); moveUnitTo(&unitsArr[heroIndex]);
} else if (isKeyPressed('D')) { unitsArr[heroIndex].changeMoveDirectionTo(1, 0); moveUnitTo(&unitsArr[heroIndex]); } ... }
После этого захотел написать функцию, которая выводила бы на экран вопрос, и при помощи _getch() считывала бы ответ игрока (y/n)
bool getAnswerFromLogPanel(const string questionMessage) { UpdateLog(questionMessage + " [Y]/[N]");
const char inputAnswer = tolower(_getch()); if (inputAnswer == 'y') { UpdateLog("[Y]"); return true; }
UpdateLog("[N]"); return false; }
Здесь столкнулся с проблемой, что _getch() не останавливает поток и не ждет нажатия клавиши.
При этом если использовать вместо _getch() функцию getchar() или cin.get() на экран консоли выводятся символы ранее нажатых клавиш.


Как я понял,_getch() просто считывает один символ из последних нажатых клавиш (те, которые выводит на экран getchar() или cin.get()) и поэтому не останавливает поток.
То что мне не помогло:
cin.ignore(), cin.clear(), cin.sync(), system("cls"), fflush(stdin)
То что работает, но не так как надо:
Работает, но если до этого когда-то была нажата клавиша Y или N - ответ будет считываться с нее.
do { char input = _getch(); input = tolower(input);
if (input == 'y') { UpdateLog("[Y]"); return true; }
if(input == 'n') { UpdateLog("[N]"); return false; } } while (true); При каждом срабатывании _kbhit() считывать при помощи _getch() символ с потока. Но тогда движение героя и реакция на нажатия клавиш значительно замедляется.
C++, Visual Studio 2015


Ответ

Поскольку потоковое чтение работает в конечном итоге через WinAPI-шные функции и не ожидает, что будет использован прямой доступ к тем же функциям, то оно не дружит с низкоуровневым вводом через GetAsyncKeyState
Поэтому, если уж вы пользуетесь низкоуровневыми функциями, пользуйтесь ими всё время.
Для вашего случая, вам должны помочь FlushConsoleInputBuffer (чтобы сбросить буферизацию уже нажатых к текущему моменту клавиш) и ReadConsoleInput. Вот общая страница документации, на всякий случай.