Когда вы создаёте список, используя генераторное выражение, вы создаёте также итератор:
Я бы был аккуратнее, потому что есть ещё вот такая конструкция (круглые скобки):
myList = (x * x for x in range(3))
И вот это как раз я бы назвал генераторным выражением. Как минимум, я бы добавлял в скобках оригинальное название терминов, которые трудно переводятся (в данном случае это list comprehension).
Всё, к чему можно применить конструкцию «for… in...», является итерируемым объектом:
А зачем вы переводите так, что каждый раз у вас новый термин ? В оригинале заголовок Iterables - вы его перевели как Итераторы . Тут то же слово в оригинале, но теперь он у вас итерируемый объект .
Ваш код будет вызываться каждый раз, когда for обращается к генератору.
Вводит в заблуждение. Оригинал: "Then, your code will continue from where it left off each time for uses the generator." - Каждый раз, когда for обращается к генератору на очередной итерации, ваша функция продолжит с того места, где она была прервана на предыдущей итерации. Как-то так.
Этот код содержит несколько меньших частей:
Там "smart parts", а не "small parts".
Цикл итерируется по списку, но списко расширяется во время итерации :-) Это лаконичный способ обойти все сгрупиррованные данные, зоть это и немного опасно, так как может обернуться бесконечным циклом. В таком случае
Тут вообще с точностью до наоборот. Не в таком случае, а в этом (имеется в виду случай, описанный в коде). А у вас тут как будто вы дальше продолжаете обосновывать предыдущее утверждение про опасность бесконечного цикла. Хотя автор просто описывает дальше, как код работает.
который ожидает на вход что-нибудь итерируемое и добавляет его значения к списку.
Теперь iterable превратилось в что-нибудь итерируемое.
Как это нет, вроде как раз есть. Каждый раз candidates модифицируются ссылками на узлы, при вызове extend. То, что каждый раз выкусывается самый ранний делу не помогает. Или я что-то не понял.
На мой вгляд здесь действительно есть место введению в заблуждение. extend как раз-таки добавит ссыли на узлы. Генератор тут вообще ничего не оптимизирует. То же самое можно было сделать с обычными ссылками. Либо я что-то тоже не понимаю.
Но вообще я предпочитаю конфигурацию хранить в отдельном файле. Типа config.h . Так скетч не захламляется.
// Инвертированные значения HIGH и LOW
const int MYHIGH = LOW;
const int MYLOW = HIGH;
Тут уже сказали про это. Имя плохое. Более того, int здесь избыточен может быть. Достаточно uint8_t , хотя надо смотреть, что там по памяти будет. В любом случае, всякие digitalWriteuint8_t ожидают, ЕМНИП.
unsigned long minTime = 0xFFFFFFFF; // Максимальное значение unsigned long
#include <limits.h>
...
unsigned long minTime = ULONG_MAX;
// А ещё лучше
typedef unsigned long ms_t; // Или time_t
...
ms_t minTime = ULONG_MAX;
// Метод для добавления насоса
bool addPump(SoilSensor sensor, int pumpPin, unsigned long pumpDuration) {
Я бы ещё добавил проверку на пересечение. Т.е. что будет, если я пытаюсь добавить насос на занятый пин ? С другой стороны, ниже в setup я не вижу проверки статуса добавления.
// Класс контроллера насосов
class PumpController {
private:
Pump** pumps; // Массив указателей на насосы
Как альтернатива, можно использовать шаблоны, и сделать класс
template <uint8_t N = 10>
class PumpController {
private:
Pump*[N] = {}; // ЕМНИП тут уже нулевые указатели, но проверьте
public:
static constexpr MaxN = N; // если надо
}
Как я уже сказал выше: не вижу проверку статуса добавления. И так, просто мысли вслух: я вижу тут проблему, что сенсоры приколочены к контроллеру. Т.е., если мне надо сенсор, ещё как-то использовать, то я этого сделать не могу, потому что он только внутри контроллера существует. Может быть, лучше было сделать так:
Pump::Pump(const SoilSensor* sensor);
// и
bool PumpController::addPump(const Pump* pump);
И тупо в скетче (скорее всего где-то вру, но набросок) :
Недавно делал реализацию FSM на C++. Состояния (State) и События (Event) представлены enum 'ами. Переходы (Transition) --- это мапы типа [EState, EEvent] -> EState, т.е. текущее состояние и событие определяет конечное. Далее у FSM есть методы void process(EEvent) и bool step() . Первый --- ищет в вышеупомянутом мапе переходов соответствующую пару события и текущего состояния и меняет текущее состояние. Второй --- делает действие, соответствующее текущему состоянию. Т.е. выглядит это следующим образом:
FSM fsm; // A bit more complicated but doesn't matter now
EEvent event;
while(fsm.step()) {
//get event somehow
event = ...;
fsm.process(event);
}
В этом смысле гарантии на уровне того самого списка переходов. Далее можно навешивать тесты и/или валидации. Скажем, что нет переписывающих переходов, т.е., когда сначала [A, B] -> C, а потом [A, B] -> D. И т.д. Я даже видел реализацию чисто на шаблонах. Статья даже на хабре есть.
Не совсем понял. В начале вы говорите так, что подразумевается какая-то неоднозначность справедливости позиции автора статьи. Но дальше я не вижу никакого противопоставления. Вы просто говорите, что данные окна удобно хранить в классе, но про методы ничего не сказали. Они тоже у окна удобнее, или это отдельные функции ?
# Устанавливаем соединение с базой данных
with sqlite3.connect('my_database.db') as connection:
cursor = connection.cursor()
try:
# Начинаем транзакцию автоматически
with connection:
Извините, не совсем уверен, что тут повторный context manager нужен. Вы же уже и так в контекст вошли в первой строчке. Более того, необходимо выставить autocommit = False при соединении. Иначе контекст ничего не делает: docs
UPD: Пардон, насчет последнего я ошибся. Документация говорит, что в случае, если autocommit = LEGACY_TRANSACTION_CONTROL (что по умолчанию так), то поведение диктуется другим параметром, а именно, isolation_level . И по умолчанию, действительно, транзакции открываются перед некоторыми операциями над базой. Но, на мой взгляд, это сильно всё запутывает, а "explicit better than implicit". Вот этот пост довольно полезный: SE
Айнштайн. Ойлер. Фройд. Ну это так, навскидку. Как написали ниже, если уж называть правильно, то надо называть на "родном языке". Считаю, что это абсолютно не важно. Любая русификация будет неправильной в узком смысле. Я не пытаюсь проявить таким образом неуважение. Просто я об этом не задумываюсь и вам не советую. В моих кругах он известен как линус.
Да, я, к сожалению, знаю :) Не додумался до такого простого решения. Теперь только так делать буду. Бонусом меньше вероятность пятак сорвать сверлом. Спасибо !
У меня мысли следующие. Оператор производной --- действует на функцию (а не на число) и возвращает функцию, а не число. Что в данном случае означает запись 2' ? Я понимаю, что есть функции-константы, и да --- для таких функций будем иметь f' = 0. Но меня корёжит запись 2' .
Я бы был аккуратнее, потому что есть ещё вот такая конструкция (круглые скобки):
И вот это как раз я бы назвал генераторным выражением. Как минимум, я бы добавлял в скобках оригинальное название терминов, которые трудно переводятся (в данном случае это list comprehension).
А зачем вы переводите так, что каждый раз у вас новый термин ? В оригинале заголовок Iterables - вы его перевели как Итераторы . Тут то же слово в оригинале, но теперь он у вас итерируемый объект .
Вводит в заблуждение. Оригинал: "Then, your code will continue from where it left off each time
foruses the generator." - Каждый раз, когдаforобращается к генератору на очередной итерации, ваша функция продолжит с того места, где она была прервана на предыдущей итерации. Как-то так.Там "smart parts", а не "small parts".
Тут вообще с точностью до наоборот. Не в таком случае, а в этом (имеется в виду случай, описанный в коде). А у вас тут как будто вы дальше продолжаете обосновывать предыдущее утверждение про опасность бесконечного цикла. Хотя автор просто описывает дальше, как код работает.
Теперь iterable превратилось в что-нибудь итерируемое.
Дальше уже не стал корректировать.
Перевод на троечку. Лучше прочтите оригинал.
Как это нет, вроде как раз есть. Каждый раз
candidatesмодифицируются ссылками на узлы, при вызовеextend. То, что каждый раз выкусывается самый ранний делу не помогает. Или я что-то не понял.На мой вгляд здесь действительно есть место введению в заблуждение.
extendкак раз-таки добавит ссыли на узлы. Генератор тут вообще ничего не оптимизирует. То же самое можно было сделать с обычными ссылками. Либо я что-то тоже не понимаю.Приветствую ! Спасибо за статью. Тоже недавно приобрел такой сенсор. Буду смотреть. А пока:
С одной стороны динамическое. С другой --- нужно модифицировать прошивку и перешивать.
NIT. Форматирование не везде.
NIT. ИМХО здесь лучше использовать слово платформа (которое вы как раз далее используете).
Захардкоженное значение. Я бы использовал:
Но вообще я предпочитаю конфигурацию хранить в отдельном файле. Типа
config.h. Так скетч не захламляется.Тут уже сказали про это. Имя плохое. Более того,
intздесь избыточен может быть. Достаточноuint8_t, хотя надо смотреть, что там по памяти будет. В любом случае, всякиеdigitalWriteuint8_tожидают, ЕМНИП.Я бы поглядел в
limits.h: тут . Т.е.Я бы ещё добавил проверку на пересечение. Т.е. что будет, если я пытаюсь добавить насос на занятый пин ? С другой стороны, ниже в
setupя не вижу проверки статуса добавления.Как альтернатива, можно использовать шаблоны, и сделать класс
Зачем такая низкая скорость ? Не, я понимаю, что тут, наверное, не бутылочное горлышко, но подозреваю, что это сделано, потому что в тутриалах так.
Как я уже сказал выше: не вижу проверку статуса добавления. И так, просто мысли вслух: я вижу тут проблему, что сенсоры приколочены к контроллеру. Т.е., если мне надо сенсор, ещё как-то использовать, то я этого сделать не могу, потому что он только внутри контроллера существует. Может быть, лучше было сделать так:
И тупо в скетче (скорее всего где-то вру, но набросок) :
На мой взгляд так выглядит нагляднее. И возникает возможность использовать один насос на несколько датчиков, если нужно.
P.S. Вот такой тред есть:
https://www.reddit.com/r/arduino/comments/q1anwt/beware_of_faulty_capacitive_soil_moisture_sensors/
P.P.S. А почему
>для цитирования не работает ?Вклинюсь.
Недавно делал реализацию FSM на C++. Состояния (State) и События (Event) представлены
enum'ами. Переходы (Transition) --- это мапы типа[EState, EEvent] -> EState, т.е. текущее состояние и событие определяет конечное. Далее у FSM есть методыvoid process(EEvent)иbool step(). Первый --- ищет в вышеупомянутом мапе переходов соответствующую пару события и текущего состояния и меняет текущее состояние. Второй --- делает действие, соответствующее текущему состоянию. Т.е. выглядит это следующим образом:В этом смысле гарантии на уровне того самого списка переходов. Далее можно навешивать тесты и/или валидации. Скажем, что нет переписывающих переходов, т.е., когда сначала [A, B] -> C, а потом [A, B] -> D. И т.д. Я даже видел реализацию чисто на шаблонах. Статья даже на хабре есть.
Спасибо. Я тоже ламинатор взял FGK-320S. Фоторезист китайский беру AQUA MER ME720. Получается неплохо.
Не совсем понял. В начале вы говорите так, что подразумевается какая-то неоднозначность справедливости позиции автора статьи. Но дальше я не вижу никакого противопоставления. Вы просто говорите, что данные окна удобно хранить в классе, но про методы ничего не сказали. Они тоже у окна удобнее, или это отдельные функции ?
Я теперь так и делаю. Пушка вообще. Даже старым станком советским я тепепь делаю отверстия 0.9мм
Скрытый текст
Взяли ? Просто интересно, спустя 10 лет :)
Извините, не совсем уверен, что тут повторный context manager нужен. Вы же уже и так в контекст вошли в первой строчке. Более того, необходимо выставить
autocommit = Falseпри соединении. Иначе контекст ничего не делает: docsUPD: Пардон, насчет последнего я ошибся. Документация говорит, что в случае, если
autocommit = LEGACY_TRANSACTION_CONTROL(что по умолчанию так), то поведение диктуется другим параметром, а именно,isolation_level. И по умолчанию, действительно, транзакции открываются перед некоторыми операциями над базой. Но, на мой взгляд, это сильно всё запутывает, а "explicit better than implicit". Вот этот пост довольно полезный: SEАйнштайн. Ойлер. Фройд. Ну это так, навскидку. Как написали ниже, если уж называть правильно, то надо называть на "родном языке". Считаю, что это абсолютно не важно. Любая русификация будет неправильной в узком смысле. Я не пытаюсь проявить таким образом неуважение. Просто я об этом не задумываюсь и вам не советую. В моих кругах он известен как линус.
А почему ошибка ? Напряжение на резисторе/конденсаторе пропорционально интегралу от входного напряжения.
https://youtu.be/S5S9LIT-hdc?si=zfQP4UgN8M_lTA9r
Скрытый текст
Линус Торвальдс печатает двумя пальцами
Пал пал
Спасибо, гляну.
Как же плохо... прям не заморачиваются. Уже и Autodesc туда же --- на стартовой странице сгенеренная печатная плата.
А можете порекомендовать материал по трассировке ?
Я нашел следующее: https://www.scs.stanford.edu/~zyedidia/docs/pcb/pcb_tutorial.pdf
и
https://docs.toradex.com/102492-layout-design-guide.pdf
Да, я, к сожалению, знаю :) Не додумался до такого простого решения. Теперь только так делать буду. Бонусом меньше вероятность пятак сорвать сверлом. Спасибо !
А точки у пятачков меди -- это чтобы их протравить и затем высверлить ?
У меня мысли следующие. Оператор производной --- действует на функцию (а не на число) и возвращает функцию, а не число. Что в данном случае означает запись 2' ? Я понимаю, что есть функции-константы, и да --- для таких функций будем иметь f' = 0. Но меня корёжит запись 2' .