I have the following piece of code – simplified version of what I want to do.
But it gives me a recursion error.
class File:
def __new__(cls, filename):
extension = filename.split(".")[-1].lower()
if extension == "csv":
cls = CSVFile
elif extension == "json":
cls = JSONFile
else:
raise ValueError(f"Unsupported file extension: {extension}")
# instance = super().__new__(cls) # this works
instance = cls.create_instance(filename)
return instance
class CSVFile(File):
def __init__(self, filename):
self.filename = filename
@classmethod
def create_instance(cls, filename):
print("CSVFile, create_instance")
return cls(filename)
class JSONFile(File):
def __init__(self, filename):
self.filename = filename
@classmethod
def create_instance(cls, filename):
print("JSONFile, create_instance")
return cls(filename)
# Example usage
file_instance = File("data.csv")
print(f"File instance: {file_instance.filename}")
Do you have idea how to make it work?
__new__
indirectly invokes itself when subclass create_method
methods call cls
.
If you want a factory method, define a distinct one instead of trying to hijack __new__
for the purpose.
File("data.cvs"
invokes File.__new__(File, "data.csv")
which invokes CSVFile.create_method("data.csv")
which invokes CSVFile("data.csv")
which calls CSVFile.__new__(CSVFile, "data.csv")
which, because CSVFile.__new__
isn’t defined, calls File.__new__(CSVFile, "data.csv")
… which invokes CSVFile.create_method(“data.csv”) which …
3
I’m not sure what your later goal is, but why not something like this?
from pathlib import Path
class File:
def __init__(self, filename: Path):
self.filename = filename.name
def parse(self) -> Any:
raise NotImplementedError()
class CSVFile(File):
pass
class JSONFile(File):
pass
def get_file(filename: Path) -> File:
"""Get a file by its name."""
match filename.suffix:
case ".csv":
return CSVFile(filename)
case ".json":
return JSONFile(filename)
case _:
raise ValueError(f"Unsupported file type: {filename.suffix}")
1