Since Vyper has no inheritance, code reuse within a contract happens through `@internal` helper functions rather than base contracts. This keeps every contract self-contained and readable without following a chain of `is` relationships.
@internal
def _safe_transfer(token: address, to: address, amount: uint256):
success: bool = ERC20(token).transfer(to, amount)
assert success, "transfer failed"
@external
def payout(token: address, to: address, amount: uint256):
self._safe_transfer(token, to, amount)Internal functions can call other internal functions, take any type Vyper supports, and are inlined-away at the bytecode level with no runtime dispatch overhead compared to an external call.