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 = ""
¿Fue útil?

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.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top