我编写了一个用于解析专用文本格式的Python类。
class Parser(object):
def __init__(self):
# Initialize parser instance
def parseFile(self , filename):
pass
def modifyParser(self , *args , **kwargs):
pass
#Classmethod has same name as instance method - this does not work.
@classmethod
def parseFile(cls , filename)
parser = Parser( )
return parser.parseFile( filename )
如上所示,可以使用modifyParser
方法修改解析器 - 但在大多数情况下,我将只使用Parser实例,因为它来自Parser.__init__()
。我希望能够做到这一点:
# Parse file using 'custom' parser:
parser = Parser( )
parser.modifyParser( ... )
result = parser.parseFile("file.input")
# Parse using the default parser - do not explicitly instantiate an object:
result = Parser.parseFile("file.input")
这要求parseFile( )
方法既可以作为实例方法调用 - 使用self
- 也可以作为类方法调用。这可能吗?形式不好?
答案 0 :(得分:6)
如果我是你,我会提供两个不同的功能:
mymodule.Parser().parseFile()
(实例方法)和mymodule.parseFile()
(使用默认实例的模块级函数)。例如,使用标准json
模块会发生这种情况,您有json.JSONDecoder().decode()
和json.loads()
。提供两个不同的函数使得代码不那么模糊,更明确,更可预测(在我看来)。
然而,是的:你想做的事情是可能的。您必须使用__get__
实施自己的descriptor。这是一个例子:
from functools import partial
class class_and_instance_method(object):
def __init__(self, func):
self.func = func
def __get__(self, obj, type=None):
first_arg = obj if obj is not None else type
return partial(self.func, first_arg)
class Parser(object):
@class_and_instance_method
def parseFile(self):
if isinstance(self, type):
print('using default parser')
else:
print('using the current instance')
>>> Parser.parseFile()
using default parser
>>> p = Parser()
>>> p.parseFile()
using the current instance
答案 1 :(得分:2)
您必须使用两个单独的名称。在python中由于它的动态特性,在C ++中没有运算符重载,当一个函数具有不同参数的相同名称时。
当您在脚本中说def
时,您告诉Python“将以下对象(函数对象)设置为此名称”。因此,在您的代码中,您只需重新定义名称以引用classmethod
,并且您的实例方法函数对象将丢失。
解决方案:对instace方法和类方法使用不同的名称。