【问题标题】:What's the pythonic method for this algorithm?这个算法的pythonic方法是什么?
【发布时间】:2017-03-19 18:39:57
【问题描述】:

我有一个类,我希望能够像这样使用:

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__ 来设置实例变量?

【问题讨论】:

  • EAFP 是一种非常容易接受的 pythonic 方法。

标签: python object instantiation


【解决方案1】:

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

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 类,而是为您的特定模块类创建异常或使用内置异常之一。

【讨论】:

    【解决方案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,您会发现代码最终会变得更加简洁。

    【讨论】:

      【解决方案3】:

      Python 的特点是不要这样做。做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)

      【讨论】:

        猜你喜欢
        • 2014-02-20
        • 1970-01-01
        • 2014-05-22
        • 2022-12-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-09-11
        • 1970-01-01
        相关资源
        最近更新 更多