Являются перегрузки оператора в C++ большей проблемой, чем они стоят?

Вы можете создать индекс по столбцу User и использовать sum по первому уровню:

csvArray = []
for x in range(1,101): 
   csvArray.append(pd.read_csv("myCsv{}.csv".format(x), index_col=['User']))

Или:

csvArray = [pd.read_csv("myCsv{}.csv".format(x), index_col=['User']) for x in range(1,101)]
<час>
full_df = pd.concat(csvArray).fillna(0).sum(level=0).reset_index()

В вашем решении следует агрегировать по столбцу User:

full_df = pd.concat(csvArray).fillna(0).groupby('User', as_index=False).sum()
6
задан 3 revs, 3 users 100% 23 May 2012 в 05:55
поделиться

14 ответов

Перегруженные операторы похожи на специю. Немного может сделать что-то лучше; слишком много может сделать это горьким.

38
ответ дан 8 December 2019 в 02:00
поделиться

Некоторые примеры перегрузки, о которой должен знать каждый программист на C++, даже если они не одобряют:

  • оператор = () требуется, чтобы позволить объектам C++ вести себя как значения.
  • оператор-> () требуется для реализации интеллектуальных указателей
  • оператор <<() и оператор>> () требуются, чтобы интегрировать типы в iostream платформу
  • оператор <() используется по умолчанию при сравнении объектов, хранивших в стандартных контейнерах библиотеки
  • оператор () () используется для реализации функторов, используемых стандартными алгоритмами библиотеки
  • оператор ++ (), как ожидают, будет доступен при реализации собственного итератора
30
ответ дан 8 December 2019 в 02:00
поделиться

Столь же легкий, как это должно жаловаться на перегруженные операторы, пока они не действуют удивительными способами, я действительно не вижу проблему. Да существуют плохие примеры там (даже в stl). Посмотрите оператор присваивания auto_ptr, например. Перегрузка некоторых операторов, как &&, || и , почти всегда будет плохим. Но по большей части, заставьте операторы сделать то, что они рекламируют и нет никакой настоящей проблемы.

Это - плохая практика для перегрузки operator+ чтобы сделать что-то странное, но это столь же плохо при помещении метода под названием, "Добавляют" к классу, который сериализировал объект к диску.

14
ответ дан 8 December 2019 в 02:00
поделиться

Я думаю, что это действительно зависит от варианта использования. Существует несколько типов классов, которых операторы являются необходимостью. Например, интеллектуальные указатели были бы бесполезны без-> и * операторы.

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

if ( point1 > point2 ) ...

Просто взгляды загружаются лучше, чем

if ( point1.Compare(point2) < 0 ) ...

Я нахожу, что меньше использования для других операторов, хотя брошено иногда пригождается.

4
ответ дан 8 December 2019 в 02:00
поделиться

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

Перегрузка << и >> операторы помогают расширить потоки C++, и в новых видах потоков, новых объектах для ввода-вывода и в обоих. Перегрузка -> делает интеллектуальные указатели почти общедоступной заменой для указателей C++. Перегруженные операторы позволяют иметь оператор объединения строк и создать новые виды чисел, которые являются синтаксически точно так же, как ints. Наличие их позволяет сделать вещи в библиотеках, которые потребовали бы изменений уровня языка на других языках.

У них действительно есть свои ограничения. Нет никакого оператора, подходящего для возведения в степень. Существует только один оператор умножения, и в некоторых случаях существует больше чем один способ умножиться (с 3D векторами, например, существуют, по крайней мере, скалярные и векторные произведения). &&, ||, и операторы запятой не могут копировать свою встроенную функциональность, так как они не могут иметь оценок короткого замыкания и упорядочить точки.

И, конечно, они могут быть оскорблены. Нет никакого требования языка, например, чтобы арифметические операторы работали что-либо как арифметика. Я видел ужасные вещи, сделанные, чтобы придумать нотацию SQL, что кто-то думал, было интуитивно. В программе C++, которая была плохо записана, невозможно знать что, скажем, a = x * y; делает, так как это a.operator=(x.operator*(y));, или возможно a.operator=(operator*(x, y)); или что-то и функции оператора могли быть записаны, чтобы сделать что-либо.

Намерение Bjarne Stroustrup в разработке C++ состояло в том, чтобы включать полезные функции независимо от возможности злоупотребления, тогда как намерение James Gosling в разработке Java состояло в том, чтобы исключить чрезмерно оскорбительные функции, даже если бы они были несколько полезны. Мне не ясно, что или тех основных положений является корректным или неправильным, но они отличаются.

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

