In Python you're describing a Protocol. It's actually super reasonable to have a ObjectWithFirstNameAndLastName noun like this. You don't ever need to construct one but you can use it in the type slot and objects you pass in will be checked to conform. You see all kinds of weird specific types floating around the standard lib like this for type hinting.
Duck typing is great, what's even better is documenting when when they need to quack or waddle.
I think protocols have two major drawbacks regarding readability and safety. When I have a protocol, I cannot easily find its concrete implementations, so it becomes harder to see what the code is actually doing. As for safety, protocols have no way of distinguishing between
class Command:
def execute(self) -> None:
# some implementation
and
class Prisoner:
def execute(self) -> None:
# some other implementation
The implementor of the Prisoner class might not want the Prisoner class to be able to be slotted in where the Command class can be slotted in. Your type checker will be of no help here. If you use abstract base classes, your type checker can prevent such mistakes.
So when it comes to your own code, the drawbacks of the structural Protocols in comparison the nominal ABCs are pretty big. The pros seem non-existent. The pro, I guess, is that you don't have to type the handful of characters "(Baseclass)" with every concrete implementation.
But they do have one major advantage: if you have third party code that you have no control over, and you have some part of this codebase that you want to replace with your own, and there's no convenient way to do something like the adapter pattern, because it's somehow a bit deeply nested then a Protocol is a great solution.
Duck typing is great, what's even better is documenting when when they need to quack or waddle.