Правильный шаблон для функций c в Python - PullRequest
1 голос
/ 20 апреля 2020

У меня есть Python программа, которая имеет сбой, и моя голова кружится с правилами контекста.

Предположим, у нас есть класс с именем Matrix. Внутри он содержит двумерный луч чисел. Таким образом, ядро ​​для создания экземпляра выглядит следующим образом:

z = Matrix([values])

, поэтому экземпляр z берет список списков и создает экземпляр, в котором z.internal_matrix является атрибутом, содержащим переданный в виде матрицы список.

Вопрос, на котором я всегда застреваю, заключается в следующем: как вы разрабатываете код, чтобы он был максимально надежным и понятным, если вы создаете функции dyadi c, такие как "matrix_mult"?

Обратите внимание, что это проблема возникает меньше, когда функция, которую вы хотите вызвать, является функцией одной переменной. Если это так, в коде мы можем иметь функцию типа «определитель», которая называется monadi c и ссылается на себя. Итак, я думаю, что мы предпочитаем

z.determinant()

, а определитель - это функция, объявленная внутри класса (такая же, как init ).

Теперь предположим, что у нас есть dyadi c функция типа умножения, называемая matrix_multiply. Мы можем определить это на том же уровне, что и init .

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

z = self.matrix_multiply(y)

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

z = y.matrix_multiply((x))

Наконец, можно создать функцию на некотором уровне maxtrix_multiply. Он был бы осведомлен обо всех внутренних классах, данных и методах. Затем мы можем написать:

z = matrix_multiply(x, y)

, где matrix_multiply может быть членом (методом) класса, ИЛИ это может быть отдельно стоящая подпрограмма FORTRAN; все, что нужно знать, - это как создать новую переменную путем «проникновения» в поле объекта и доступа к внутренней подпрограмме. Делая это таким образом, вы понимаете, что это не «маги c» функция в недрах класса или экземпляра класса.

Однако, чтобы работать, matrix_multiply должен хорошо знать переменные класса / экземпляра, чтобы он мог сделать свои магические действия c «вне» любого экземпляра.

Попытка обдумать все возможности - и заставить работать - истощает мой мозг. Какой общий совет в таких ситуациях?

1 Ответ

0 голосов
/ 20 апреля 2020

Я бы, вероятно, go для classmethod под названием multiply в классе Matrix. Это будет называться как z = Matrix.multiply(x, y). Это позволяет избежать любых предположений о том, что один из операндов является «более привилегированным», и сохраняет все логики c, связанные с внутренними элементами класса Matrix, внутри класса Matrix.

class Matrix:
    def __init__(self, values):
        ...

    @classmethod
    def multiply(cls, left: 'Matrix', right: 'Matrix') -> 'Matrix':
        ...
        return result

Однако это без знания какого-либо остального контекста вашего проекта / приложения. Например, это может иметь больше смысла в вашем приложении, если код выглядит как

z = x.multiply(y)

в в этом случае вы должны реализовать его как обычный метод в классе Matrix.

Наконец, если вы хотите иметь возможность писать

z = x * y

, вам необходимо реализовать __mul__ метод Matrix класса:

class Matrix:
    ...
    def __mul__(self, other: 'Matrix') -> 'Matrix':
        ...
        return result
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...