Vertex Parenting
Among other ways can be done with vertex parenting.
Test script, run with mesh in edit mode, adds a vertex parented empty for each selected vert and prints vertex's global location to the console.
import bpy
import bmesh
context = bpy.context
scene = context.scene
obj = context.edit_object
mesh = obj.data
bm = bmesh.from_edit_mesh(mesh)
empties = []
# selected verts
for v in [v for v in bm.verts if v.select]:
empty = bpy.data.objects.new("Empty", None)
empty.parent = obj
empty.parent_type = 'VERTEX'
empty.parent_vertices = [v.index] * 3
scene.objects.link(empty)
empty.matrix_parent_inverse.identity()
empties.append((v.index, empty))
# update the scene
scene.update()
for index, empty in empties:
print("Vert %d location: " % index, empty.matrix_world.to_translation())
scene.objects.unlink(empty)
bpy.data.objects.remove(empty)
Test result on default cube with subsurf (cat-clark) 3 subdivisions.
Vert 0 location: <Vector (0.5015, 0.5015, -0.5015)>
Vert 1 location: <Vector (0.5015, -0.5015, -0.5015)>
Vert 2 location: <Vector (-0.5015, -0.5015, -0.5015)>
Vert 3 location: <Vector (-0.5015, 0.5015, -0.5015)>
Vert 4 location: <Vector (0.5015, 0.5015, 0.5015)>
Vert 5 location: <Vector (0.5015, -0.5015, 0.5015)>
Vert 6 location: <Vector (-0.5015, -0.5015, 0.5015)>
Vert 7 location: <Vector (-0.5015, 0.5015, 0.5015)>