Просмотр определения встроенных классов в Python, например в Symbol - PullRequest
1 голос
/ 10 июля 2020

Я новичок в Python (переход с Matlab) и в настоящее время работаю с пакетом SymPy. Я понял, что могу вычислить производную функции с помощью f.diff(x), даже если я не импортировал функцию diff. Итак, в основном f.diff(x) работает, но diff(f,x) возвращает ошибку.

from sympy import symbols
x = symbols('x')
f = x**2 + 1
f.diff(x)

Причина, о которой я мог подумать, заключалась в том, что diff фактически определен как атрибут метода для класса Symbol и таким образом, f.diff(x) работает, пока x имеет тип Symbol, а f был определен с помощью x. Есть ли способ каким-либо образом просмотреть определение класса Symbol, чтобы убедиться, что атрибут метода diff действительно существует?

1 Ответ

0 голосов
/ 11 июля 2020

Причина, о которой я мог подумать, заключалась в том, что diff фактически определен как атрибут метода для класса Symbol и, таким образом, f.diff(x) работает, пока x имеет тип Symbol и f был определен с использованием x.

Это в основном правильно (исправления ниже).

В отличие от Matlab, Python использует пространства имен. Это означает, что у вас есть только очень c функций, классов и т. Д. c. доступен по умолчанию, а все остальное необходимо импортировать в основное пространство имен или доступно только с «префиксом», определяющим пространство имен. Что вы получаете от этого, так это то, что вы избегаете конфликтов имен и легко отслеживать, из какого модуля поступает функция. Например, в вашем примере читатель может увидеть, что symbols был импортирован из модуля sympy (в основное пространство имен). В этом модуле также есть функция diff (а не метод), которую вы могли бы использовать после импорта с from sympy import diff.

В этом смысле каждый объект имеет собственное пространство имен, которое используется для большинства практических целей. определяется его классом¹. Функции в этом пространстве имен называются методами и (обычно) что-то делают с самим объектом или с использованием особенностей самого объекта.

Теперь, что касается обещанных исправлений или уточнений: Это * Здесь важен класс 1024 *, а не x. Вы можете увидеть класс f с type(f), и это Add (находящийся в sympy.core.add). Это потому, что это, прежде всего, сумма (x**2 и 1). Что еще более важно, Add является подклассом Expr (выражение), который является родительским классом для всех выражений SymPy. Например, класс Symbol также является подклассом Expr. (Вы можете увидеть это с помощью type(f).mro().) И это важно здесь: все выражения SymPy имеют метод diff.

Фактически не имеет значения, что аргумент f.diff является Symbol или Expr. Это должно быть только что-то, что SymPy может разумно интерпретировать как единое целое. Например, f.diff("x") также работает, потому что SymPy может преобразовать строку "x" в символ, эквивалентный вашему x.

Есть ли способ каким-либо образом просмотреть класс Symbol определение, чтобы проверить, что атрибут метода diff действительно существует?

Да. Самый простой способ - это функция basi c Python dir, которая возвращает список всех атрибутов (всего, что доступно оператору .) объекта. Обычно это методы. В таком случае можно просто позвонить по номеру dir(f). Обратите внимание, что этот список также содержит довольно много атрибутов, начинающихся с _, что означает, что они не предназначены для использования пользователем. В любой разумной среде программирования (IDE, I Python, Jupyter) этот список также отображается вам, когда вы используете завершение табуляции ( F , . , Tab ).

Однако , хотя изучение класса путем перебора всех его методов обычно является хорошим подходом, для выражений SymPy это невозможно. Есть много вещей, которые кто-то может захотеть сделать с этими выражениями, но вы всегда будете использовать только часть из них. Вместо этого вы можете угадать название метода и, таким образом, значительно сузить область поиска. Например, вы можете догадаться, что метод дифференцирования начинается с d (будь то дифференцировать или производное ), а здесь завершение табуляции ( F , . , D , Tab ) дает только четыре результата вместо трех сотен. Другой подход заключается в том, что вы начинаете поиск в документации (или Inte rnet в целом) с того, что представляет собой ваша операция (здесь дифференциация), вместо вашего объекта вашей операции (здесь, выражения SymPy, т. Е. Экземпляры Expr ). В конце концов, SymPy полностью посвящен последнему, так что это своего рода данность.

Наконец, обычно есть документация класса, в котором представлены все его методы. Для Expr это , здесь . К сожалению, в случае Expr документация не является исчерпывающей, т.е. г., в нем отсутствует метод diff. Хотя это не идеально, но это несколько понятно, учитывая количество методов, а также двойственность методов и функций SymPy: для большинства методов Expr аналогичная функция может быть напрямую импортирована из sympy.

¹ Вы также можете просто добавить туда что-нибудь (symbols.wrzlprmft = "foo"), но это довольно продвинутое и редкое использование. Также некоторые классы созданы, чтобы блокировать это, например, вы не можете делать f.wrzlprmft = "foo".

...