4

How can I find a list of all **args of a function?

For example, I know that symbols() take positive=True, real=True, etc. as arguments, and I would like to see a full list of these possible arguments. However, they're not listed in the Sympy Core doc page.

And I've dug through the source code itself, but I can't trace and locate what I'm looking for.

Mogsdad
  • 44,709
  • 21
  • 151
  • 275
saintsfan342000
  • 1,724
  • 1
  • 13
  • 16
  • Just wondered whether the answers here have helped you, or if you need more detail in any particular aspect? – J Richard Snape Aug 14 '15 at 13:01
  • Yes sir. Sounds like the Assumptions Module is the place to look. And I especially appreciate the code walk! Very instructive. It's easy for me to say this from my seat on the sidelines, but it would be nice to have this documented in the doc page. – saintsfan342000 Aug 14 '15 at 17:59
  • Excellent - glad it helped. If you feel an answer has solved the issue, please do [accept it.](http://stackoverflow.com/help/someone-answers) I agree the docs could be more explicit in saying "this is a complete list of all the possible arguments you can pass in" – J Richard Snape Aug 14 '15 at 22:28

4 Answers4

4

symbols() function

As other answers have noted - one use of **args in the symbols is to pass in Assumptions about the Symbol being created. The list of assumptions you can pass is documented under the Assumptions page as supported predicates.

However, you should also note that some other special named arguments can be passed in.

These are both documented in the section that you link and are:

  1. cls=<ClassName>

    Despite its name, symbols() can create symbol-like objects like instances of Function or Wild classes. To achieve this, set cls keyword argument to the desired type:

    N.B. If not specified, the default Symbol class is used.

  2. seq=<True|False>

    The docs say:

    If an iterable container is needed for a single symbol, set the seq argument to True or terminate the symbol name with a comma

Code walk

You note that you've looked through the code - so I'll show you where these are implemented in the code. If you call the symbols() function, it does various checks of its arguments, including pop-ing cls and seq arguments from **args it then performs more checks etc, before finally calling through to instantiate the Symbol here, here or here. These call the constructor of Symbol (or its subclass passed in via cls) with whatever is left in **args which are all interpreted as assumptions in the constructor. - they are sanitized here i.e. non-assumption or non-applicable named arguments are thrown out at this point!

This shows that Assumptions + cls + seq form the set of named arguments that can be passed in **args to symbols()


Other functions (general case)

It occurs to me that symbols() may have simply served as a representative example of a more general question. I hope the above has convinced you that all the values that can be usefully passed into symbols() are documented. This may give you some confidence that the same is true for other functions within SymPy.

However, in the general case, the answer is that it is rather hard to prove to yourself that all the values that can be passed in as keywordarguments are in the documentation of any library or function. Indeed, sometimes only a subset are documented deliberately as they are the "public API" for the library whereas the actual code may take other arguments, but for some reason the developer doesn't want to expose them to the public - e.g. because their availability may change, or their functionality is untested.

If you do pass in invalid arguments, the behaviour of the library you are using may differ. Some libraries or functions will ignore them, while others will throw errors if you pass in invalid keyword arguments.

If you want to find out whether that's the case (and the library is open source, like SymPy), then you can always dive through the code (as I show in the Code Walk above). If you do that - you need to follow the path of execution, looking for occurences of args.pop(). If there are other functions in SymPy that you are concerned about let me know in comments - but hopefully this general method will work for you.

I'm assuming in the above that you understand the *args and **args syntax. If that's not totally clear for you - this section of the python official tutorial deals with it.

J Richard Snape
  • 20,116
  • 5
  • 51
  • 79
  • @Dietrich as you're the one putting up the bounty, I wondered if you were more interested in the specific `symbols()` function, or whether there is something else you wanted that I might be able to help with? – J Richard Snape Aug 14 '15 at 13:00
  • Many thanks for the comprehensive answer. The link to the Assumptions page is really helpful. As a casual Sympy user (trying to be less addicted to Mathematica), I have problems remembering those parameters, especially since they are not checked for validity: E.g., `symbols('x', pos=True)` does not raise a Error (which is not a nice bug to find in one's code). – Dietrich Aug 15 '15 at 09:46
  • Thanks for the comment and bounty. i agree - those kinds of errors are horrible. I don't really like the way SymPy ignores unsupported names by just [popping them and ignoring here](https://github.com/sympy/sympy/blob/sympy-0.7.6/sympy/core/symbol.py#L86). It's not a bug as such, but it does make the exmple you give really horrible to debug. – J Richard Snape Aug 15 '15 at 18:52
3

These arguments are named assumptions and can be found in the documentation: Sympy Assumptions

rfkortekaas
  • 6,049
  • 2
  • 27
  • 34
3

Classification of assumptions

  • related with symbols for simplification, e.g. Q.positive, Q.even.
  • related with algebraic fields/rings, e.g. Q.real, Q.complex.
  • related with some facts, e.g. .is_bounded, is_infinity, is_zero and so on. They are help us to operate with calculation in core. Apparently they are derived from the above other classes of assumptions (while start-upping of the objects) (in this case e.g. is_zero is means that it is a Zero for the ring). Or they can be derived from expression's analyze: in this case we can create some class of assumption that are calculated (in this case is_zero can be means but it this sort of calculation is a difficult so called "zero test" problem). In any case we can realize in mind with what we deal exactly (now in the core somewhere we used is_zero in second sense).

Assumptions Examples :

M ... Mathematica
S0 ... SymPy, current approach
S1 .... SymPy, approach 1
S2 .... SymPy, approach 2

M: Simplify[1/Sqrt[x] - Sqrt[1/x], x > 0]
S1: x = Symbol('x', assumptions=IsPositive)
  simplify(1/sqrt(x) - sqrt(1/x))
S2: simplify(1/sqrt(x) - sqrt(1/x), Assumptions(x>0))

M: FunctionExpand[Log[x y], x > 0 && y > 0]
S1: x, y = Symbol('x', assumptions=IsPositive), Symbol('y', assumptions=IsPositive)
 log(x*y).expand()
S2: log(x*y).expand(Assumptions([x>0, y>0]))

M: Simplify[Sin[n Pi], n \[Element] Integers]
S1: n = Symbol('n', assumptions=IsInteger)
  simplify(sin(n*pi))
S2: simplify(sin(n*pi), Assumptions(Element(n, Integer)))

# we can talk about the syntax of Element(n, Integer)

M: FunctionExpand[EulerPhi[m n], {m, n} \[Element] Integers && GCD[m, n] == 1]
S1: n = Symbol('n', assumptions=IsInteger)
  m = Symbol('m', assumptions=IsInteger)
  n.assumptions.add(Eq(gcd(m, n) - 1))
  euler_phi(m, n)
S2: euler_phi(m, n).expand(Assumptions([Element(n, Integer), Element(m, Integer), Eq(gcd(m, n) - 1)]))

# again we can talk about the syntax of Element(n, Integer)

M: RealQ[x, x \[Element] Real]
S0: x = Symbol('x',real=True, integer=True)
  assert x.is_real == True
S1:
S2: assert IsElement(x, Real, assumptions=Element(x, Real))

M: Refine[Abs[x], x>0]
   Refine[Abs[x], x0))
  print e.refine(Assumptions(x))

More References :

Wiki Sympi Assumptions

Assuming

Setting Assumptions on Variables in Sympy Relative to Other Variables

Using SymPy's New Assumptions

Community
  • 1
  • 1
Tharif
  • 13,794
  • 9
  • 55
  • 77
1

You can get the argument details from any function using a built-in python library called inspect:

import inspect
inspect.getargspec(funcname)

It will return an ArgSpec named tuple with some information such as:

ArgSpec(args=['myarg'], varargs=None, keywords=None, defaults=(None,))

To get the argument names you can simply access the args attribute of that returned object.

samuraisam
  • 1,927
  • 1
  • 20
  • 24
  • 1
    Whilst this would work for named arguments - it is not applicable here where the OP is looking for a list of keyword arguments that are valid when passed in the `**args dict`. You can test this by importing `sympy` and doing `inspect.getargspec(sympy.symbols)`. You get `ArgSpec(args=['names'], varargs=None, keywords='args', defaults=None)`, not a list of all values that can be passed in `args` – J Richard Snape Aug 12 '15 at 06:56