Mee*_*ies 1 python class subclass superclass
我有一个Python类(它实际上不是我的,它来自一个包,所以我不想编辑这个).最小的例子(不切实际):
import os
class SuperClass:
def __init__(self):
# Do something, for example
self.a = 0
pass
def from_file(filename):
# Do something with the file,
# use it to create superclass
# instance obj. For example...
obj = SuperClass()
obj.a = os.stat(filename).st_size
return obj
Run Code Online (Sandbox Code Playgroud)
现在我想创建这个超类的子类,它的初始化总是来自一个文件 - 也就是说,我想做类似的事情
class SubClass(SuperClass):
def __init__(self, filename):
self = SuperClass.from_file(filename)
Run Code Online (Sandbox Code Playgroud)
这不起作用(我没想到):我没有得到异常但是子类没有正确初始化.例如,如果SuperClass有一些实例值a,总是设置,那么
new_subclass_instance = SubClass('/filepath/file')
print(new_subclass_instance.a)
Run Code Online (Sandbox Code Playgroud)
会给一个AttributeError: type object 'SubClass' has no attribute 'a'.
如何使用from_file父类中的函数初始化?
Python的__init__方法实际上不是构造函数,它只是一个初始化器.这就是为什么你不能在__init__方法中实现这种行为- 一旦__init__被调用,你已经有一个多余的对象实例浮动.
负责实际创建类的新实例的方法是__new__,所以我们可以通过覆盖它来实现我们的目标.基本的想法是写这样的东西:
class SubClass(SuperClass):
def __new__(cls, filename):
return cls.from_file(filename)
def __init__(self, *args, **kwargs):
pass
Run Code Online (Sandbox Code Playgroud)
空__init__是必要的,因为python会自动在返回的对象上调用它__new__.如果省略空__init__方法,python将最终调用SuperClass.__init__该对象,这将重置其所有属性.
但是有一个问题:由于我们已经重写了__new__方法以便它需要filename参数,因此该from_file方法可能不再有效.你没有展示它的代码,但它可能在这些方面做了些什么:
@classmethod
def from_file(cls, filename):
obj = cls()
obj.filename = filename
return obj
Run Code Online (Sandbox Code Playgroud)
这里的问题是调用cls()将失败:这将调用我们的__new__方法,它需要一个filename参数,没有任何参数.我们最终得到一个例外TypeError: __new__() missing 1 required positional argument: 'filename'.要解决此问题,我们可以使filename参数可选:
class SubClass(SuperClass):
def __new__(cls, filename=None):
if filename is None:
return super().__new__(cls)
return cls.from_file(filename)
def __init__(self, *args, **kwargs):
pass
Run Code Online (Sandbox Code Playgroud)
现在我们可以obj = SubClass('/filepath/file')根据需要打电话.但是,也可以在SubClass没有任何参数(如obj = SubClass())的情况下调用,这将返回一个完全单元化的对象实例(记住,我们__init__是空的,因此对象将没有任何属性).不幸的是,我们无能为力.
一般来说,这样做可能是一个坏主意.我相信你现在可以知道,在尝试更改现有类的界面时,有许多陷阱需要注意.它很可能不值得麻烦,你应该坚持创建你的实例SubClass.from_file.
| 归档时间: |
|
| 查看次数: |
135 次 |
| 最近记录: |