До обучающих студентов скажите им не самим операторам перегрузки (кроме при определенных условиях, таких как функторы и оператор присваивания), но укажите, как библиотека использует перегруженные операторы. Я не доверял бы никакому студенту C++, чтобы сделать их правильно, и если они собираются быть способными сделать это, они могут и изучать это самостоятельно. Они будут знать, что это хитро, потому что Вы запретили его в классе. Некоторые из тех я никогда не доверял бы ничего более сложного, чем a for оператор узнает, как перегрузить операторы и сделает так или иначе, но это - жизнь.

6
ответ дан 8 December 2019 в 02:00
поделиться

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

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

3
ответ дан 8 December 2019 в 02:00
поделиться

Операторы и случаи, когда я использовал их:
оператор->, оператор* - для объектов прокси и различных оберток.
оператор = - необходимый для избегает неожиданного поведения на копии.
оператор <(>, <=>, =) - для хранилища в карте или наборе (но обычно лучше передать функтор в этого).
оператор <<(>>) - для потоков и повышения:: совместимость lexical_cast.
оператор ==! = - для позволяют, сравнивают объекты.
оператор! - иногда вместо этого допустимый () функция.
оператор Type - для преобразования в другой тип.
оператор () - для умного функтора, когда повышение было запрещено.

это все.
Иногда назад я использовал другие операторы, но это было для моей математики utils.

Также должно быть осторожным с логическими операторами (&&, ||) - у нас будет различие со стандартом семантическим:

ptr && ptr->method()

мог иметь другой смысл, если мы перегрузили operator&&.

1
ответ дан 8 December 2019 в 02:00
поделиться

Как Neil указывает в своем ответе, перегрузка оператора является необходимой темой для изучения хороших объектно-ориентированных идиом C++. Я учил бы это с осторожностью студентам, что, если Вы не реализуете перегруженные операторы в соответствии с идиоматическими конвенциями, это может привести к очень ошибочному и неожиданному поведению. Перегрузка оператора не является хорошим временем, чтобы быть творческой.

2
ответ дан 8 December 2019 в 02:00
поделиться

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

Интеллектуальные указатели полагаются на способность объектов перегрузить оператор разыменования так, чтобы они могли вести себя как указатели.

Перегрузка оператора чрезвычайно важна для того, чтобы сделать C++, программирующий терпимый. Что касается его сложный, я просто не вижу его. Это не более сложно, чем создание Вашей собственной функции, которую люди обычно находят довольно легкими. Если Вы называете его, "умножаются", это - функция при именовании его "оператором*" это - оператор. Но код в теле - то же самое.

Конечно, операторами иногда злоупотребляют. И <<или>> может быть приемлемая граница, но они так обычно известны и использовали это, я думаю, что это справедливо.

Если бы Вы спросили об операторе, перегружающемся в чем-то как C#, однако, я с удовольствием обошелся бы без них. Их реализация является намного более неловкой, они не работают с дженериками, и они не включают все хорошие и удобные приемы, которые использует C++.

5
ответ дан 8 December 2019 в 02:00
поделиться

Мне действительно нравится способность перегрузить арифметические операторы для невстроенных типов в C++. Но только для типов с подобным арифметике поведением; например, классы фиксированной точки, 3D векторные классы, классы комплексного числа, классы "сверхбольшого числа" произвольной длины. Я написал подобный код в Java и раздражался при необходимости записать вещи как a.Add(b) вместо a+b. Обратите внимание, я - математик по образованию; кажется мне, перегрузка оператора позволяет Вам получить определенное совершенство предметно-ориентированного языка в C++, не имея необходимость на самом деле реализовывать тот.

Но меня действительно раздражает, когда я вижу, например, operator+ будучи перегруженным с функциональностью, которая была бы лучше сделана operator<< (в соответствии с изворотливой, но хорошо установленной iostream конвенцией) или STL .push_back()- как шаблоны.

Что касается operator()... обнаружение сообщения boost::bind & boost::function Я не могу вообразить жизнь без функторов. И интеллектуальные указатели не были бы почти как удобные без перегруженного operator*, operator-> и т.д.

1
ответ дан 8 December 2019 в 02:00
поделиться

