"Initializer list" for std.vector

Hi, I’m wondering if it’s possible to initialize a ROOT.std.vector(ROOT.Double) with values from a Python collection in one line.

Currently, one has to do something like this:

v = ROOT.std.vector(ROOT.Double)()
[v.push_back(x) for x in [5,6,7,8]]

Is there a way to do what I mean here?:

v = ROOT.std.vector(ROOT.Double)([5,6,7,8])

Even if it’s a workaround with array.array(‘d’,[5,6,7,8]) or something, it’d be nice to be able to create std.vectors on-the-fly and as temporaries in function calls.

Jean-François

Hi,

I have asked Wim for help…

Axel.

Hi,

of course it’s possible. :slight_smile: You can replace init of vector, after all, to do the push_back. Note that similar is already done for +=. This works:[code]>>> from ROOT import std

v = std.vector(‘float’)()
v += [4,5,6,7]
print list(v)
[4.0, 5.0, 6.0, 7.0]

[/code]
The more general question of initializer list is something that I haven’t looked into yet. It will depend on what the representation on the Cling side is. Looks like (from the init doc string): vector<float>::vector<float>(initializer_list<vector<float>::value_type> __l, const vector<float>::allocator_type& __a)so looks doable if I can actually create an object of type initializer_list.

Actually, continuing this thread of thought, I find why I love cling soo much:[code]>>> help(std.initializer_list(‘float’).init)
Help on method init in module ROOT:

init(self, *args) unbound cppyy.initializer_list method
initializer_list::initializer_list()
initializer_list::initializer_list(const initializer_list&)
initializer_list::initializer_list(initializer_list&&)[/code]Ah, just like that. :slight_smile:

But iow., no: in fact, the only useful constructor of an initializer_list is private and can only be called by the compiler, so the ticket will likely be to generate a C++ helper.

Will look into that once I have time again.

Aside, it’s a long-standing TODO to allow Python list where std::vector is expected for (temporary) function arguments.

Cheers,
Wim

Strange that you can do

v = ROOT.std.vector(ROOT.Double)()
v += [5,6,7,8]

but not

v = ROOT.std.vector(ROOT.Double)() + [5,6,7,8]

When you say replace the init method of vector, you mean like monkey-patching on a new init function? I never thought of doing that.

I’m glad stuff is in the works. If it proves difficult to allow python lists where ROOT expects vectors or arrays, it’s probably easier to use python array.array objects, since those are fixed-type and contiguous in memory, afaik.

Jean-François

Jean-François,

is b/c only iadd has been added to take a list, not add. And yes, I meant monkey-patching. Is no different then for iadd, see in cppyy.py:[code] result = _backend.MakeRootTemplateClass( *newargs )

   # special case pythonization (builtin_map is not available from the C-API)
     if hasattr( result, 'push_back' ):
        def iadd( self, ll ):
           [ self.push_back(x) for x in ll ]
           return self

        result.__iadd__ = iadd[/code]

array.array need not be contiguous (but that can be checked at run-time). Even so, it matters not: values still need to be copied over into the temporary std::vector. What is saved, of course, is the unpacking of PyObjects (and their checking).

Cheers,
Wim