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 _______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor