type annotation vs working code

dn PythonList at DancesWithMice.info
Wed Oct 4 00:25:04 EDT 2023


On 02/10/2023 00.57, Karsten Hilbert via Python-list wrote:
> Sorry for having conflated the core of the matter with all
> the Borg shenanigans, that's where I found the problem in my
> real code, so there :-)

The first question when dealing with the Singleton Pattern is what to do 
when more than one instantiation is attempted:

- silently return the first instance
- raise an exception


The 'problem' interpreting the original code was that the 'Borg 
Pattern', is not limited in number, but is where some class-attribute 
list (or dict) is used to enable all instances to be aware of each of 
the others (IIRC).

Is choosing names as important as selecting/implementing smart algorithms?


> Consider this:
> 
> #----------------------------------------------------
> class Surprise:
> 	def __init__(self, with_type_annotation=False):
> 		if with_type_annotation:
> 			try:
> 				self.does_not_exist:bool
> 				print('does_not_exist does exist')
> 			except AttributeError:
> 				print('does_not_exist does not exist')
> 			return
> 
> 		try:
> 			self.does_not_exist
> 			print('does_not_exist does exist')
> 		except AttributeError:
> 			print('does_not_exist does not exist')
> 
> Surprise(with_type_annotation = False)
> Surprise(with_type_annotation = True)
> #----------------------------------------------------
> 
> Is this how it is supposed to be ?

Wasn't this answered earlier? (@Mats)

That self.does_not_exist:bool isn't interpreted by Python to mean the 
same as self.does_not_exist.


>> ...and so we're addressing the important question: the try-test is for existence, cf for
>> some value.
>>
>> This can also be achieved by using the attribute in a legal expression, eg:
> ...
>> Might this remove the confusion (ref: @Mats):
>>
>>      self.already_initialized:bool == True
> 
> Not for me as that would _create_ already_initialized on the
> instance. It would not allow me to test for it.
> 
>>> Which seems akin constructs for generating compatibility
>>> between versions.
>>
>> versions of ?
> 
> Of the language. Sometimes one tests for existence of a given
> class in a module and defines said class oneself if it does
> not exist. But that's leading astray.
> 
>> What is the intent: a class where each instance is aware of every other instance - yet
>> the word "Singleton" implies there's only one (cf a dict full of ...)?
> 
> The latter.

and so, returning to the matter of 'readability':

- the name "Borg" de-railed comprehension

- _instances:dict = {} implied the tracking of more than one

- should the class have been called either;

     class SomethingSingleton():

or a Singleton() class defined, which is then sub-classed, ie

     class Something( Singleton ):

in order to better communicate the coder's intent to the reader?

- from there, plenty of 'templates' exist for Singletons, so why do 
something quite different/alien to the reader?
(thus concurring with @Richard: "tricky" subverts 'readability')

- is it better to use a technique which 'we' will recognise, or to ask 
'us' to comprehend something 'new'?
(unless the 'new' is taking-advantage of a recent extension to the 
language, eg switch; to justify 'trail-blazing' a 
new/improved/replacement 'best practice')

- part of the 'tricky' seems to be an attempt to assess using an 
instance-attribute, rather than a class-attribute. If the :bool (or 
whichever) typing-annotation is added to a class-attribute (eg 
_instance), will the problem arise?

- does the sequence

     _instance = False
     ...
     if not cls._instance:
ie the explicit version
     if cls._instance == False:

measure 'existence' or a value?

- does the sequence

     _instance = None
     ...
     if not cls._instance:
ie the explicit version:
     if cls._instance is None:

measure 'existence' or identity?
(indeed, are they more-or-less the same concept?)

- do the *attr() functions test for 'existence'?

(that said, most of the code-examples I spotted, in reading-up on this, 
use either None or False - et tu Brute!)


Speaking of reading-up:

- am wondering where PEP 661 - Sentinel Values is 'going'?

- this article (https://python-patterns.guide/gang-of-four/singleton/) 
mentions that the original GoF Singleton Pattern preceded Python 
(particularly Python 3 classes). Also, that Python doesn't have 
complications present in C++. It further discusses "several drawbacks", 
which also champion 'readability' over 'trick' or 'sophistication'. I 
think you'll enjoy it!

-- 
Regards,
=dn


More information about the Python-list mailing list