RE: Configuring an object via a dictionary
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
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
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
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
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
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
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
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
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