Sympy get Symbol name

I can get the name of an "undefined" symbol:

import sympy as sym
knodef = sym.Symbol('k_{nodef}')
print(type(knodef))
sym.pprint(knodef.name)
    
<class 'sympy.core.symbol.Symbol'>
k_{nodef}

But as soon as I define it as an expression, I cannot get the name anymore.

kdef = sym.Symbol('k_{def}')
kdef = sym.tan(b*x)
print(type(kdef))
sym.pprint(kdef.name)      # AttributeError: 'tan' object has no attribute 'name'

tan
<Error raised>

How can I get the name of kdef?

Similarly for functions...

knodef2 = sym.Function('k_{nodef2}')
#display(disp.Math(knodef2.name), type(knodef2))
print(type(knodef2))
sym.pprint(knodef2.name)

<class 'sympy.core.function.UndefinedFunction'>
k_{nodef2}

... (is there in this case an equivalent to defining the Symbol)?

Upvotes: 4

Views: 4231

Answers (2)

Answer based on comments by hpaulj and ulterior experimentation and learning...

Assigning kdef = sym.Symbol('k_{def}') assigns the name 'k_{def}', because that is an attribute of class sym.Symbol.

Later assigning kdef = sym.tan(b*x) simply defines a new object of class sym.tan, and uses kdef as a variable for it, but it actually has nothing to do with the previous object. So at this point, there is no more association between kdef and 'k_{def}'.

This is easily seen with:

kdef = sym.Symbol('k_{def}')
print('kdef = ', kdef, ', address = ', hex(id(kdef)), sep='')
kdef = sym.tan(b*x)
print('kdef = ', kdef, ', address = ', hex(id(kdef)), sep='')

kdef = k_{def}, address = 0x20f21b58228
kdef = tan(b*x), address = 0x20f21b584f8

This even happens with assignments to the same type, where in principle the same exact memory block could be used:

q = 2.1
print('q = ', q, ', address = ', hex(id(q)), sep='')
q = 30000.1
print('q = ', q, ', address = ', hex(id(q)), sep='')

q = 2.1, address = 0x1c4dbd5d0d0
q = 30000.1, address = 0x1c4dbd5d2b0

Besides, it also turns out that class sym.tan has no name, so it is not possible to get it because it does not exist. Since a given variable may or may not have a name, one could simply try/expect, or inquire with dir().

Upvotes: 1

smichr
smichr

Reputation: 19115

As you demonstrate, the name attribute of Symbol and Function can be used to return a string form of the "name". For UndefinedFunction you can use .func.name to get that string, but for defined FunctionClass you can just use str on the func attribute:

>>> s=Symbol('s');f=Function('f');a=f(s);b=tan(s)
>>> s.name
's'
>>> f.name
'f'
>>> a.func.name
'f'
>>> str(b.func)
'tan'

Upvotes: 6

Related Questions