__new__() does not return anything, on singletong pattern
Steven D'Aprano
steve+comp.lang.python at pearwood.info
Thu Mar 12 01:31:12 EDT 2015
Mario Figueiredo wrote:
> I'm fairly new to Python, so I don't know if the following is me
> abusing the programming language idioms, or simply a mistake of my IDE
> code inspection routine.
>
> I have a singleton Map class which is defined like so:
>
> class Map:
> _instance = None
> def __new__(cls):
> if Map._instance is None:
> Map._instance = super(Map, cls).__new__(cls)
> return Map._instance
In Python 2, you need to inherit from object for __new__ to be called. In
Python 3, it doesn't matter.
> def __init__(self, filename):
> # Instantiates from the contents of a binary file
>
> I am now trying to add another way of constructing an instance of this
> class. (I need to be able to create a dirty empty instance that is
> going to be used by the separate map editor script).
If this is supposed to be a singleton, you can't create more instances. The
point of a singleton that there is only one instance (or perhaps a small
number, two or three say). Why do you need two different ways to create
instances if you only have one instance?
> I added the following method to the class definition, above:
>
> @classmethod
> def generate(cls, width, height, fill=terrain[6]):
> if Map._instance is None:
> Map._instance = super(Map, cls).__new__(cls)
> else:
> raise Exception('Cannot generate an instance of Map.')
>
> Map._instance.author = None
> Map._instance.name = None
Since this method modifies the singleton instance in place, it doesn't
generate a new instance. It shouldn't be called generate(). In fact since
this is a singleton, the method shouldn't exist at all. Just put the
initialisation code in __new__, drop the __init__ and generate methods, and
call Map(argument).
def __new__(cls, width, height, fill=terrain[6]):
if Map._instance is None:
instance = Map._instance = super(Map, cls).__new__(cls)
instance.author = None
instance.name = None
instance.description = None
instance.cells = [Cell(fill)] * width * height
else:
# Ignore the arguments. Why are you passing different arguments
# to a singleton class? Bleh.
instance = Map._instance
return instance
> Map._instance.description = None
> # etc...
> self.cells = [Cell(fill)] * width * height
> return Map._instance
That's not your actual code, since the indentation is wrong. What does your
actual code look like? You are running PyCharm on one piece of code, then
showing us *different* (edited) code. We cannot see what PyCharm sees, so
how do we know why PyCharm says what it says?
> The following code runs just fine. But PyCharm flags the assignment
> with a warning telling me that generate() does not return anything and
> the I lose code completion on the mmap variable.
>
> if __name__ == '__main__':
> mmap = Map.generate(12, 24)
> print(mmap.width, mmap.height, mmap.author)
>
> I need to understand if this is just a glitch of the IDE or I am doing
> indeed something that is frowned upon and ended up caught in a
> misleading static analysis warning.
Probably.
--
Steve
More information about the Python-list
mailing list