1

我有一个 Python 函数,它在 XML 文件上做了很多主要工作。

使用这个函数时,我需要两个选项:要么传递一个 XML 文件的名称,要么传递一个预解析的 ElementTree 实例。

我希望该函数能够确定其变量中给出的内容。

例子:

def doLotsOfXmlStuff(xmlData):
    if (xmlData != # if xmlData is not ET instance):
        xmlData = ET.parse(xmlData)
    # do a bunch of stuff
    return stuff

调用此函数的应用可能只需要调用一次,也可能需要多次调用。多次调用它并每次都解析 XML 是非常低效且不必要的。创建一个完整的类来包装这个函数似乎有点矫枉过正,最终需要进行一些代码重构。例如:

ourResults = doLotsOfXmlStuff(myObject)

必须变成:

xmlObject = XMLProcessingObjectThatHasOneFunction("data.xml")
ourResult = xmlObject.doLotsOfXmlStuff()

如果我必须在很多小文件上运行它,每次都会创建一个类,这似乎效率低下。

有没有一种简单的方法来简单地检测进来的变量的类型?我知道很多 Python 爱好者会说“你不应该检查”,但这是一个很好的例子。

在其他强类型语言中,我可以通过方法重载来做到这一点,但这显然不是 Pythonic 的方式......

4

5 回答 5

2

The principle of "duck typing" is that you shouldn't care so much about the specific type of an object but rather you should check whether is supports the APIs in which you're interested.

In other words if the object passed to your function through the xmlData argument contains some method or attribute which is indicative of an ElementTree that's been parsed then you just use those methods or attributes ... if it doesn't have the necessary attribute then you are free to then pass it through some parsing.

So functions/methods/attributes of the result ET are you looking to use? You can use hasattr() to check for that. Alternatively you can wrap your call to any such functionality with a try: ... except AttributeError: block.

Personally I think if not hasattr(...): is a bit cleaner. (If it doesn't have the attribut I want, then rebind the name to something which has been prepared, parsed, whatever as I need it).

This approach has advantages over isinstance() because it allows users of your functionality to pass references to objects in their own classes which have extended ET through composition rather than inheritance. In other words if I wrap an ET like object in my own class, and expose the necessary functionality then I should be able to pass reference s to your function and have you just treat my object as if it were a "duck" even if it wasn't a descendant of a duck. If you need feathers, a bill, and webbed feet then just check for one of those and try to use the rest. I may be a black box containing a duck and I may have provided holes through which the feet, duck-bill, and feathers are accessible.

于 2013-05-09T17:07:29.397 回答
2

这是一个相当正常的模式(例如接受文件对象或路径的 Python 函数)。只需使用isinstance

def doLotsOfXmlStuff(xmlData):
    if not isinstance(xmlData, ET):
        xmlData = ET.parse(xmlData)
    ...

如果您需要进行清理(例如关闭文件),那么递归调用您的函数就可以了:

def doLotsOfXmlStuff(xmlData):
    if not isinstance(xmlData, ET):
        xmlData = ET.parse(xmlData)
        ret = doLotsOfXmlStuff(xmlData)
        ... # cleanup (or use a context manager)
        return ret
    ...
于 2013-05-09T17:05:01.303 回答
0

我认为您可以比较数据类型:

if (xmlData.dtype==something):
    call Function1
else:
    call Function2
于 2013-05-09T17:06:30.997 回答
0

您可以使用 isinstance 来确定变量的类型。

于 2013-05-09T17:04:54.373 回答
0

您可以尝试使用 if 语句来检查类型并确定从那里运行什么吗?

if type(xmlData).__name__=='ElementTree':
    #do stuff
else: 
    #do some other stuff
于 2013-05-09T17:05:12.283 回答