[Tutor] method, type?
Steven D'Aprano
steve at pearwood.info
Wed Jan 6 19:31:31 EST 2016
On Wed, Jan 06, 2016 at 06:57:31PM +0000, Alan Gauld wrote:
> On 06/01/16 14:46, Steven D'Aprano wrote:
> > I don't understand what you mean by "Python doesn't support named
> > constructors". It seems to me that this is the *only* sort of
> > constructor that Python supports.
>
> No, Python constructors have names(new/init) but they are not
> used explicitly (ie. by the client code)to create objects.
The default new/init constructor isn't, but any additional ones are. The
classic example is dict.fromkeys. Other examples include:
Decimal.from_float
fractions.from_float
fractions.from_decimal
datetime.fromordinal
datetime.fromtimestamp
> By contrast languages like Delphi, Smalltalk, Objective C,
> some Lisps and, I think, Eiffel (and others?) all require an
> explicit call of a constructor method
The fact that in Python the default constructor is called via the class
name is, in my opinion, just a cosmetic difference: MyClass(x) versus
MyClass.new(arg) is not that big a difference. It just means that
one name is implicit.
Contrast that to the C++ style where the compiler can do multiple
dispatch by the number and type of arguments:
# Using Python syntax again
class Spam:
# four constructors
def Spam(afloat): ...
def Spam(astring): ...
def Spam(inta): ...
def Spam(inta, intb): ...
compared to the Python/Smalltalk/Delphi etc style where they all have to
be named differently:
class Spam:
def __new__(cls, afloat): ...
def from_word(cls, astring): ...
def from_count(cls, inta): ...
def from_ratio(cls, inta, intb): ...
But if you want to insist that the default Python constructor of __new__
plus __init__ doesn't qualify as a "named constructor" because it is
called implicitly rather than explicitly, I won't argue. I'll just say
that Python has named constructors for the *alternate* (non-default)
constructors :-)
> and there may be
> multiple constructors per class each with different names
> (usually describing how the construction occurs or the
> nature of the object constructed).
Exactly like in Python :-)
> > So the only way to have two different constructors is to give them
> > different names.
> >
> > Hence all constructors in Python are "named constructors".
>
> But they are not native constructors such as those used in
> Smalltalk etc. They have to be factory methods that call new/init
> under the covers.
No they don't. It is *most common* for alternate constructors to hand
over the actual work of building the instance to __new__, because DRY.
Hence:
class Spam(object):
def __new__(cls, alist):
# do the real work here
@classmethod
def from_string(cls, astring):
alist = astring.split()
return cls(alist)
But that's not a hard rule. Any method can manually create an instance,
well, any *new-style class* method. (Classic classes from Python 2 are
different, because they can't have constructors except for the default.)
class Eggs(object):
@classmethod
def this_is_my_constructor(cls):
instance = object.__new__(cls)
instance.initiate_me()
return instance
def initiate_me(self):
print("Initiating...")
self.style = "hard boiled"
# And just to prove that the default constructor isn't used:
def __new__(cls):
raise TypeError
e = Eggs.this_is_my_constructor()
So while you are right that most alternate constructors end up calling
the default __new__, that's not compulsory. It's just convenient.
> > ... ensures that if you subclass the class, you automatically
> > get a valid constructor as well.
>
> Wouldn't it return an instance of the superclass rather than
> the sub class? You'd need to override it wouldn't you?
Not if you write it correctly :-)
If you hard-code the name of the superclass into the method, then you
will always get the superclass. That is bad.
# Don't do this, this is wrong.
class Spam(object):
@classmethod
def from_eggs(cls, eggs):
args = process(eggs)
return Spam(args)
# Do this instead.
class Spam(object):
@classmethod
def from_eggs(cls, eggs):
args = process(eggs)
return cls(args)
--
Steve
More information about the Tutor
mailing list