创建一个Python类方法

我已经熟悉了这个概念,特别是通过观看Raymond Hettinger的优秀视频并阅读接受的答案,我想知道我错了什么。

class ReadHTML(object):

    def __init__(self, url):
        page = urlopen(url).read()
        self.page = page

    @classmethod
    def from_file(cls, path):
        page = open(path).read()
        return cls(page)

这工作

r = ReadHTML('http://example.com')
print r.page

而这不是

r = ReadHTML.from_file('example.html')
print r.page 

它会抛出一个错误,就像我试图“urlopen”一个文件一样:

File "/usr/lib/python2.7/urllib2.py", line 258, in get_type
    raise ValueError, "unknown url type: %s" % self.__original
ValueError: unknown url type: <!doctype html>

你能看到有什么问题吗?


当您调用cls(page)时,您仍然在调用类初始化程序ReadHTML.__init__() cls(page) ; 该调用与调用ReadHTML(page)没有区别,您只是使用了不同的引用。 这个方法只接受一个url参数,代码将其传递给urlopen()

调整您的ReadHTML.__init__()方法来处理被传递的页面而不是URL:

class ReadHTML(object):
    def __init__(self, url=None, page=None):
        if url is not None:
            page = urlopen(url).read()
        self.page = page

    @classmethod
    def from_file(cls, path):
        page = open(path).read()
        return cls(page=page)

现在代码支持两个路径来生成一个实例。


from_file打开页面,但是你的__init__()构造函数也是如此,所以如果你使用ReadHTML.from_file('example.html') ,你基本上是这样做的:

page = urlopen(open('example.html').read()).read()

就个人而言,我更喜欢Martijn的解决方案,为了语义清晰,但这里有一个选择:

class ReadHTML(object):
    def __init__(self, url, opener=urlopen):
        self.page = opener(url).read()

    @classmethod
    def from_file(cls, path):
        return cls(path, opener=open)

这种解决方案是有利的,因为它使您能够定义任意开启者(例如,打开存储在数据库中的文件)。


我不是可选参数的重要粉丝。 我会这样做,以便默认构造函数接受一个字符串,我将不得不分开替代构造函数来处理文件名和URL。

我还修改了文件名构造函数以明确关闭文件。

class ReadHTML(object):

    def __init__(self, page):
        self.page = page

    @classmethod
    def from_filename(cls, path):
        with open(path) as f:
            page = f.read()
        return cls(page)

    @classmethod
    def from_url(cls, url):
        page = urlopen(url).read()
        return cls(page)

作为一个方面说明,我相信urllib / urllib2支持file://,所以你完全不需要文件名构造函数(但我仍然相信它很好)。

链接地址: http://www.djcxy.com/p/54281.html

上一篇: Creating a Python classmethod

下一篇: Python saying I'm passing in too many parameters to my function?