Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/278.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何创建隐藏工厂?_Python - Fatal编程技术网

Python 如何创建隐藏工厂?

Python 如何创建隐藏工厂?,python,Python,我知道它以前被报道过,但我只是不明白 我想创建一个用文件名调用的类,但根据文件名的扩展名,它会变形为几个子类之一。它认为这是一种工厂模式,我在使用staticmethod之前就已经这样做了,但我现在尝试使用基类的一个公共实例化来实现它,这并不完全是为了好玩。这可能吗 >>> foo = FileClass('foo.txt') >>> type(foo) <type 'TextFileClass'> >>> foo =

我知道它以前被报道过,但我只是不明白

我想创建一个用文件名调用的类,但根据文件名的扩展名,它会变形为几个子类之一。它认为这是一种工厂模式,我在使用staticmethod之前就已经这样做了,但我现在尝试使用基类的一个公共实例化来实现它,这并不完全是为了好玩。这可能吗

 >>> foo = FileClass('foo.txt')
 >>> type(foo)
 <type 'TextFileClass'>

 >>> foo = FileClass('foo.rtf')
 >>> type(foo)
 <type 'RTFFileClass'>
>foo=FileClass('foo.txt'))
>>>类型(foo)
>>>foo=FileClass('foo.rtf')
>>>类型(foo)

这不是实际产出,而是我希望达到的目标。我一直在尝试疯狂的东西,一定是偏离了轨道。目前,我已经在
FileClass
中实现了一个
\uuuuu new\uuuuu
例程,但似乎做得不对。似乎有很多方法可以做到这一点?正确的方法是什么?

使用
\uuuuuu new\uuuuuu
执行此操作的主要问题是,如果
FileClass.\uuuuu new\uuuuu
调用
TextFileClass
构造函数,那么
TextFileClass
将如何运行一个实例以返回

为了解决这个问题,我们可以测试
\uuuuu new\uuuuuu
中的
cls
是什么,这样我们就不会干扰子类的
\uuuu new\uuuu

def __new__(cls, filename):
    if cls is FileClass:
        return cls._factory(filename)
    return super(FileClass, cls).__new__(cls, filename)
调用
FileClass('foo.txt')
时,如果对象是
FileClass
的实例,Python会调用
\uuuu init\uuuu
返回的对象,因此我们必须使用
TextFileClass.\uu new\uuuu('foo.txt')
,而不是
TextFileClass('foo.txt')


总而言之,这样做可能不值得。工厂函数或工厂方法更容易正确使用。

为什么不直接使用工厂函数呢

class BaseFile(object):
    """Inherit these common methods and properties"""
    def __init__(self, fname):
        self.fname = fname

    def is_pretty(self):
        NotImplemented

class TextFileClass(BaseFile): 
    def is_pretty(self):
        return False

class RTFFileClass(BaseFile):
    def is_pretty(self):
        return True

def createFileClass(fname):
    if fname.endswith('.txt'):
        return TextFileClass(fname)
    elif fname.endswith('.rtf'):
        return RTFFileClass(fname)
    else:
        raise Exception, 'unknown file format'

FileClass = createFileClass
产生:

>>> foo = FileClass('foo.txt')
>>> type(foo)
<class '__main__.TextFileClass'>

>>> foo = FileClass('foo.rtf')
>>> type(foo)
<class '__main__.RTFFileClass'>
>foo=FileClass('foo.txt'))
>>>类型(foo)
>>>foo=FileClass('foo.rtf')
>>>类型(foo)

如果
FileClass
不能作为工厂函数,则可以应用模式(或派生模式)使
FileClass
实例化实现类,将其保存在字段中,并对其进行代理方法调用。使用者不会在变量类型中看到子类,但会出现接口,这是很重要的。

如果您感觉更好,可以创建单独的函数。像
def创建\u right\u对象(文件名):
@JBernardo是的,但我可以,但那只是一顶旧帽子;-)然后只需使用
\uuuuu new\uuuuu
。它将像我上面描述的功能一样工作。。。只要返回您喜欢的任何内容,类并不是真正想要知道它们的子类。为什么
FileClass
不能只是一个工厂函数?它有点像mime类型吗?实际上,这是一种低技术的方法。我喜欢这样。它有用吗?@JohnMee很抱歉没有看到“旧帽子”的评论,但为什么它是“低技术的”?仅仅是因为使用了函数而不是类吗?“低技术”意味着即使是python noobs也能理解它;不要乱说python构造函数。@JohnMee、javanoobs等将能够更容易地理解它。啊,这个编辑更好,因为我刚刚要提到递归循环。让我试试……嗯。它反复调用new和init。这可能只是一个普通的案例,但我的实际问题有一些未提及的复杂性,这些复杂性和调用参数有关;因此,我发现这种方法很难做到正确,这让我担心,对于我的继任者来说,这可能有点太棘手了-(
>>> foo = FileClass('foo.txt')
>>> type(foo)
<class '__main__.TextFileClass'>

>>> foo = FileClass('foo.rtf')
>>> type(foo)
<class '__main__.RTFFileClass'>