Skip to content

Instantly share code, notes, and snippets.

@misja
Last active January 3, 2022 00:12
Show Gist options
  • Save misja/2a7ab71f6346c5c19382412627ddf34e to your computer and use it in GitHub Desktop.
Save misja/2a7ab71f6346c5c19382412627ddf34e to your computer and use it in GitHub Desktop.
Python None is an object (and a singleton)
# None is of type NoneType
print(f"{None} is of type", type(None))
# Each object contains a reference to its class,
# let's use this to create a new instance of NoneType
NewNone = None.__class__()
# NoneType is a *singleton*, so should be equal
assert NewNone is None
# Can we set attributes on None?
try:
None.ok = True # can't set attributes on None
except AttributeError as e:
print(f"Can't set attribute on {None}:", e)
# Let's emulate NoneType, a singleton!
class EmptyType:
__slots__ = () # no declared instance attributes permitted
def __new__(cls, *args, **kwargs):
if not hasattr(cls, "_instance"):
cls._instance = super().__new__(cls, *args, **kwargs)
return cls._instance # will be 'self' in instance context
def __str__(self):
return "Empty"
__repr__ = __str__
# With None being an instance of NoneType,
# so will Empty be an instance of EmptyType
Empty = EmptyType()
# Empty is of type EmptyType
print(f"{Empty} is of type", type(Empty))
# A new instance of EmptyType
MyEmpty = EmptyType() # could also have called Empty.__class__()
# EmptyType is a *singleton*, should be equal
assert MyEmpty is Empty
# Can we set attributes on Empty?
try:
Empty.ok = True # will fail because of __slots__
except AttributeError as e:
print(f"Can't set attribute on {Empty}:", e)
# But _instance attribute was set, let's modify!
try:
Empty._instance = "Hey there!" # is read-only
except AttributeError as e:
print(f"Can't change '_instance' of {Empty}:", e)
# NoneType is not a base type (i.e. not subclassable),
# but given the above we could do ...
class MyNoneType:
def __new__(cls, *args, **kwargs):
return None # will be 'self' in instance context
# New instance!
MyNone = MyNoneType()
# Will be of type *type*, which we could subclass (if we´d like)
print(f"{MyNone} is of type", type(MyNoneType))
# MyNone is a None, hence a *singleton* (NoneType), and should be equal
assert MyNone is None
# Now also try this with True and False (also objects and singletons)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment