RE: Configuring an object via a dictionary

2024-03-15 Thread AVI GROSS via Python-list
A part of the Python view of the world is about a concept of whether
something is "truthy" or not and thus many corners of the language do not
care what kind of object an expression returns. If the object is returned in
a context looking for not a Boolean value but a truth value, it is evaluated
and in other scenarios, left alone to propagate in the code.

Changing such behavior would be a very serious undertaking, and frankly,
silly. 

But if anyone really wants an actual Boolean, then the non-not operator
should do the trick as !(whatever) takes what follows as a truthy value and
negates it and a second ! brings it back as a True/False as in !!(whatever)

And for many data types, perhaps all, you can use the bool() function that I
believe follows the same rules about being truthy.

Both of the above should be fairly easy to use in any rare contexts that
demand a more standard Boolean result as in some other languages.

It is one of many strengths of python that supports varieties of
polymorphism. And it allows a value to be passed or returned that can both
be viewed as some kind of object of many kinds and seen as a Boolean for
considerations like flow of control.

-Original Message-
From: Python-list  On
Behalf Of Dan Sommers via Python-list
Sent: Friday, March 15, 2024 5:33 PM
To: python-list@python.org
Subject: Re: Configuring an object via a dictionary

On 2024-03-15 at 15:48:17 -0400,
Thomas Passin via Python-list  wrote:

> [...] And I suppose there is always the possibility that sometime in
> the future an "or" clause like that will be changed to return a
> Boolean, which one would expect anyway.

Not only is the current value is way more useful, but changing it would
be a compatibility and maintenance nightmare.

If I want Java, I know where to find it.  :-)
-- 
https://mail.python.org/mailman/listinfo/python-list

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Configuring an object via a dictionary

2024-03-15 Thread Thomas Passin via Python-list

On 3/15/2024 5:33 PM, Dan Sommers via Python-list wrote:

On 2024-03-15 at 15:48:17 -0400,
Thomas Passin via Python-list  wrote:


[...] And I suppose there is always the possibility that sometime in
the future an "or" clause like that will be changed to return a
Boolean, which one would expect anyway.


Not only is the current value is way more useful, but changing it would
be a compatibility and maintenance nightmare.


I'm with you here!


If I want Java, I know where to find it.  :-)


--
https://mail.python.org/mailman/listinfo/python-list


Re: Configuring an object via a dictionary

2024-03-15 Thread dn via Python-list

On 15/03/24 22:30, Loris Bennett via Python-list wrote:

Hi,

I am initialising an object via the following:

 def __init__(self, config):

 self.connection = None

 self.source_name = config['source_name']
 self.server_host = config['server_host']
 self.server_port = config['server_port']
 self.user_base = config['user_base']
 self.user_identifier = config['user_identifier']
 self.group_base = config['group_base']
 self.group_identifier = config['group_identifier']
 self.owner_base = config['owner_base']

However, some entries in the configuration might be missing.  What is
the best way of dealing with this?


How do you define "missing"?

Thus, @Thomas' suggestion may/not apply. It is neat and easy.

I usually plump for:

self.source_name = config[ "source_name" ] or default_value

