пространства имен для перечислимых типов - лучшие практики

1112 Я немного повозился. Действительно, в документации говорится:

буферизация является необязательным целым числом, используемым для установки политики буферизации. Пропуск 0, чтобы отключить буферизацию (разрешено только в двоичном режиме), 1, чтобы выбрать буферизацию строки (можно использовать только в текстовом режиме), и целое число> 1, чтобы указать размер в байтах буфера фрагмента фиксированного размера ... ] blockquote>

Следовательно, было бы разумно ожидать, что указание buffering=2 приведет к использованию буфера размером 2B (и при использовании этого буфера файлы будут сброшены). Однако в текстовом режиме это, кажется, (и документация не совсем ясно указывает, что в этом месте) влияет на подчеркивание BufferedWriter, но TextIOWrapper, чье write() вы в конечном итоге вызываете, по-прежнему «свое дело». .. Начиная с Python 3.7, вы говорите ему не делать этого и немедленно передаете записи в базовый объект, вызывая f.reconfigure(write_through=True) в файле, который вы открыли.


На самом деле весь код и проверки значения write_through уже есть в Python 3.6 (я проверял 3.6.8) (на самом деле _io_TextIOWrapper_write_impl, то есть _io.TextIOWrapper.write, идентичны в обе версии), но атрибут write_through не раскрывается (пока).

97
задан JasonMArcher 7 June 2015 в 01:29
поделиться

6 ответов

Исходный C++ 03 ответа:

преимущество от namespace (по class) - то, что можно использовать using объявления, когда Вы хотите.

проблема с использованием namespace состоит в том, что пространства имен могут быть расширены в другом месте в коде. В крупном проекте Вам не гарантировали бы это, два отличных перечисления оба не думают, что их называют eFeelings

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

при выполнении какого-либо из этих методов Вы опережаете события и вероятно не должны тщательно исследовать это далее.

Более новый, C++ 11 советов:

, Если Вы используете C++ 11 или позже, enum class, неявно определит объем перечислимых значений в имени перечисления.

С enum class Вы потеряете неявные преобразования и сравнения с целыми типами, но на практике который может помочь Вам обнаружить неоднозначный или содержащий ошибки код.

66
ответ дан Drew Dormann 24 November 2019 в 05:28
поделиться

К вашему сведению В C++ 0x существует новый синтаксис для случаев как то, что Вы упомянули (см. C++ 0x страница Wiki)

enum class eColors { ... };
enum class eFeelings { ... };
20
ответ дан jmihalicza 24 November 2019 в 05:28
поделиться

Я определенно избегал бы использования класса для этого; используйте пространство имен вместо этого. Вопрос сводится к тому, использовать ли пространство имен или использовать уникальные идентификаторы для перечислимых значений. Лично, я использовал бы пространство имен так, чтобы мои идентификаторы могли быть короче и надо надеяться более очевидными. Затем код приложения мог использовать 'директиву' пространства имен использования и сделать все более читаемым.

От Вашего примера выше:

using namespace Colors;

void setPenColor( const e c ) {
    switch (c) {
        default: assert(false);
        break; case cRed: //...
        break; case cBlue: //...
        //...
    }
}
9
ответ дан Charles Anderson 24 November 2019 в 05:28
поделиться

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

А возможное преимущество для использования класса, то, что они могут использоваться в качестве шаблонных аргументов типа, который не имеет место для пространств имен:

class Colors {
public:
  enum TYPE {
    Red,
    Green,
    Blue
  };
};

template <typename T> void foo (T t) {
  typedef typename T::TYPE EnumType;
  // ...
}

Лично, я не поклонник использование , и я предпочитаю полностью определенные имена, таким образом, я действительно не рассматриваю что как плюс для пространств имен. Однако это - вероятно, не самое важное решение, которое Вы примете в своем проекте!

7
ответ дан Richard Corden 24 November 2019 в 05:28
поделиться

Так как перечисления ограничены по объему к их объему включения, вероятно, лучше перенести их в что-то , чтобы не загрязнять глобальное пространство имен и помогать избежать коллизий имени. Я предпочитаю пространство имен классу просто, потому что namespace чувствует себя подобно мешку содержания, тогда как class чувствует себя подобно устойчивому объекту (cf. struct по сравнению с class дебаты). Возможное преимущество для пространства имен - то, что оно может быть расширено позже - полезный, если Вы имеете дело со сторонним кодом, который Вы не можете изменить.

Это все спорно, конечно, когда мы получаем классы Enum с C++ 0x.

5
ответ дан Michael Kristofik 24 November 2019 в 05:28
поделиться

Я также склонен заключать свои перечисления в классы.

Как сообщил Ричард Корден, преимущество класса состоит в том, что это тип в смысле С ++, и поэтому вы можете его использовать с шаблонами.

У меня есть специальный класс toolbox :: Enum для моих нужд, который я специализирую для каждого шаблона, который предоставляет базовые функции (в основном: отображение значения перечисления в std :: string, чтобы было легче читать ввод-вывод) .

Мой маленький шаблон также имеет дополнительное преимущество - действительно проверять допустимые значения. Компилятор в некоторой степени небрежно проверяет, действительно ли значение находится в перечислении:

typedef enum { False: 0, True: 2 } boolean;
   // The classic enum you don't want to see around your code ;)

int main(int argc, char* argv[])
{
  boolean x = static_cast<boolean>(1);
  return (x == False || x == True) ? 0 : 1;
} // main

Меня всегда беспокоило, что компилятор не улавливает этого, поскольку у вас остается значение перечисления, которое не имеет смысла (и что вы выиграли '' t ожидать).

Аналогично:

typedef enum { Zero: 0, One: 1, Two: 2 } example;

int main(int argc, char* argv[])
{
  example y = static_cast<example>(3);
  return (y == Zero || y == One || y == Two) ? 0 : 1;
} // main

Еще раз main вернет ошибку.

3
ответ дан 24 November 2019 в 05:28
поделиться
Другие вопросы по тегам:

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