oh python.... this is actually my special subject but in python??!!? ... well lets have a look.
here a mel example:
global proc string getShaders(string $input)
// shaders can be attached to shapes even if not on a face!
// so get only the faces
string $faces = polyListComponentConversion("-tf",$input);
if (!size($faces)) // break if there are no faces
// now list all shadinggroups that these faces are members of
string $connectedSGs =
listSets -type 1 -object $faces;
if (!size($connectedSGs)) // break if there are no shadingGroups
// type lambert would not return shaders that
// aren't derived from lambert1, ls -materials works better
$shaders = ls("-materials",(
listConnections -s 1 -d 0 $connectedSGs));
now listHistory works well. but for example: If you select all faces of a poly object and then assign a different shader, you'd get the old shadingGroup too! Even if its not connected to any surface.
As well as the surfaceShader plug is good. Thats the common case.. but what about a volumeShader? ls -materials would get any shaders and you can parse an array! Thats the key I guess :]