Funções de cópia localizadas em instâncias
-
22-09-2019 - |
Pergunta
Aqui está algum código (simplificado) para o que estou tentando fazer:
class a:
pass
class b:
def printSelf(self):
print self
instOfA = a()
instOfB = b()
instOfA.printSelf = instOfB.printSelf
instOfA.printSelf()
<__main__.b instance at 0x0295D238>
Quando eu chamo instofa.printself (), ele imprime como sendo instofb.
Mas eu quero que eu seja Instofa quando ligo para instofa.printself () e instofb quando eu chamo instofb.printself ()
Como eu faria isso sem definir manualmente a impressão na classe A?
Para aqueles que se perguntam por que eu gostaria de fazer algo assim, aqui está um exemplo mais longo:
#Acts as a template for aInstance. I would have several aInstances that have common rules, which are defined by an instance of the aDefinition class (though I'd have multiple rule sets too)
class aDefinitionClass:
def setInput(self, val):
self.inputStr = val
def checkInputByLength(self):
return len(self.inputStr) < 5
def checkInputByCase(self):
return self.inputStr == self.inputStr.upper()
checkInput = checkInputByLength
class aInstance(aDefinition):
inputStr = ""
def __init__(self, ruleDefinition):
self.checkInput = ruleDefinition.checkInput
aDef = aDefinitionClass()
aDef.checkInput = aDef.checkInputByCase #Changing one of the rules.
aInst = aInstance(aDef)
aInst.setInput("ABC")
aInst.checkInput()
AttributeError: aDefinitionClass instance has no attribute 'inputStr'
Sei que é um pouco incomum, mas não conseguia pensar em uma maneira diferente de fazê -lo. Estou efetivamente tentando subclasse uma instância. Pareceria algo assim se Python permitisse:
class aInstance(aDef):
inputStr = ""
Solução
Você pode usar o descritor do método para obter um método vinculado:
instOfA.printSelf = b.printSelf.__get__(instOfA)
Claro, você pode usar __class__
Se você não conhece o tipo de instofb:
instOfA.printSelf = instOfB.__class__.printSelf.__get__(instOfA)
Se instOfA
Não precisa do método armazenado, você pode simplesmente passar em um exemplo de a
Como self
:
instOfB.printSelf.__func__(instOfA)
Outras dicas
A questão é que instOfB.printSelf
é um Método ligado - a self
A variável está definida para ser instofb quando você cria o objeto. O que eu faria, francamente, é apenas configurar a função um pouco diferente:
class b:
def printSelf(self, other):
print other
Então você simplesmente faz
instOfA = a()
instOfB = b()
instOfA.printSelf = instOfB.printSelf
instOfA.printSelf(instOfA)
E se você quiser fazer isso com o Instofb:
instOfB.printSelf(instOfB)
É um pouco mais feio dessa maneira, mas é um pouco mais limpo e mais óbvio que a solução de Brian (o que funciona muito bem).
Editar:
Uma maneira ainda melhor é usar descritores (embora isso ainda exija modificar seu código):
class b:
@staticmethod
def printSelf(self):
print self
Embora você ainda precise incluir a instância do objeto ao chamar a função.