Property access instead of getters/setters

This question comes up a fair bit, and a number of users are very interested in this.

There’s the possibility of adding a property interface where getters/setters are currently used. This would change the interface from:

x = node.get_transform().get_pos().get_x()
text.set_slant(text.get_slant() + 0.1)

if base.win.get_gsg().get_supports_shadow_filter():
    texture.set_minfilter(SamplerState.FT_shadow)

To:

x = node.transform.pos.x
text.slant += 0.1

if base.win.gsg.supports_shadow_filter:
    texture.minfilter = SamplerState.FT_shadow

Thoughts? I’m willing to experiment with this and add properties as an alternative way, and eventually (Panda 2.0?) even phase out the getters and setters entirely in favour of a property-only interface.

There are some important examples where we can’t eliminate a getter/setter-like interface, such as NodePath, since methods like get_pos and set_pos do much more complicated things than setting a simple attribute on the class, and we can’t reduce this functionality down to a simple property-like interface.

There’s also the question of whether we should have camelCase alternative names for properties, the same way we support both getTransform() and get_transform(). I’m tempted to just have snake_case properties so that we can more easily phase out the camelCase() methods in the future, but I’m willing to yield if there is enough clamour for camelCase properties.

I wanted to say “Yay! Shorter code”, but I’m not 100% sure if it really is such a good thing.
If I can do

x = node.transform.pos.x

Then can I also do

x = node.transform.pos.x
x+=1 #??

and expect a change in position?

Someone might be also tempted to ‘enable’ shadow filtering by doing:

base.win.gsg.supports_shadow_filter=True

I think it might be confusing for some new users, especially if we have 3 ways of doing something x=spam.egg, x=spam.get_egg() and x=spam.getEgg(), but on the other side … Yay! Shorter code!

As for the camelCase… I kind of like them, but I’m dyslectic and sometimes I can mistake a “.” for a “_” or vice versa, with camelCase it’s less likely to make a mistake like that, but I also keep writing “elf” instead of “self” so I’ll always find some way of making errors. I won’t cry (much) if cameCase goes away :wink:

I don’t think, as far as I understood the change, there would be a set_x and get_x , with get_x you get a PyDouble (?), which is not related to the internal handle stored by the transform I believe.

I guess the goal would be to have only way, like only supporting lower_case and properties.

If you try to assign gsg.supports_xyz, a read-only property, you will get:

>>> base.win.gsg.supports_glsl = True
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: attribute 'supports_glsl' of 'panda3d.core.GraphicsStateGuardian' objects is not writable

One can argue that someone might be tempted to write set_supports_glsl(True) for the same reason why he would be tempted to assign it as a property.

You can’t do your “x += 1” trick in any Python class either, since floats are immutable. But if you did something like .transform.pos += (1, 0, 0), then you would get a similar error. But we could theoretically support this case in the future.

As for it being confusing for new users: perhaps we can add it, but not document it until we’re confident we can consistently recommend the new style, and then recommend the new style (properties + snake_case) across the board in a future release).

I’m massively in favor of this. It may not be obvious to people who are primarily C++ coders, but Panda3D syntax often feels antiquated and crufty to me. I honestly can’t remember the last time I used another library that used getter and setter functions.

Edit: Not to be critical! Panda3D is awesome. I’m just hoping it continues to embody “pythonic” practices, like these properties.

A great many Panda3D classes have been extended with properties in the latest dev build. Even more is coming. I intend not to advertise this feature yet or use it in the manual or sample code, though, at least not until we’re ready to recommend the new style across the board. A future Panda 2 release might be a good opportunity to remove the old getters and setters, along with the camel case interfaces.

Cases where there is a has_x() and clear_x() method have been implemented by making the property None if has_x() returns False and calling clear_x() when assigning None to the property.

can this be made backward compatible? if getter/setters are removed, older code can’t be used anymore?
and is there any difference in performance/overhead?

Yes, I think you may have misunderstood - there is no intention to break existing code in the foreseeable future.

Yes, properties are 150% as fast as getters/setters.

I just added “sequence properties”, which replace methods like:

node.get_num_children()
node.get_child(i)
node.set_child(i, node2)
node.remove_child(i)

with:

len(node.children)
node.children[i]
node.children[i] = node2
del node.children[i]

Up next: map properties, so you will be able to do node.python_tags[“something”] = “else”.

1 Like