我在Python类创建方面遇到了一些麻烦。我的任务是使用一些解析方法创建对象。但我想使用doFetch() {
fetch('mysite', {
...
})
})
.then((response) => response.json())
.then((responseJson) => {
this.setState({someData: responseJson.success}); //***** put the result -> state
})
.catch((error) => {
console.error(error); })
);
}
render () {
{/* whatever you would like to show for someData */}
<Text< {this.state.someData} </Text>
}
}
例如,我有
__init__
这让我有机会使用像这样的命令创建对象
class A:
@classmethod
def create_from_file(cls, file):
# Create instance form file...
return self
但是这段代码让我有机会使用a = A.create_from_file()
__init__
不会引发异常......
当我尝试添加自己的a = A()
方法时,我的解析函数也会引发异常。
__init__
我如何解决这个问题,以及编写这个类的最Pythonic方法是什么?
答案 0 :(得分:1)
__init__
不负责创建实例。它是一个钩子方法,Python在实例创建之后为您调用。你不能阻止那里的实例创建。此外,您不希望阻止所有实例创建,即使您的classmethod
必须在某个时间创建实例。
由于当您的工厂方法不用于创建实例时,您想要做的只是引发异常,因此在__init__
方法中引发异常仍然可以。这将阻止新实例被分配到任何地方。您需要做的是区分直接访问和使用的工厂方法。
你可以通过几种不同的方式实现这一点。你可以使用&#34;秘密&#34;只有工厂方法传入的标记:
_token = object() # unique token to flag factory use
class A:
def __init__(self, data, _from_factory=None):
if _from_factory is not _token:
raise TypeError(f"Can't create {type(self).__name__!r} objects directly")
self._data = data
@classmethod
def create_from_file(cls, file):
data = file.read()
return cls(data, _from_factory=_token)
classmethod
仍然创建一个实例,仍然为该实例调用__init__
,并且因为传入了正确的令牌而没有引发异常。
您可以将您的课程作为模块的实施细节,并仅提供公共工厂功能:
def create_from_file(cls, file):
data = file.read()
return _A(data)
class _A:
def __init__(self, data):
self._data = data
现在公共API只为您提供create_from_file()
,领先的下划线告诉开发人员_A()
是一个内部名称,不应该依赖于模块外部。
实际实例创建是object.__new__
method的责任;您也可以使用该方法来防止创建新实例。您可以使用与上面显示的相同的令牌方法,或您可以通过使用super()
来调用原始重写的实现来完全绕过它:
class A:
def __new__(cls, *args, **kwargs):
raise TypeError(f"Can't create {cls.__name__!r} objects directly")
def __init__(self, data):
self._data = data
@classmethod
def create_from_file(cls, file):
data = file.read()
# Don't use __new__ *on this class*, but on the next one in the
# MRO. We'll have to manually apply __init__ now.
instance = super().__new__(cls)
instance.__init__(data)
return instance
此处直接调用A()
会引发异常,但在super().__new__
中使用classmethod
我们会绕过A.__new__
实施。
注意:__new__
隐含地设为staticmethod
,因此当我们从cls
调用时,我们必须手动传入classmethod
参数。
答案 1 :(得分:0)
如果你只有一个方法来创建对象,那就把它作为构造函数。也就是说,而不是
@classmethod
def create_from_file(cls, file):
# Create instance form file...
return self
你会有
def __init__(self, file):
# Create instance form file...
如果有几种不同的创建对象的方法,那么它们中的一种通常会比其他方法更基础 - 换句话说,其他方法的参数可以是& #34;转换&#34;进入一个方法的参数。例如,您可能有create_from_file()
,create_from_url()
和create_from_string()
,其中前两种方法基本上读取文件或网址的内容,然后对其执行相同的操作{{1} 1}}。因此,只需将create_from_string()
转换为create_from_string()
,然后让其他两个方法读取文件或网址,并使用内容调用构造函数。
如果你真的没有单一的&#34;基础&#34;创建对象的方法,可能值得考虑你是否应该有一个基类的不同子类。