Метод atoms
может быть тем, что вам нужно:
>>> (2*(x+y)).atoms(Number)
{2}
В методе replace
также есть опция отслеживания используемого отображения, но он не обрабатывает идентичные элементы, которые были заменены другими значениями
>>> (2*x + x**2).replace(lambda x:x.is_Number, lambda x: Dummy(), map=True)
(Dummy_1*x + x**Dummy_2, {2: Dummy_2})
Таким образом, может работать следующее:
>>> def flatargs(expr):
... if expr.is_Atom: yield expr
... else:
... for a in expr.args:
... for i in flatargs(a): yield i
>>> list(flatargs(2*x+x**2))
[x, 2, 2, x]
>>> from sympy.utilities.iterables import multiset
>>> multiset([i for i in flatargs(2*x+x**2+y/2) if i.is_Number)
{1/2: 1, 2: 2}
Если вы хотите, чтобы числитель и знаменатель были отдельно от flatargs
, вам бы пришлось обрабатывать атом Rational как особый рассматривайте случаи, когда числитель или деноминатор равен 1. Но, надеюсь, то, что здесь, поможет вам в этом.