Im using `web3.py 6.0.0` with code:
 

    import os
    import json
    from pathlib import Path
    from web3 import Web3
    import time
    from dotenv import load_dotenv
    
    load_dotenv()
    
    class SmartContractInterface:
        def __init__(self, nft_contract_address: str, owner_address: str, http_provider: str, type_of_nft: str):
            self.w3Provider = Web3(Web3.HTTPProvider(http_provider))
            self.nft_contract_address = nft_contract_address
            self.owner_address = owner_address
            self.base_dir = Path(__file__).resolve().parent.parent.parent
            self.abi_path = os.path.join(self.base_dir, f"backend/utils/contract_abi/{type_of_nft}.json")
            with open(
                self.abi_path            
            ) as f:
                nftAbiJson = json.load(f)
                self.nftAbi = nftAbiJson["abi"]    
            self.nft_contract = self.w3Provider.eth.contract(address=self.nft_contract_address, abi=self.nftAbi)        
        
        def transferNftFromCustodialWallet(self, user_address: str, number_of_nft: str) -> str:
            """ Transfer NFT from custodial wallet to user Ethereum address"""
            try:
                event_filter = self.nft_contract.events["Transfer"].create_filter(
                    fromBlock="latest"
                )

                ###### THIS FEW LINES ARE RELEVENT FOR THIS QUESTION ########
                self.nft_contract.functions.transferFrom(self.owner_address, user_address,int(number_of_nft)).transact(
                    {"from": self.owner_address}
                )
                ###########################################################

                events = event_filter.get_new_entries()
                for event in events:
                    if event["event"] == "Transfer":
                        return (True, event) 
                    else:
                        return (False)
            except Exception as e:
                return e

Where for `owner address` I use eth address of NFT token owner who have rights to make this transfer. 

But now I'm puzzled how web3.py know which private keys he should use to sign this transaction just by knowing public address? From where does he gets this private keys? 

It looks like some web3.py magic is involved under the hood? I don`t have other explanation...Some ideas?