You're getting a lot of conceptual definitions, but mechanically, it's just:
keeping state (data) and behavior (functions) that operate on that state, together
At minimum, that's it. All the other things (encapsulation, message passing, inheritance, etc) are for solidifying that concept further or for extending the paradigm with features.
For example, you can express OOP semantics without OOP syntax:
foo_dict.add(key, val) # OOP syntax
dict_add(foo_dict, key, val) # OOP semantics