我有一个我希望能够像这样使用的课程:
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__
来设置实例变量
答案 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,你会发现代码最终会更加清晰。