Зачем нам нужны три разных способа работы в пандах? - PullRequest
1 голос
/ 19 апреля 2019

Зачем нам нужны три способа работы?

(я использую умножение для примеров)

Первый способ:

df['a'] * 5

Второй способ:

df['a'].mul(5)

Третий способ:

df['a'].__mul__(5)

Не достаточно просто двух, не нужно mul, мне было интересно, может ли это быть как обычные способы, как целое число

Первый способ:

3 * 5

Второй способ:

(3).__mul__(5)

Но в штатных базах инетгера:

(3).mul(5)

сломается.

Мне просто любопытно, зачем нам столько вещей в Пандах, то же самое с сложением, вычитанием и делением.

Ответы [ 3 ]

3 голосов
/ 19 апреля 2019

* и mul делают одно и то же, но __mul__ отличается.

* и mul выполняют некоторые проверки перед делегированием __mul__.Есть две вещи, о которых вы должны знать.

  1. NotImplemented

Существует специальное одноэлементное значение NotImplemented, которое возвращается классом __mul__ вслучаи, когда он не может обработать другой операнд.Затем он говорит Python попробовать __rmul__.Если это тоже не помогает, то генерируется общий TypeError.Если вы используете __mul__ напрямую, вы не получите эту логику.Обратите внимание:

class TestClass:

    def __mul__(self, other):
        return NotImplemented

TestClass() * 1

Вывод:

TypeError: unsupported operand type(s) for *: 'TestClass' and 'int'

Сравните это с этим:

TestClass().__mul__(1)

Вывод:

NotImplemented

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

Обработка оператора производного класса

Когда вы пытаетесь выполнить что-то вроде Base() * Derived(), где Derived наследует от Base, вы ожидаете, что Base.__mul__(Derived()) будет вызван первым.Это может создавать проблемы, поскольку Derived.__mul__ с большей вероятностью знает, как обрабатывать такие ситуации.

Поэтому, когда вы используете *, Python проверяет, является ли тип правого операнда более производным, чем тип левого, иесли это так, то вызывает метод __rmul__ правого операнда напрямую.

Наблюдение:

class Base:

    def __mul__(self, other):
        print('base mul')

class Derived(Base):

    def __rmul__(self, other):
        print('derived rmul')

Base() * Derived()

Вывод:

derived rmul

Обратите внимание, что даже если Base.__mul__ невернуть NotImplemented и может четко обрабатывать объект типа Derived, Python даже даже не смотрит на него первым;он делегирует Derived.__rmul__ немедленно.

Для полноты, равно одно отличие между * и mul, в контексте pandas: mul является функциейи, следовательно, может передаваться в переменной и использоваться независимо.Например:

import pandas as pd

pandas_mul = pd.DataFrame.mul
pandas_mul(pd.DataFrame([[1]]), pd.DataFrame([[2]]))

С другой стороны, это не удастся:

*(pd.DataFrame([[1]]), pd.DataFrame([[2]]))
1 голос
/ 19 апреля 2019

Во-первых, никогда не следует использовать третий способ (df['a'].__mul__(5)), поскольку это внутренний метод, вызываемый классом Python.В общем, пользователи не касаются ни одного из методов «дунда».

Что касается двух других способов, первый способ очевиден;Вы просто умножаете вещь.Это стандартная математика.

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

Например:

def pandas_math(series, func, val):
    return getattr(series, func)(val)

pandas_math(df['a'], 'mul', 5) даст тот же результат, что и df['a'].mul(5) но теперь вы можете передать mul в качестве переменной или любую другую функцию, которую вы хотите использовать.Это гораздо проще, чем жестко кодировать все символы.

1 голос
/ 19 апреля 2019

И "магический метод" __mul__, и оператор * одинаковы в лежащем в основе питоне (* просто вызывает __mul__), и, как вы указали, это способ, которым python stadarized обрабатывает вещи.Другой метод mul - это метод, который вы можете использовать для отображения (используйте map) и избегать использования, например, lambda x, y: x*mul.Да, вы все еще можете использовать __mul__, но обычно эти методы (__x__) не предназначены для использования в качестве обычных функций, а простой mul делает код более понятным.

Итак,Вы действительно не «нуждаетесь» в этом, но приятно иметь и использовать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...