Проблема с перегружающимися операторами состоит в том, что некоторым людям нравится перегружать их с функциональностью, которая действительно не имеет никакого смысла относительно исходной (C) цели оператора (здесь, я указываю на>> и <<операторы в станд.:: материал iostream.). В моем уме единственное время необходимо перегрузиться, операторы, когда любой перегрузка ТОЧНО соответствует значению базового оператора (т.е. <и> должны быть сравнения.) ИЛИ, необходимо перегрузить его определенным способом для взаимодействия с другой библиотекой.

Откровенно говоря, я не перегружу оператор вообще, если я не должен буду для библиотеки. Это просто заставляет читателя также упорно работать для выяснения то, что продолжается.

0
ответ дан 8 December 2019 в 02:00
поделиться

Один из операторов, которые необходимо постараться не перегружать, является оператором преобразования. Это приводит к таким неожиданным результатам, что даже STL предпочитает не перегружать его и вместо этого предпочитает функциональное преобразование стиля:

std::string str = "foo";
char *ch = str.c_str(); //rather than char *ch = str.operator *char();
0
ответ дан 8 December 2019 в 02:00
поделиться

Это - хорошее, чтобы иметь функцию, но не существенную. Во многих случаях я нахожу их более сбивающими с толку, чем преимущества, которыми они обладают. Как в примере JaredPars, функция .compare более очевидна, чем'>' мне. Один see's непосредственно, что point1 является объектом и не примитивным типом данных. Мне нравятся перегруженные операторы в, освобождает, я использую, но в моем собственном коде я использую их очень редко.

Править: мой выбор имени функции непоследователен. .compare замены с .greaterThan делает это более ясным. То, что я имею в виду, что имя функции, связанное возразить для меня, более очевидно, чем оператор, который не имеет никакого ascociation с объектом на первом взгляде. По моему скромному мнению, хорошо выбранное имя функции легче считать.

-1
ответ дан 8 December 2019 в 02:00
поделиться

Я отсутствую перегружавший операторы в Java, особенно в следующих ситуациях:

Класс, который является алгоритмом или функтором: (Стратегическая модель, Цепочка Ответственности, Интерпретатора, и т.д.). Естественная вещь состоит в том, чтобы перегрузить op (); вместо этого, каждый программист придумывает (часто несовместимый и таким образом сбивающий с толку) названия функций: "оценка", "оцените", "операция", "мелкая монета", и т.д. Таким образом, ясность уменьшается, потому что эти имена, которые мы вынуждены использовать, не делают свое значение очевидным.

Класс, который имеет преобразование в другой тип: В C++ это - оператор Type () и работает и на фактическое преобразование и на получение внутреннего члена желаемого класса. Второй случай подходит много в Java, когда класс является излишне окончательным, но Вы хотите добавить операции к нему:

class DecoratedStringBuffer { //extends StringBuffer doesn't work, as String is final
  private String byContainmentThen;
  public decorate(final String prefix, final String suffix) { ... }
  public append(final String s) { byContainmentThen.append(s);}
  // other forwarding functions
}

Так как DecoratedStringBuffer не, - StringBuffer, прежде чем он оставит Ваш код и возвратится к клиентскому коду, он должен быть преобразован назад, по-видимому, функцией, которая наконец применяет суффикс и префикс. Было бы замечательно, если мы могли бы назвать тот оператор StringBuffer () (и еще больше, если Java, как C++, мог бы применить одно предоставленное пользователями преобразование).

Вместо этого потому что нет никакой конвенции, мы должны дать ему имя, которое обязательно более неоднозначно. getStringBuffer () является одним очевидным именем, но многим пользователям Java, это будет подразумевать соответствующий setStringBuffer, который мы не хотим. Даже если это не подразумевает что, неоднозначное имя: StringBuffer, Вы получаете тот, которым мы управляем на, или что-то еще?

toStringBuffer () является лучшим именем и шаблоном, который я склонен применять, но затем кто-то читающий код задается вопросом, почему то, что похоже на метод считывания, называют "к" ClassName.

Честно, кроме разработки числовых классов или "очевидно" cocatenatable объектов, существует мало использования для перегрузки op +. И поскольку Java не основан на значении как C++, там не полезен для op =; Java не пытается заставить все действовать как примитивный международный класс значения. Это - op () и операторы преобразования, которые я пропускаю.

0
ответ дан 8 December 2019 в 02:00
поделиться
Другие вопросы по тегам:

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