Disclaimer: Nunca faça isso na real!
Python tem uma natureza funcional muito boa (não tão boa quanto linguagens funcionais, é claro), o que de certo modo faz ele similar com Javascript, utilizando closures e afins. Inclusive permite construções similares a esta abaixo:
def Pessoa(nome: str, sobrenome:str, idade:int):
def getNome():
return nome
def getSobrenome():
return sobrenome
def getNomeCompleto():
return f'{nome} {sobrenome}'
def getIdade():
return idade
return {
'getNome': getNome,
'getSobrenome': getSobrenome,
'getNomeCompleto': getNomeCompleto,
'getIdade': getIdade,
}
p = Pessoa('Jar Jar', 'Binks', 38)
print(p['getNomeCompleto'](), p['getIdade']())
Python não define um meio de criar objetos dinâmicos como Javascript, devido a sua forte tipagem, por isso usei a estrutura de dicionário. O que acontece na verdade é que devolvemos uma coleção de funções que acessam os atributos do “construtor” através de closures.
Desde o ES6/ES2015 temos como declarar classes em Javascript utilizando keywords como class, constructor, etc, o que deixa bem mais limpo e agrupado, mas tudo isso ainda é syntax suggar para a estrutura de criação de objetos que existia anteriormente.
Update:
Consegui usar as chamadas de método normalmente, porém tive que definir uma classe apenas de quebra galho (a classe Object) apenas para poder usar setattr e para isto é necessário a classe definir __dict__:
def Pessoa(nome: str, sobrenome:str, idade:int):
class Object:
pass
def getNome():
return nome
def getSobrenome():
return sobrenome
def getNomeCompleto():
return f'{nome} {sobrenome}'
def getIdade():
return idade
o = Object()
setattr(o, 'getNome', getNome)
setattr(o, 'getSobrenome', getSobrenome)
setattr(o, 'getNomeCompleto', getNomeCompleto)
setattr(o, 'getIdade', getIdade)
return o
p = Pessoa('Jar Jar', 'Binks', 38)
print(f'{p.getNomeCompleto()} - {p.getIdade()}')