类示例的功能

时间:2010-08-09 20:52:08

标签: python

我的python代码中有类似的东西

class A:
  __mess = "Yeap!"
  def doSome(self):
    self.FN()
  def FN(self):
    pass

def myFN(self):
  print self.__mess

b = A()
b.FN = myFN
b.doSome()

但这不起作用。我哪里错了?

python 2.6.5

upd:我想仅为一个示例(b)重新定义方法(FN)。

UPD2:

import new
class A:
  __mess = "Yeap!"
  def doSome(self):
    self.FN()
  def FN(self):
    pass

def myFN(self):
  print self.__mess

b = A()
b.FN = new.instancemethod(myFN, b, A)
b.doSome()

也行不通。

  

追踪(最近的呼叫最后):
  文件“”,第1行,在中   doSome中的文件“”,第4行   myFN中的文件“”,第2行   AttributeError:实例没有   属性'__mess'

2 个答案:

答案 0 :(得分:4)

myLoopFN是一个函数,而不是实例方法。做

import new
b.loopFN = new.instancemethod( myLoopFN, b, A )

问题在于Python将实例方法与常规函数略有不同:它们将运行它们的实例作为默认的第一个参数。如果在类定义中定义一个方法,它会自动成为一个实例方法,这样当你实例化它时,它就会传递实例。但是,当您定义myLoopFN时,之外的类定义中,因此它是普通函数而不是实例方法。您可以通过将其明确声明为实例方法来解决此问题。

...

BUT

这很icky因为不是你应该做的事;在运行时更改实例方法将导致问题。您永远不会确定您的A是原始A还是已修改的loopFN,并且您将无法调试它,因为您无法判断您是否已更改{{1} }} 或不。这会给你Nyarlathotep自己会引以为豪的那种错误。

执行此操作的正确方法是子类A并覆盖该方法,以便您可以区分不同的类。

class myA( A ):
    def loopFN(self):
        #put modified function here

这样,您可以实例化修改后的类并确定其方法。

修改

您使用的是双下划线变量名称__mess。你(几乎可以肯定)不想这样做。由于某些原因,只有我们的仁慈独裁生活和其他少数人知道,Python会自动将这些__名称变为_<class-name>__,作为一种虚假的私有变量。这太可怕了,除此之外没有理由称之为__mess而不是(更好)mess

如果您绝对必须将其称为__mess,您可以按以下方式参考:

def myFN(self):
    print( self._A__mess )

(当您更改A的名称时,经过必要的修改)。这是令人讨厌和unPythonic。

答案 1 :(得分:1)

关于第二个错误(使用__mess):

更改

print self.__mess

print self._mess

并改变

class A:
  __mess = "Yeap!"

class A:
  _mess = "Yeap!"

双下划线告诉Python使用name-mangling

另一种方法是改变

def myFN(self):
    print self.__mess

def myFN(self):
    print self._A__mess