Take the 2-minute tour ×
Blender Stack Exchange is a question and answer site for people who use Blender to create 3D graphics, animations, or games. It's 100% free, no registration required.

What is the proper way to test the identity of two objects?

Usually I do this:

if ob1 == ob2:

Or if the references have become outdated, it may be safer to hold onto names and see if they still exist:

objects = bpy.data.objects
ob_a = objects.get(name_a)
if ob_a is not None:
    ob_b = objects.get(name_b)
    if ob_a == ob_b:
        # found a match!

In Python, you're taught that equality is not the same as identity. Theoretically, there can be two indistinguishable Blender objects. So what I'd really like to do is test identity:

if ob1 is ob2:

However, in the Blender console:

C.object is C.object

returns False! Why is this so, and what is the recommended way for determining the identity of two objects?

share|improve this question
    
What do you mean by "the pointers have become outdated"? Python doesn't have pointers. –  CharlesL Jan 3 at 0:27
1  
Well, it actually kind of does, but I changed the wording to "references", since that's usually what they are called in Python instead of "pointers". –  supergra Jan 3 at 0:31
    
There is a distinction between the two, of course, but from a high-level they work the same way. In Blender, the reference to an object can become invalid. For example, if you delete the object, while holding on to a reference to it. –  supergra Jan 3 at 0:37
    
If the reference is out-dated its not safer to do if ob1.name == ob2.name, since this is reading from the reference (rather then just comparing it). –  ideasman42 Jan 3 at 1:28
1  
@CharlesL Python doesn't have native Pointers (unless you count ctypes), but internally (in the Py-C-API), pointers are used, ideally script authors wouldn't have to care about this but there are exceptions to that. –  ideasman42 Jan 3 at 1:32

2 Answers 2

up vote 6 down vote accepted

In short, for the bpy api use ==, instead of is or comparing the name (which is error prone).

Blender data-blocks * happen not to be Python objects, that is to say, when Blender creates a mesh for example, there exists no Python object for it, until a script asks for one, The way the Python API works, each data-block is a reference to Blender data. therefor id(bpy.context.object) == id(bpy.context.object) won't be equal since each time a new python-object is created.

Note:

This is not the case for all areas of Blender, The game-engine (bge) and the bmesh api's can use identity for comparisons.

Note:

If you do want a unique id() for a data-block you can do:
ob1.as_pointer() == ob2.as_pointer(), this is specific to the bpy api.

* In Blender data-block is a general term for a scene, group, mesh, image, material, texture... etc, (avoiding the term object since its confusing in this context)

share|improve this answer
    
I see in the API that as_pointer() returns an integer. So this can be used to compare datablocks even after they are deleted? (Not saying that would be a good idea...) –  supergra Jan 3 at 1:55
    
Furthermore, it looks like you could then be more Pythonic and write: ob1.as_pointer() is ob2.as_pointer(), recovering the is syntax. –  supergra Jan 3 at 1:55
    
And is it possible that a datablock will maintain its content, but have its memory location shifted? (In other words can the value returned by as_pointer() become stale, despite the datablock still existing?) –  supergra Jan 3 at 2:07
    
Strictly speaking you shouldn't use as_pointer() on a data-block that's been freed, Since its possible a newly allocated object has the same address, In general its best do avoid holding references to objects for extended periods where you aren't sure if they are removed or not on future access. –  ideasman42 Jan 3 at 6:45

In (C)Python, the is operator is based on id(), which returns the memory address of a python object. For some reason, calling id(bpy.context.active_object) consecutively does not return the same value. I assume this is an implementation detail(or bug) of the Blender Python API.

Without id() working as expected, you can't use is for comparison. But == works just fine from my quick testing.

You are right that using obj.name to compare object is not ideal. Use BlenderObject == BlenderObject when possible.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.