how I should structure the class using __init__
and __new__
as they are different and both accepts arbitrary arguments besides default first argument.
Only rarely will you have to worry about __new__
. Usually, you'll just define __init__
and let the default __new__
pass the constructor arguments to it.
self
keyword is in terms of name can be changed to something else? But I am wondering cls
is in terms of name is subject to change to something else as it is just a parameter name?
Both are just parameter names with no special meaning in the language. But their use is a very strong convention in the Python community; most Pythonistas will never change the names self
and cls
in these contexts and will be confused when someone else does.
Note that your use of def __new__(tuple)
re-binds the name tuple
inside the constructor function. When actually implementing __new__
, you'll want to do it as
def __new__(cls, *args, **kwargs):
# do allocation to get an object, say, obj
return obj
Albeit I said I want to return tuple
, this code works fine and returned me [1,2,3]
.
MyClass()
will have the value that __new__
returns. There's no implicit type checking in Python; it's the responsibility of the programmer to return the correct type ("we're all consenting adults here"). Being able to return a different type than requested can be useful for implementing factories: you can return a subclass of the type requested.
This also explains the issubclass
/isinstance
behavior you observe: the subclass relationship follows from your use of class MyClass(tuple)
, the isinstance
reflects that you return the "wrong" type from __new__
.
For reference, check out the requirements for __new__
in the Python Language Reference.
Edit: ok, here's an example of potentially useful use of __new__
. The class Eel
keeps track of how many eels are alive in the process and refuses to allocate if this exceeds some maximum.
class Eel(object):
MAX_EELS = 20
n_eels = 0
def __new__(cls, *args, **kwargs):
if cls.n_eels == cls.MAX_EELS:
raise HovercraftFull()
obj = super(Eel, cls).__new__(cls)
cls.n_eels += 1
return obj
def __init__(self, voltage):
self.voltage = voltage
def __del__(self):
type(self).n_eels -= 1
def electric(self):
"""Is this an electric eel?"""
return self.voltage > 0
Mind you, there are smarter ways to accomplish this behavior.