我可能不会以Pythonic的方式思考这个问题。 我有一个类,SqlDB,它使用fetchall来获取游标中的所有行:
class SqlDB(object):
@classmethod
def executeQuery(cls, cursor, query, params):
# code to set up and execute query here
rows = cls.fetchRows(cursor)
# other code here
@classmethod
def fetchRows(cls, cursor):
print "in class SqlDB"
return cursor.fetchall()
所以我想添加一个使用fetchmany的子类,并使用批量大小进行初始化:
class SqlDBBatch(SqlDB):
def __init__(self, batchsize=1000):
self.batchsize = batchsize
def fetchRows(self, cursor):
print "in SqlDBBatch"
while True:
results = cursor.fetchmany(self.batchsize)
# more code
当然,由于最初的executeQuery函数在传递给它的类上调用fetchRows,所以当我尝试在SqlDBBatch的实例上调用executeQuery时,我得到TypeError: unbound method fetchRows() must be called with SqlDBBatch instance as first argument (got CursorDebugWrapper instance instead)
。有没有办法实现我的目标,我可以用实例方法覆盖父类的类方法,并让父类能够调用子类实现?
答案 0 :(得分:0)
我认为问题不在于父项或继承,而只是从类方法中调用实例方法。
class Bar(object):
def caller(self,x='cx'):
print('bar caller',self)
self.myfn(x)
@classmethod
def classcaller(cls,x='ccx'):
print('bar class caller',cls)
cls.myfn(x)
def myfn(self,x=None):
print('in bar instance',self,x)
def __repr__(self):
return 'BarInstance'
Bar().myfn()
# ('in bar instance', BarInstance, None)
Bar.myfn(Bar())
# ('in bar instance', BarInstance, None)
Bar().caller()
# ('bar caller', BarInstance)
# ('in bar instance', BarInstance, 'cx')
Bar.classcaller(Bar())
# ('bar class caller', <class '__main__.Bar'>)
# ('in bar instance', BarInstance, None)
Bar().classcaller(Bar())
# same
# the following produce:
# TypeError: unbound method myfn() must be called with Bar instance ...
# Bar.myfn()
# Bar.caller()
# Bar.classcaller()
# Bar().classcaller()
使用这个单一类,我可以从实例myfn
方法中轻松调用caller
,但如果使用Bar()
,则会传递单独的classcaller
实例。使用Bar()
调用classmethod与使用Bar
调用它没有区别。
即使使用实例调用classmethod,它也是klass
传递的,而不是obj
。 http://docs.python.org/2/howto/descriptor.html#static-methods-and-class-methods
class ClassMethod(object):
"Emulate PyClassMethod_Type() in Objects/funcobject.c"
...
def __get__(self, obj, klass=None):
if klass is None:
klass = type(obj)
def newfunc(*args):
return self.f(klass, *args)
return newfunc
您为什么使用@classmethod
?你只用类名或实例来称呼它们吗?即使父类版本不使用实例属性,在所有级别使用实例方法也可能更简单。 Python在没有这个装饰器的情况下相处很多年(在2.4中添加)。