c4d.Vector.__init__ does not accept named arguments



  • Hi,

    in R23 and R21 (at least on Windows) c4d.Vector.__init__() does not respect named arguments and the documentation might let you believe it would.

    Cheers,
    zipit

    """ Demonstrates that c4d.Vector.__init__ does not handle named arguments
    properly. 
    """
    
    import c4d
    
    def main():
        """
        """
        # Won't throw an argument exception, will just fail silently. 
        u = c4d.Vector(x=1, z=2)
        print (u)
        # Vector(0, 0, 0)
        
    if __name__=='__main__':
        main()
    


  • Hi @zipit thanks a lot, the issue is not really named arguments, but how we implemented internally the function.
    Previously the policy was to make Python a perfect clone of C++, and in C++ there is the concept of overload which doesn't exist in Python.
    So in C++ you can initialize a Vector with the next constructors:

    • Vector() // produce Vector(0, 0, 0)
    • Vector(0.5) // produce Vector(0.5, 0.5, 0.5)
    • Vector(0.1, 0.5, 1)

    But there is no overload for 2 arguments. And here is the cause of the issue if I can tell.
    But I completely understand the issue and the fact that the code is not really pythonic, so in this case, this is not a problem, and I will adapt the method to make it more pythonic and make x, y, z optional argument as the documentation suggested.

    Note that this issue may be present in some other area (like Matrix), I will try to look at it and fix them, but if you(the community) could also report us when something like that occurs, this would be very welcome.

    However, in some situations, we have the exact same issue but there is no easy fix because default values are not easily determinable (a good example is FieldList.DirectSample.

    Finally, the fact it didn't raise anything, this is not normal.

    Hope it answers your question,
    Cheers,
    Maxime :)



  • Hi @zipit thanks a lot, the issue is not really named arguments, but how we implemented internally the function.
    Previously the policy was to make Python a perfect clone of C++, and in C++ there is the concept of overload which doesn't exist in Python.
    So in C++ you can initialize a Vector with the next constructors:

    • Vector() // produce Vector(0, 0, 0)
    • Vector(0.5) // produce Vector(0.5, 0.5, 0.5)
    • Vector(0.1, 0.5, 1)

    But there is no overload for 2 arguments. And here is the cause of the issue if I can tell.
    But I completely understand the issue and the fact that the code is not really pythonic, so in this case, this is not a problem, and I will adapt the method to make it more pythonic and make x, y, z optional argument as the documentation suggested.

    Note that this issue may be present in some other area (like Matrix), I will try to look at it and fix them, but if you(the community) could also report us when something like that occurs, this would be very welcome.

    However, in some situations, we have the exact same issue but there is no easy fix because default values are not easily determinable (a good example is FieldList.DirectSample.

    Finally, the fact it didn't raise anything, this is not normal.

    Hope it answers your question,
    Cheers,
    Maxime :)



  • I think what zipit was referring to is that the named params do not work at all, regardless of the argument count.
    So, doing stuff like c4d.Vector(y=1,z=2,x=4) won't work as well.



  • Hi,

    I did not really expect an answer, I just did put it up to make you guys aware.

    Regarding your reply, I agree with most of it and am aware that there a some hurdles to overcome in mapping C++ interfaces to Python, i.e. that you do run into problems in general when you want to express overloaded methods in Python. But as @mp5gosu pointed out, my major point was that the function does not accept named arguments at all. Which is mainly a problem because the docs tell you explicitly otherwise in two ways. First of all the docs say explicitly that all arguments are optional which implies for Python usually that I can pick and choose in which arguments I can pass by passing named arguments. And secondly, you print out the signature as Vector.__init__(x=0.0, y=0.0, z=0.0) which implies the same.

    I would have probably ignored all this and booked it under "that's for me to know and for you to find out", if it wasn't for the fact that the method does not raise a TypeError on attempts of feeding it with such unknown named arguments. Which can make this quite critical IMHO.

    Cheers,
    zipit