Operator class retrieval
The actual operator class is only accessible if it's defined in the same script, or imported from another file. It's not a standard Python class however, because it is derived from the Operator type:

import bpy

class PrimitiveManipulatorOperator(bpy.types.Operator):
    bl_idname = "object.primitive_manipulator"
    bl_label = "Primitive Manipulator"

    def execute(self, context):
        return {'FINISHED'}

type(PrimitiveManipulatorOperator) # returns &lt;class 'bpy_types.OrderedMeta'&gt;


Upon class registration of an operator class, it is made available as type as bpy.types.OBJECT_OT_primitive_manipulator (which is the bl_idname transformed from Python to C notation):

def register():
    bpy.utils.register_class(PrimitiveManipulatorOperator)

    # returns &lt;class 'bpy_types.OrderedMeta'&gt;
    print(type(bpy.types.OBJECT_OT_primitive_manipulator))

    # fails, the class name isn't used in case of operators
    print(type(bpy.types.PrimitiveManipulatorOperator))


The interface to call operators is via bpy.ops:

bpy.ops.object.primitive_manipulator()

# returns &lt;class 'bpy.ops.BPyOpsSubModOp'&gt;
type(bpy.ops.object.primitive_manipulator())


What can be confusing about bpy.ops (which is &lt;class 'bpy.ops.BPyOps'&gt;), is that hasattr() will always return True:

hasattr(bpy.ops, "object.primitive_manipulator") # True
hasattr(bpy.ops, "foobar") # also True


This is caused by the design of this module-like class and presumably necessary to make proper calls work.

The correct way to programmatically get a reference to the operator for a call is to getattr() twice, as you want to retrieve a property and its sub-property:

op = getattr(getattr(bpy.ops, "object"), "primitive_manipulator")
op() # equivalent to bpy.ops.object.primitive_manipulator()


getattr(bpy.ops, "object.primitive_manipulator") can't work because there is no property "object.primitive_manipulator", there's only "object", which in turn has the property "primitive_manipulator".

&gt;&gt;&gt; type(getattr(bpy.ops, "object"))
&lt;class 'bpy.ops.BPyOpsSubMod'&gt;

&gt;&gt;&gt; type(getattr(bpy.ops, "foo.bar"))
&lt;class 'bpy.ops.BPyOpsSubMod'&gt;

&gt;&gt;&gt; type(getattr(getattr(bpy.ops, "object"), "primitive_manipulator"))
&lt;class 'bpy.ops.BPyOpsSubModOp'&gt;


You may want to resolve the operator name in a loop like this:

def get_operator(idname):
    op = bpy.ops
    for attr in idname.split("."):
        op = getattr(op, attr)
    return op

get_operator("object.primitive_operator")()

# if there's a poll() classmethod, you can also:
get_operator("object.primitive_operator.poll")()


# return a blank function to suppress AttributeErrors
# in case the operator idname does not exist
def get_operator_failsafe(idname):
    op = bpy.ops
    for attr in idname.split("."):
        if attr not in dir(op):
            return lambda: None
        op = getattr(op, attr)
    return op

get_operator_failsafe("foo.bar")()