这个算法的pythonic方法是什么?

时间:2017-03-19 18:39:57

标签: python object instantiation

我有一个我希望能够像这样使用的课程:

obj = MyClass(arg1, arg2)
if (obj is None):
    # tell user to try again
else:
    # give user options for continuing

对象创建的基本算法(__init__和/或__new__,我不确定)应该是这样的:

retrieve database record from arg1 and arg2 search criteria
if a record is returned
    setup instance variables
else
    return None

有没有明确的pythonic方式来做到这一点?我已经阅读了一些建议提出异常的文章,但这看起来并不正确,因为这是预期的行为。我已经看到其他人建议使用__new__,但我如何检查__new__中的数据库以查看记录是否有效,而无需检入__init__来设置实例变量

3 个答案:

答案 0 :(得分:3)

我认为你最好的方法是在你的类之上创建一个工厂,如果它无法检索正确的数据库记录,那么该类会引发异常,即:

class MyClass:
    def __init__(self, arg1, arg2):
        if arg1 or arg2:
            raise Exception()


def my_class(arg1, arg2):
    try:
        return MyClass(arg1, arg2)
    except Exception:  # using the default exception for simplicity
        return None


obj = my_class(arg1, arg2)
if obj is None:
    pass  # try again
else:
    pass  # other options

请不要在上面的代码中使用默认的Exception类,而是为您的特定模块类创建一个例外,或使用其中一个内置例外。

答案 1 :(得分:2)

Pythonic的事情是不要这样做。执行MyClass(whatever)实例化对象;根据定义,它总是会创建一个实例。

一种替代方法可能是将工厂函数定义为类方法,它可以返回一个对象。

class MyClass(object):
    ...

    @classmethod
    def create_maybe(cls, arg1, arg2):
        ... do logic ...
        if whatever:
            return cls(arg1, arg2)

现在可以创建对象,您可以调用MyClass.create_maybe(arg1, arg2)

答案 2 :(得分:2)

提出异常在这里完全有效。 SQLAlchemy是一个相对流行的Python ORM,如果需要一个记录但是找不到它会引发NoResultFound exception(尽管这是来自a function,而不是类实例化,所以可能无法直接比较)。我认为这样做并不常见 - it's not bad form to raise exceptions in __init__

您想要表达的“缺少值但不是错误”的想法类似于Option type,但这不是真正的Pythonic构造。如'Is there a Python equivalent for Scala's Option or Either?'中所述,Pythonic方式 以引发异常。

您不应该将异常视为您的程序被破坏的意思,只是在某种程度上预期的事件流中断。您可能希望阅读“When and how should I use exceptions?”,其中提供了有关Python中常见异常哲学的一些想法。

作为commented by idjaw,它是Easier to Ask for Forgiveness than Permission

  

这种常见的Python编码风格假设存在有效的键或属性,并且如果假设被证明是错误则捕获异常。这种干净和快速的风格的特点是存在许多try和except语句。该技术与许多其他语言(如C。

)共有的LBYL风格形成对比

你应该假设记录存在,如果不存在则处理错误。 Python是围绕这个设计的,如果你遵循EAFP,你会发现代码最终会更加清晰。

相关问题