Call by reference

Hi!
Some functions like TF1.GetRange need call-by-reference to return more than one value at a time.
Is there a way that this can be done via PyROOT, considering that Python does only support call-by-value AFAIK?

Cheers,
Michael

1 Like

Michael,

[congrats to first post in the new ‘PyROOT’ section :smiley: ]

limited support for pass by reference of builtin types made it into 5.02. It is better for the upcoming release (some fixes for overloads float& vs double&), but TF1::GetRange() should be ok.

There is, however, a very important caveat: since in python there is no such thing as “pass by reference” there are some aliasing pbs: python will recycle numeric objects if they represent the same value. I.e., if you pass a number by reference, and an equivalent number already exists (locally, that is), both objects will change. Example:

[code]>>> x, y = 0.1, 0.1

gRandom.Rannor( x, y )
print x, y
-1.79938935851 -1.79938935851
x, y = 0.1, 0.2
gRandom.Rannor( x, y )
1.20281322884 0.915717379223
[/code]

Also, always make sure that the type matches (e.g. x = 123 can’t be passed through a double&).

HTH,
Wim

Hi all
Is there a way to use the method TGraph::GetPoint((Int_t i, Double_t& x, Double_t& y) and similar methods with the & with PyRoot?

Cheers Angi

Hi,

yes, but only up to an extent, b/c the python objects need to carry the exact same underlying C-type as is passed by reference. There are two such objects, python int and float (i.e. C long and double) that conform. However, to prevent confusion on the python side where interactively number objects tend to get recycled (i.e. an object representing a number can be used in multiple places, so if the C++ reference changes it, it would change in those other python calculations as well, which can’t have been the intention), two types were added that derive from the python numeric types. That way, they can’t get recycled.

So, the types are ROOT.Long and ROOT.Double which pass through long& and double&. Something like:d1, d2 = ROOT.Long(0), ROOT.Long(0) myGraph.GetPoint( 41, d1, d2 )should do the trick.

Since these types derive from python int and float, they can drop in any place where those are used, or you can simply use int() or float() to convert to the “builtin” types.

Cheers,
Wim

Hi thanks for your suggestion, but this does not work unfortunately for me. I get the following error:

d2 = ROOT.Long(0)
Traceback (most recent call last):
File “”, line 1, in
AttributeError: type object ‘ROOT’ has no attribute ‘Long’

Do you have any idea what I am missing?
Cheers Angi

Hi,

which version of ROOT are you using, or is it that you did “from ROOT import *” rather than “import ROOT”?

Cheers,
Wim

Hi I am using 5.18/00
And yes I use from ROOT import *, what is wrong with that?
Cheers Angi

Angi,

there are two “ROOT” namespaces. One is the PyROOT python module, where Long lives (so ROOT.Long works), the other is the ROOT C++ namespace, which does not contain Long.

Thus, if you use “import ROOT”, the type to use is “ROOT.Long” but if you use “from ROOT import *” then the type to use is just “Long”.

HTH,
Wim