but @Grant's warning applies!
(which is why the pythonic way is to use (and test for) None as a 
definition of "missing" (see also impacts of using default values and 
mutable data-structures)



LBYL cf EAFP:
When setting-up an environment like this, elements are often set to a 
default-value, and then user-settings, command-line arguments, and the 
like, applied in a priority-order sequence, amend as-appropriate. In 
this way, such problems will never arise.


This is the better course 90% of the time.


Which raises the next question:

What is the impact if some attribute is "missing"? ie if the 'whatever' 
must be identified by source_name (for example), then there is little 
point in assigning any values to the new class. Considerations which 
apply *after* this question, the __init__(), are at least 
equally-important considerations (see below)!




I could of course simply test each element of the dictionary before
trying to use.  I could also just write

self.config = config

but then addressing the elements will add more clutter to the code.


By which you mean that such "clutter" should only appear in the 
__init__() - which is not such a bad idea (but see below).


OTOH it is often helpful to one's comprehension to be given a prompt as 
to the source of the data. Thus, in later processing *config[ 
"source_name" ] may add a small amount of extra information to the 
reader, over self.source_name.


* maybe prepended "self.", or not...


Am assuming that passing all eight elements as individual arguments is 
off-the-table, embodying far too many 'negatives' (see below).




However, with a view to asking forgiveness rather than
permission, is there some simple way just to assign the dictionary
elements which do in fact exist to self-variables?


Assuming config is a dict:

self.__dict__.update( config )

will work, but attracts similar criticism - if not "clutter" then an 
unnecessary view (and understanding) of the workings of classes 
under-the-hood.



Another question:
When these values are used, are they all used at the same time, and 
never again? It may only be worth 'breaking-out' and making attributes 
from those which are used in multiple situations within the class's 
methods. If, the other extreme, they are only (effectively) passed from 
the __init__() to some sort of open() method, then pass the 
data-structure as an whole and delegate/remove the "clutter" to there. 
In that scenario, such detail would *only* has meaning *and* purpose in 
the open() method and thus no point in cluttering-up the __init__() with 
detail that is only required elsewhere!




Or should I be doing this completely differently?


YMMV, but I prefer the idea of transferring the environment/config as a 
whole (as above).


If it were a class (cf the supposed dict) then "clutter" is reduced by 
eschewing brackets and quotation-marks, eg "config.source_name".



If those eight-elements are not the entirety of that data-structure, 
then consider creating an interface-class, which is extracted (or built 
that way) from some wider 'environment', and used to set-up access to 
data-source(s) or whatever. Again, this aids understanding in knowing 
where data has been created/gathered, and improves confidence when 
utilising it down-the-line.


The other principle in only providing the required (eight) items of 
data, is that the 'receiving-class' needs no understanding of the 
structure or workings of the 'sending-class' = separation of concerns, 
and each class has single purpose/reason to change.



A variation on that might be to use a method/function as the interface:

access = Access( config.access_data )

Thus, the config class (instance) will need an access_data method to 
collate the data-items. The complimentary code in this Access.__init__( 
self, config, ) might be something like:


(
self.source_name,
self.server_host,
self.server_port,
self.user_base,
self.user_identifier,
self.group_base,

Re: Configuring an object via a dictionary

2024-03-15 Thread Dan Sommers via Python-list
On 2024-03-15 at 15:48:17 -0400,
Thomas Passin via Python-list  wrote:

> [...] And I suppose there is always the possibility that sometime in
> the future an "or" clause like that will be changed to return a
> Boolean, which one would expect anyway.

Not only is the current value is way more useful, but changing it would
be a compatibility and maintenance nightmare.

If I want Java, I know where to find it.  :-)
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Configuring an object via a dictionary

2024-03-15 Thread Thomas Passin via Python-list

On 3/15/2024 3:09 PM, Grant Edwards via Python-list wrote:

On 2024-03-15, Thomas Passin via Python-list  wrote:

On 3/15/2024 5:30 AM, Loris Bennett via Python-list wrote:

Hi,

I am initialising an object via the following:

  def __init__(self, config):

  self.connection = None

  self.source_name = config['source_name']
  self.server_host = config['server_host']
  self.server_port = config['server_port']
  self.user_base = config['user_base']
  self.user_identifier = config['user_identifier']
  self.group_base = config['group_base']
  self.group_identifier = config['group_identifier']
  self.owner_base = config['owner_base']

However, some entries in the configuration might be missing.  What is
the best way of dealing with this?

I could of course simply test each element of the dictionary before
trying to use.  I could also just write

 self.config = config

but then addressing the elements will add more clutter to the code.

However, with a view to asking forgiveness rather than
permission, is there some simple way just to assign the dictionary
elements which do in fact exist to self-variables?

Or should I be doing this completely differently?


  self.source_name = config.get('source_name', default_value)

Or, if you like this kind of expression better,

  self.source_name = config.get('source_name') or default_value


Won't the latter version misbehave if the value of config['source_name'] has a
"false" boolean value (e.g. "", 0, 0.0, None, [], (), {}, ...)


config = {}
config['source_name'] = ""
config.get('source_name') or 'default'

'default'


Oh, well, picky, picky!  I've always like writing using the "or" form 
and have never gotten bit - especially for configuration-type values 
where you really do expect a non-falsey value, it's probably low risk - 
but of course, you're right. In newer code I have been putting a default 
into get().  And I suppose there is always the possibility that sometime 
in the future an "or" clause like that will be changed to return a 
Boolean, which one would expect anyway.


--
https://mail.python.org/mailman/listinfo/python-list


Re: Configuring an object via a dictionary

2024-03-15 Thread Grant Edwards via Python-list
On 2024-03-15, Thomas Passin via Python-list  wrote:
> On 3/15/2024 5:30 AM, Loris Bennett via Python-list wrote:
>> Hi,
>> 
>> I am initialising an object via the following:
>> 
>>  def __init__(self, config):
>> 
>>  self.connection = None
>> 
>>  self.source_name = config['source_name']
>>  self.server_host = config['server_host']
>>  self.server_port = config['server_port']
>>  self.user_base = config['user_base']
>>  self.user_identifier = config['user_identifier']
>>  self.group_base = config['group_base']
>>  self.group_identifier = config['group_identifier']
>>  self.owner_base = config['owner_base']
>> 
>> However, some entries in the configuration might be missing.  What is
>> the best way of dealing with this?
>> 
>> I could of course simply test each element of the dictionary before
>> trying to use.  I could also just write
>> 
>> self.config = config
>> 
>> but then addressing the elements will add more clutter to the code.
>> 
>> However, with a view to asking forgiveness rather than
>> permission, is there some simple way just to assign the dictionary
>> elements which do in fact exist to self-variables?
>> 
>> Or should I be doing this completely differently?
>
>  self.source_name = config.get('source_name', default_value)
>
> Or, if you like this kind of expression better,
>
>  self.source_name = config.get('source_name') or default_value

Won't the latter version misbehave if the value of config['source_name'] has a
"false" boolean value (e.g. "", 0, 0.0, None, [], (), {}, ...)

>>> config = {}
>>> config['source_name'] = ""
>>> config.get('source_name') or 'default'
'default'



-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Configuring an object via a dictionary

2024-03-15 Thread Thomas Passin via Python-list

On 3/15/2024 5:30 AM, Loris Bennett via Python-list wrote:

Hi,

I am initialising an object via the following:

 def __init__(self, config):

 self.connection = None

 self.source_name = config['source_name']
 self.server_host = config['server_host']
 self.server_port = config['server_port']
 self.user_base = config['user_base']
 self.user_identifier = config['user_identifier']
 self.group_base = config['group_base']
 self.group_identifier = config['group_identifier']
 self.owner_base = config['owner_base']

However, some entries in the configuration might be missing.  What is
the best way of dealing with this?

I could of course simply test each element of the dictionary before
trying to use.  I could also just write

self.config = config

but then addressing the elements will add more clutter to the code.

However, with a view to asking forgiveness rather than
permission, is there some simple way just to assign the dictionary
elements which do in fact exist to self-variables?

Or should I be doing this completely differently?


self.source_name = config.get('source_name', default_value)

Or, if you like this kind of expression better,

self.source_name = config.get('source_name') or default_value

.get() will return None if the key doesn't exist, or the default value 
if you specify one.

--
https://mail.python.org/mailman/listinfo/python-list


Re: Configuring an object via a dictionary

2024-03-15 Thread Mats Wichmann via Python-list

On 3/15/24 03:30, Loris Bennett via Python-list wrote:

Hi,

I am initialising an object via the following:



 self.source_name = config['source_name']


config.get('source_name', default_if_not_defined)  is a common technique...




--
https://mail.python.org/mailman/listinfo/python-list


Configuring an object via a dictionary

2024-03-15 Thread Loris Bennett via Python-list
Hi,

I am initialising an object via the following:

def __init__(self, config):

self.connection = None

self.source_name = config['source_name']
self.server_host = config['server_host']
self.server_port = config['server_port']
self.user_base = config['user_base']
self.user_identifier = config['user_identifier']
self.group_base = config['group_base']
self.group_identifier = config['group_identifier']
self.owner_base = config['owner_base']

However, some entries in the configuration might be missing.  What is
the best way of dealing with this?

I could of course simply test each element of the dictionary before
trying to use.  I could also just write 

   self.config = config

but then addressing the elements will add more clutter to the code.

However, with a view to asking forgiveness rather than
permission, is there some simple way just to assign the dictionary
elements which do in fact exist to self-variables?

Or should I be doing this completely differently?

Cheers,

Loris

-- 
This signature is currently under constuction.
-- 
https://mail.python.org/mailman/listinfo/python-list