Поиск самого изящного диспетчера кода

Да, это было , добавил в версии 2.5. Синтаксис выражения:

a if condition else b

Первый condition оценен, затем точно, один из a или b оценен и возвращен на основе булевская переменная значение condition. Если condition оценивает к True, то a оценен и возвращен, но b проигнорирован, или иначе когда b оценен и возвращен, но a проигнорирован.

Это позволяет закорачивать, потому что то, когда condition верно, что только [1 115] оценены и b, не оценено вообще, но когда condition ложь только [1 118] оценены, и a не оценен вообще.

, Например:

>>> 'true' if True else 'false'
'true'
>>> 'true' if False else 'false'
'false'

Примечание, что условные выражения выражение , не оператор . Это означает, что Вы не можете использовать операторы присваивания или pass или другой операторы в условном выражении выражение :

>>> pass if False else x = 3
  File "", line 1
    pass if False else x = 3
          ^
SyntaxError: invalid syntax

можно, однако, использовать условные выражения для присвоения переменной как так:

x = a if True else b

Думают об условном выражении как переключающийся между двумя значениями. Очень полезно, когда Вы находитесь в 'одном значении или другой' ситуации, этом, но еще не делает многого.

, Если необходимо использовать операторы, необходимо использовать нормальное if оператор вместо условного выражения , выражение .

Имеет в виду, что осуждено некоторым Pythonistas по нескольким причинам:

  • порядок аргументов отличается от тех из классика condition ? a : b тернарный оператор со многих других языков (таких как C, C++, Пойдите, Perl, Ruby, Java, JavaScript, и т.д.), который может привести к ошибкам, когда люди, незнакомые с "удивительным" поведением Python, используют его (они могут инвертировать порядок аргументов).
  • Некоторые находят это "громоздким", так как это идет вопреки нормальному потоку мысли (думающий об условии сначала и затем эффектах).
  • Стилистические причины. (Хотя 'встроенный if' может быть действительно полезны, и сделать Ваш сценарий более кратким, он действительно усложняет Ваш код)

при наличии затруднений при запоминании порядка затем помните, что при чтении вслух Вы (почти) говорите, что Вы имеете в виду. Например, x = 4 if b > 8 else 9 читается вслух как [1 125].

Официальная документация:

7
задан A. Levy 19 August 2009 в 16:36
поделиться

5 ответов

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

Mappings.h:

// Note: no fileguard
// The first is  the text string of the command, 
// the second is the function to be called, 
// the third is the description.
UGLY_SUCKER( "foo", cmd_foo, "Utilize foo." );
UGLY_SUCKER( "bar", cmd_bar, "Turn on bar." );

Parser .h:

class Myclass {
...
protected:
    // The command functions
    #define UGLY_SUCKER( a, b, c ) void b( args )
    #include Mappings.h
    #undef UGLY_SUCKER
};

Parser.cpp:

void Myclass::dispatch(string cmd, string args) {
    if (cmd == "")
        // handle empty case
#define UGLY_SUCKER( a, b, c ) else if (cmd == a) b( args )
#include Mappings.h
#undef UGLY_SUCKER
    else
       cmd_default(args);
}

void Myclass::printOptions() {
#define UGLY_SUCKER( a, b, c ) std::cout << a << \t << c << std::endl
#include Mappings.h
#undef UGLY_SUCKER
}

void Myclass::cmd_foo(string args) {
...
}
1
ответ дан 6 December 2019 в 11:50
поделиться

Похоже, вы ищете шаблон команды

Что-то вроде этого:

Создайте карту, подобную этой

std::map<std::string, Command*> myMap;

, затем просто используйте свой ключ для выполнения команда вроде этой ....

std::map<std::string, Command*>::iterator it = myMap.find(str);
if( it != myMap.end() ) {
    it->second->execute()
}

Чтобы зарегистрировать свои команды, вы просто делаете это

myMap["foo"] = new CommandFoo("someArgument");
myMap["bar"] = new CommandBar("anotherArgument");
8
ответ дан 6 December 2019 в 11:50
поделиться

Основное решение, по моей ссылке в комментарии к вопросу, состоит в том, чтобы сопоставить строку с вызовом какой-либо функции.

Фактическая регистрация пары строка -> указатель функции / функтор :

Во-первых, иметь одноэлементный (шок! Ужас!) Объект-диспетчер. Назовем его TheDispatcher - это оболочка для map , где Func - это указатель на функцию или тип функтора.

Затем создайте класс регистров:

struct Register {
   Register( comst string & s, Func f ) {
      TheDispatcher.Add( s, f );
   }
};

Теперь в ваших индивидуальных модулях компиляции вы создаете статические объекты (шок! ужас!):

Register r1_( "hello", DoSayHello );

Эти объекты будут созданы (при условии, что код находится не в статической библиотеке) и автоматически зарегистрируются в TheDispatcher.

А во время выполнения вы ищите строки в TheDispatcher. и выполнить связанную функцию / функтор.

5
ответ дан 6 December 2019 в 11:50
поделиться

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

typedef void (*cmd)(string);
​​
2
ответ дан 6 December 2019 в 11:50
поделиться

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

1
ответ дан 6 December 2019 в 11:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: