функции копирования, расположенные в экземплярах - PullRequest
2 голосов
/ 25 января 2010

Вот некоторый (упрощенный) код для того, что я пытаюсь сделать:

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>

Когда я вызываю instOfA.printSelf (), он печатает self как instOfB.
Но я хочу, чтобы self было instOfA, когда я вызываю instOfA.printSelf (), и instOfB, когда я вызываю instOfB.printSelf ()
Как мне поступить так, не определяя вручную printSelf в классе a?

Для тех, кто интересуется, почему я бы даже хотел сделать что-то подобное, вот более длинный пример:

#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'

Я понимаю, что это немного необычно, но я не мог придумать другой способ сделать это. Я эффективно пытаюсь создать подкласс экземпляра. Это выглядело бы примерно так, если бы Python это разрешил:

class aInstance(aDef):
    inputStr = ""

Ответы [ 2 ]

2 голосов
/ 25 января 2010

Вы можете использовать дескриптор метода, чтобы получить связанный метод:

instOfA.printSelf = b.printSelf.__get__(instOfA)

Конечно, вы можете использовать __class__, если вы не знаете тип instOfB:

instOfA.printSelf = instOfB.__class__.printSelf.__get__(instOfA)

Если instOfA не требует сохраненного метода, вы можете просто передать экземпляр a как self:

instOfB.printSelf.__func__(instOfA)
0 голосов
/ 25 января 2010

Проблема в том, что instOfB.printSelf - это связанный метод - переменная self устанавливается как instOfB при создании объекта. Честно говоря, я бы просто настроил функцию немного по-другому:

class b:
    def printSelf(self, other):
        print other

Тогда вы просто делаете

instOfA = a()
instOfB = b()
instOfA.printSelf = instOfB.printSelf
instOfA.printSelf(instOfA)

И если вы хотите сделать это с instOfB:

instOfB.printSelf(instOfB)

Это немного уродливее, но немного чище и очевиднее, чем решение Брайана (которое также отлично работает).

Edit:

Еще лучший способ - использовать дескрипторы (хотя для этого все еще требуется изменить код):

class b:
    @staticmethod
    def printSelf(self):
        print self

Хотя вам все равно нужно включать экземпляр объекта при вызове функции.

...