Funciones de copia situados en casos
-
22-09-2019 - |
Pregunta
Aquí hay algunos (simplificado) código de lo que estoy tratando de hacer:
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>
Cuando llamo instOfA.printSelf (), imprime auto como instOfB.
Pero quiero mismo para ser instOfA cuando llamo instOfA.printSelf (), y instOfB cuando llamo instOfB.printSelf ()
¿Cómo voy a ir haciendo esto sin definir manualmente printSelf en la clase A?
Para los que se preguntan por qué incluso me gustaría hacer algo como esto, aquí hay un ejemplo más:
#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'
Me da cuenta de que es un poco inusual, pero no podía pensar en una forma diferente de hacerlo. Estoy tratando efectivamente subclase una instancia. Se vería algo como esto si Python permitió que:
class aInstance(aDef):
inputStr = ""
Solución
Se puede utilizar el descriptor del método para obtener un método vinculado:
instOfA.printSelf = b.printSelf.__get__(instOfA)
Por supuesto, puede utilizar __class__
si no se conoce el tipo de instOfB:
instOfA.printSelf = instOfB.__class__.printSelf.__get__(instOfA)
Si instOfA
no necesita el método almacenado, puede sólo tiene que pasar en una instancia de a
como self
:
instOfB.printSelf.__func__(instOfA)
Otros consejos
El problema es que instOfB.printSelf
es un método vinculado - la variable self
está dispuesto a ser instOfB cuando se crea el objeto. Lo que haría, francamente, es sólo para configurar la función de forma ligeramente diferente:
class b:
def printSelf(self, other):
print other
A continuación, sólo tiene que hacer
instOfA = a()
instOfB = b()
instOfA.printSelf = instOfB.printSelf
instOfA.printSelf(instOfA)
Y si quieres hacer eso con instOfB:
instOfB.printSelf(instOfB)
Es un poco más feo de esa manera, pero es un poco más limpio y más evidente que la solución de Brian (que funciona muy bien también).
Editar
Una mejor forma de hacerlo es descriptores de uso (aunque esto todavía requiere la modificación del código):
class b:
@staticmethod
def printSelf(self):
print self
A pesar de que todavía tiene que incluir la instancia del objeto cuando se llama a la función.