Это потому, что вы импортируете c_data в init .py, это делает рекурсивный импорт. Чтобы быть более понятным, вы импортируете c_data
и определяете flask_app внутри __init__
, но позже c_data
вы импортируете [ 115], который еще не определен.
from webapp import c_data # Remove it, it makes recursive import
# Place where webapp is defined
flask_app = Flask(__name__)
Попробуйте удалить его. Или измените способ импорта c_data.
Возможное решение, измените run_app.py
Не забудьте удалить from webapp import c_data
в __init__.py
from webapp import flask_app
from webapp import c_data # New import
if __name__ == '__main__':
# Running webapp in debug mode
flask_app.run(debug=True)
Так как Вы не можете только бросить сюда, я использовал бы бесплатную функцию, и если, вероятно, будут другие перечисления, которые также нуждаются в преобразовании, пытаются заставить его немного походить на встроенные броски:
template<typename T>
T my_enum_convert(int);
template<>
En my_enum_convert<En>(int in) {
switch(in) {
case ValA: return VALUE_A;
case ValB: return VALUE_B;
case ValC: return VALUE_C;
default: throw std::logic_error(__FILE__ ": enum En out of range");
}
}
int my_enum_convert(En in) {
switch(in) {
case VALUE_A: return ValA;
case VALUE_B: return ValB;
case VALUE_C: return ValC;
// no default, so that GCC will warn us if we've forgotten a case
}
}
En enumValue = my_enum_convert<En>(ValA);
int hashDefineValue = my_enum_convert(VALUE_A);
enumValue = my_enum_convert<En>(0); // throws exception
Или что-то как этот - могло бы скорректировать его, если проблемы возникают при использовании его.
Причина я не использовал бы неявное преобразование, состоит в том, что уже существует неявное преобразование от En до интервала, который дает неправильный ответ. Даже если можно надежно заменить это чем-то, что дает правильный ответ, получающийся код не посмотрит, как будто он делает любое преобразование. IMO это препятствует любому, который более поздние взгляды на код больше, чем ввод вызова к подпрограмме преобразования препятствуют Вам.
Если Вы хотите преобразовать в интервал и преобразовать из интервала для взгляда очень отличающимися, то Вы могли дать шаблон и функцию выше различных имен.
С другой стороны, если Вы хотите, чтобы они выглядели одинаково (и больше как static_cast), Вы могли бы сделать:
template<typename T>
T my_enum_convert(En in) {
switch(in) {
case VALUE_A: return ValA;
case VALUE_B: return ValB;
case VALUE_C: return ValC;
}
}
int hashDefineValue = my_enum_convert<int>(VALUE_A);
Как записано, T должен иметь неявное преобразование из интервала. Если Вы хотите поддерживать T, который только имеет явное преобразование, используйте "возврат T (ValA)"; вместо этого (или "возврат static_cast <T> (ValA)"; если Вы полагаете, что конструкторы единственного аргумента являются составами исполнителей C-стиля и следовательно непозволительный).
В то время как неявный кастинг более удобен, чем функции перевода, также менее очевидно видеть то, что продолжается. Так как подход был бы, оба, удобные и очевидные, могли бы быть должны использовать Ваш собственный класс с перегруженными операторами броска. При кастинге пользовательского типа в перечисление или интервал не будет легко пропустить некоторый пользовательский кастинг.
Если создание класса для этого не является опцией по любой причине, я пошел бы для функций перевода как удобочитаемость во время обслуживания, более важно, чем удобство при написании кода.
Вы не можете перегрузить операторы для перечислений. Или я пропускаю что-то? Ну, Вы могли создать своего рода фиктивные классы, которые будут иметь неявного конструктора, берущего интервал, и затем иметь оператор броска к перечислению (и наоборот).
Так, единственное решение состоит в том, чтобы иметь функции. Кроме того, я сделал бы перегрузки, как Patrick предполагает.
Функции имеют и затем перегружают библиотечные функции?
//libFunc( enum a );
libFuncOverload( define a ) {
libFunc( toEn( a ) );
}
Преобразование перечисления к интервалу, например, интервала (VALUE_A), происходит автоматически/прозрачно.
Преобразование интервала к перечислению, например, En(ValA), может извлечь выгоду из проверки исправности, чтобы удостовериться, что международное значение является допустимым членом перечисления. (Хотя, надо надеяться, код библиотеки не предполагает, что его перечислимые значения допустимы во-первых.)
В то время как это не поможет с "интервалом x" случаи, можно помочь несколько путем изменения:
#define ValA 5
Кому:
#define ValA VALUE_A
Если перечислимый En () включается/определяется везде, и ValA и VALUE_A будут работать и на нечто (интервал) и на панель (En) везде автоматически/прозрачно.
Вы могли использовать:
#ifdef ValA
STATIC_ASSERT( ValA == VALUE_A, ValA_equal_VALUE_A );
#undef ValA
#else
#warning "ValA undefined. Defining as VALUE_A"
#endif
#define ValA VALUE_A
Где STATIC_ASSERT - что-то как:
/* Use CONCATENATE_4_AGAIN to expand the arguments to CONCATENATE_4 */
#define CONCATENATE_4( a,b,c,d) CONCATENATE_4_AGAIN(a,b,c,d)
#define CONCATENATE_4_AGAIN(a,b,c,d) a ## b ## c ## d
/* Creates a typedef that's legal/illegal depending on EXPRESSION. *
* Note that IDENTIFIER_TEXT is limited to "[a-zA-Z0-9_]*". *
* (This may be replaced by static_assert() in future revisions of C++.) */
#define STATIC_ASSERT( EXPRESSION, IDENTIFIER_TEXT) \
typedef char CONCATENATE_4( static_assert____, IDENTIFIER_TEXT, \
____failed_at_line____, __LINE__ ) \
[ (EXPRESSION) ? 1 : -1 ]