.data.vertices returns an empty collection in Edit Mode
A &quot;snap shot&quot; copy.
When entering edit mode, blender takes  a &quot;snap-shot&quot; object mode copy of the mesh.  (Differs from accepted answer, as AFAIK this is not a bmesh)  Any referencing of the mesh while in edit mode will be values of the copy.  The edit mode manipulated mesh is written back to the mesh when exiting edit mode, or via Object.update_from_editmode()
The question code is adding a new object entering edit mode via the operators enter_edit_mode property, in which case it reports the 0 verts.. of a new mesh object with no geometry.
Had we added the plane primitive in object mode, then toggled into edit mode and subdivided would report 4 verts (the unsubdivided plane pre edit mode)
updating the mesh from edit mode, eg inserting this line
obj = bpy.context.active_object
obj.update_from_editmode()
print( str(obj.data  ) + &quot; vertices=&quot; + str( obj.data.vertices ) )    

would update the mesh and print 196 vertices.
Avoid edit mode.
In many cases can avoid edit mode completely.
My rule of thumb would be, if there is no need for the user input to select specific geometry there is probably no need to bother with the mind numbing overhead of numerous &amp; repetitive bpy.ops.mesh... calls.
Avoid unnecessary operations.
A 12x12 cut subdivided plane is a 14x14 grid
&gt;&gt;&gt; bpy.ops.mesh.primitive_grid_add(
...         x_subdivisions=14, 
...         y_subdivisions=14,
...         )
{'FINISHED'}

&gt;&gt;&gt; len(C.object.data.vertices)
196

instantly replacing all code in question.
Use bmesh.
If edit mode selection is required would recommend the use of a bound edit mode bmesh, bound in that it is tied to the edit mode mesh and any changes to selection or geometry  via bpy.ops.mesh... are instantly reflected by the bmesh data.
Have answered numerous questions and titled them bmesh script, so in no particular order  https://blender.stackexchange.com/search?q=user%3A15543+bmesh+script