473,748 Members | 7,827 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

acting on items passed to a method via a dictiomary

The following method is defined in one of my classes:

def setup(self, items={}):
"""perform setup based on a dictionary of items"""
if 'something' in items:
value = items['something']
# now do something with value
if 'another' in items:
value = items['another']
# do something else with value
if 'spam' in items:
value = items['spam']
# do yet another thing with value
if 'eggs' in items:
value = items['eggs']
# and so on

The purpose is to set up the object based on values contained in a
dictionary passed to the setup() method. The dictionary may be empty, or
it may contain a variable number of items, and it may contain items not
looked for by the setup() method. Moreover, this method may be
overridden in subclasses. The approach described above works ok, so I
suppose I should leave well enough alone, but I have this nagging
feeling that Python has a way to do this more simply or more elegantly.
Any suggestion?

Donnal Walter
Arkansas Children's Hospital
Jul 18 '05 #1
12 1905
Donnal Walter wrote:
The following method is defined in one of my classes:

def setup(self, items={}):
"""perform setup based on a dictionary of items"""
if 'something' in items:
value = items['something']
# now do something with value
if 'another' in items:
value = items['another']
# do something else with value
if 'spam' in items:
value = items['spam']
# do yet another thing with value
if 'eggs' in items:
value = items['eggs']
# and so on

Any suggestion?


First of all, don't use {} as default value for items. Many have stepped
into this trap: While perfectly legal, it will be evaluated only once, when
the method setup is found the first time. So then an instance of a dict is
created. But now if subsequent calls to setup alter that dict items points
to, they all share the same dict!! This small example illustrates that
behaviour:

def foo(key, bar={}):
bar[key] = key
print bar

for i in xrange(3):
foo(i)

yields:

{1:1}
{1:1, 2:2}

where you surely have expected {2:2} in the second case. So the idiom for
this commonly is this:

def foo(key, bar=None):
if bar is None:
bar = {} # remember: bar is a local name, bound to a value - so next
time, bar will still be none if foo is called w/o bar as parameter
bar[key] = key

Now to your question: This works:

for k in ['something', 'another', 'spam', 'eggs']:
if items.has_key(k ):
value = items[k]
break
--
Regards,

Diez B. Roggisch
Jul 18 '05 #2
>>>>> "Donnal" == Donnal Walter <do****@donnal. net> writes:

Donnal> if 'something' in items:
Donnal> value = items['something']
Donnal> # now do something with value
Donnal> if 'another' in items:
Donnal> value = items['another']
Donnal> # do something else with value

Donnal> overridden in subclasses. The approach described above
Donnal> works ok, so I suppose I should leave well enough alone,
Donnal> but I have this nagging feeling that Python has a way to
Donnal> do this more simply or more elegantly. Any suggestion?

The code is quite ok - you might avoid the repetition of 'something'
by using

a.get(k[, x])

# a[k] if k in a, else x

If you feel 'clever' and don't care about performance (no, I didn't
benchmark this):

-----
def dictget(d, key):
if key in d:
yield d[key]
return

d = { 'spam' : 1, 'eggs' : 67 }

for value in dictget(d,'spam '):
print value

for value in dictget(d,'larc h'):
print value + 999 # never printed
for value in dictget(d,'eggs '):
print value + 2
-----

Well well, that's almost cookbook material even if I say so myself... ;-)

--
Ville Vainio http://tinyurl.com/2prnb
Jul 18 '05 #3
On Fri, 15 Oct 2004 11:56:12 -0500, Donnal Walter wrote:
The following method is defined in one of my classes:

def setup(self, items={}):
"""perform setup based on a dictionary of items"""
if 'something' in items:
value = items['something']
# now do something with value

....

It mostly depends on the contents of the "do something with value" that
you have peppered throughout. I would pull out the various "do somethings"
into methods, but other then that, if you need the full flexibility of a
dict that can contain anything and you need to do things with arbitrary
combinations, there is little else to do.

After pulling things out into methods, I'd actually shift the "if"
statement into the method and do something like the following:

def setup(self, items = None):
if items is None:
items = {}

self.items = items

for method in ('something', 'another', 'spam', 'eggs'):
getattr(self, method)()

which will make it more flexible in the long term.

A few other things leap to mind (might want to separate the self.item
setting from the loop, so children can override the loop without messing
up items in calls to the super class; if you don't know what I mean
because I'm being somewhat vague here, don't worry :-) ), but that's about
all you can do without getting silly.
Jul 18 '05 #4
>>>>> "Ville" == Ville Vainio <vi***@spammers .com> writes:

Ville> def dictget(d, key):
Ville> if key in d:
Ville> yield d[key]
Ville> return

After putting down the crack pipe, I realized you can also do

def dictget(d,key):
if key in d:
return [d[key]]
return []

which is slightly less clever/cute. Too lazy to compare performance
right now.
--
Ville Vainio http://tinyurl.com/2prnb
Jul 18 '05 #5
Jeremy Bowers <je**@jerf.or g> wrote in message news:<pa******* *************** ******@jerf.org >...
On Fri, 15 Oct 2004 11:56:12 -0500, Donnal Walter wrote:
The following method is defined in one of my classes:

def setup(self, items={}):
"""perform setup based on a dictionary of items"""
if 'something' in items:
value = items['something']
# now do something with value

...

It mostly depends on the contents of the "do something with value" that
you have peppered throughout. I would pull out the various "do somethings"
into methods, but other then that, if you need the full flexibility of a
dict that can contain anything and you need to do things with arbitrary
combinations, there is little else to do.

After pulling things out into methods, I'd actually shift the "if"
statement into the method and do something like the following:

def setup(self, items = None):
if items is None:
items = {}

self.items = items

for method in ('something', 'another', 'spam', 'eggs'):
getattr(self, method)()

which will make it more flexible in the long term.

A few other things leap to mind (might want to separate the self.item
setting from the loop, so children can override the loop without messing
up items in calls to the super class; if you don't know what I mean
because I'm being somewhat vague here, don't worry :-) ), but that's about
all you can do without getting silly.


I agree with Jeremy here that everything depends on what "do something
with value" means.

After looking over this thread though, it appears to me that having
the 'setup()' method perform a dispatch operation using a dictionary
defined at class scope would be an easy, and extensible choice.

This way, one would not have to override the 'setup' method in derived
classes, rather one would only have to replace the class level
dispatch map, which in the examples below is named 'setupMap'.

Consider the following code, which would take a list or tuple to the
setup function.

class ListSetup:

def setup(self, items = None):
if items is None:
items = ()
#Note, here a list is being used instead of a dictionary
for item in items:
if self.setupMap.h as_key(item): #Ignore extra items
self.setupMap[item](self)

def setupfunction1( self):
print "Called ListSetup.setup function1"

def setupfunction2( self):
print "Called ListSetup.setup function2"

#This is the key to the whole thing -> a dictionary used for
#dispatching the correct calls
setupMap = {'something':se tupfunction1, 'another':setup function2}
The key is in the class scope dictionary 'setupMap'. If a key is
provided in the setup call, each of the appropropiate member functions
will be called.

On the other hand, if the 'values' stored in the dictionary passed in
are also important, we can incorporate that into our solution, by
passing them to our setupfunctionX methods as arguments.

Here is a similar solution, using an items dictionary:

class DictSetup:

def setup(self, items = None):
if items is None:
items = {}
#Note, here we are expecting a dictionary
for key in items.keys():
if self.setupMap.h as_key(key): #Ignore extra items
self.setupMap[key](self, items[key])

def setupfunction1( self, value):
print "Called DictSetup.setup function1 with value", value

def setupfunction2( self, value):
print "Called DictSetup.setup function2 with value", value

#Again, this is the key to the whole thing -> a dictionary used
#for dispatching the correct calls
setupMap = {'something':se tupfunction1, 'another':setup function2}

I hope this helps!

Michael Loritsch
Jul 18 '05 #6
Diez B. Roggisch <de*********@we b.de> wrote:
Donnal Walter wrote:
The following method is defined in one of my classes:

def setup(self, items={}):
... First of all, don't use {} as default value for items. Many have stepped
into this trap: While perfectly legal, it will be evaluated only once, when
the method setup is found the first time. So then an instance of a dict is
created. But now if subsequent calls to setup alter that dict items points
to, they all share the same dict!! This small example illustrates that


However, there are no problems whatsoever with the issue you remark on,
as long as the method never alters the 'items' object. As long as only
nonmutating methods get called on 'items', i.e., 'items' is practically
treated as "read-only", Donnal Walter's approach is just fine. The
issue you remark on does deserve to be made, but it's also important to
understand when it does matter and when it doesn't.
Alex
Jul 18 '05 #7
Donnal Walter <do****@donnal. net> wrote:
The following method is defined in one of my classes:

def setup(self, items={}):
"""perform setup based on a dictionary of items"""
if 'something' in items:
value = items['something']
# now do something with value
if 'another' in items:
value = items['another']
# do something else with value
if 'spam' in items:
value = items['spam']
# do yet another thing with value
if 'eggs' in items:
value = items['eggs']
# and so on


The various 'do something', 'do something else', etc, pieces of code,
need to be factored out into methods or functions reachable on the basis
of the related names, 'something', 'another', etc. Depending on exacly
what the various 'somethings' are that you want to do, you might be
happier with placing them in other methods of this class with names
constructed in a systematic way from the related names (this makes it
feasible for subclasses to override some part of them) or local
functions in a dictionary (if you're keen to stop subclasses from
overriding only some part of this processing).

Normally one does want to allow subclasses more flexibility rather than
less (extended variants of the "Template Method" design pattern are very
abundant in the Python standard library, exactly because of this), so,
you might want to do something like...:

class Base(object):

crucial_names = 'something another spam eggs and so on'.split()

def method_name(sel f, crucial_name): return 'handle_'+cruci al_name

def handle_somethin g(self, value): print 'something is', value
def handle_eggs(sel f, value): print 'over easy for', value
# other handle_... deliberately omitted, default to no-op

def setup(self, items={}):
for crucial_name in self.crucial_na mes:
if crucial_name in items:
metname = self.method_nam e(crucial_name)
method = getattr(self, metname, None)
if method: method(items[crucial_name])

This lets a subclass alter the list of "crucial names" (via the highly
Pythonic concept of "data override"), as well as the processing to be
performed for each "crucial name", and even the way a method name is
constructed from the "crucial name". Of course there are many design
decisions here that you may want to tweak or reverse, depending on your
exact need -- e.g., it may be that in your case a missing method should
not be a plain no-op but a serious error warranting an exception.

Do notice a little detail: it's typically important that the method_name
method 'augment' the crucial_name argument in such a way that the
resulting string cannot possibly be a Python keyword. For example, if
you had 'def method_name(sel f, crucial_name): return crucial_name' the
handling of crucial name 'and' might be bothersome, since it's a Python
keyword; if you used, e.g., "return 'a'+crucial_nam e", a subclass would
have similar problems if it wanted to have 'nd' as a crucial name
(unless it overrode method_name and reimplemented all the existing
handling methods, probably not worth the bother)... it would be feasible
to work around such problems, but it's better to design method_name so
as to avoid the problems arising in the first place!-)
Alex
Jul 18 '05 #8
> However, there are no problems whatsoever with the issue you remark on,
as long as the method never alters the 'items' object. As long as only
nonmutating methods get called on 'items', i.e., 'items' is practically
treated as "read-only", Donnal Walter's approach is just fine. The
issue you remark on does deserve to be made, but it's also important to
understand when it does matter and when it doesn't.


You are right of course, but the high frequency of postings regarding
"strange default value behaviour" made me want to make this point before
Donnal steps into that pitfall. And while the example at hand didn't alter
the contents of items, I'd nevertheless settled for items=None and used
something like this:

def foo(items=None) :
if not items is None:
....
--
Regards,

Diez B. Roggisch
Jul 18 '05 #9
On Sun, 17 Oct 2004 19:33:32 +0200, "Diez B. Roggisch" <de*********@we b.de> wrote:
However, there are no problems whatsoever with the issue you remark on,
as long as the method never alters the 'items' object. As long as only
nonmutating methods get called on 'items', i.e., 'items' is practically
treated as "read-only", Donnal Walter's approach is just fine. The
issue you remark on does deserve to be made, but it's also important to
understand when it does matter and when it doesn't.


You are right of course, but the high frequency of postings regarding
"strange default value behaviour" made me want to make this point before
Donnal steps into that pitfall. And while the example at hand didn't alter
the contents of items, I'd nevertheless settled for items=None and used
something like this:

def foo(items=None) :
if not items is None:
....


I like to use the idiom

def foo(items=None) :
if items is None: items = {} # or whatever non-shared mutable
...

Regards,
Bengt Richter
Jul 18 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
1374
by: Kay | last post by:
I have a problem in inserting items in linked list. Hence, there are different way to insert the items to the list. The first one is loading data form a txt file(1). And the second one is input from keyboard. I have done the first part. I have got a question in second part. Do I need to continue the insertion by using the (1) linked list and its position ? If yes, how to return the ptr and list position ? Can I do sth like this ? If yes,...
4
1764
by: Lynn Morrison | last post by:
I cannot find this feature at all. There is no bitmap property for menu items nor is there an imagelist property for the menu itself... How do I put images to the left of menu items? Thanks, Lynn
1
1345
by: Bryan | last post by:
in the python cookbook 2nd edition, section 6.7 (page 250-251), there a problem for implementing tuples with named items. i'm having trouble understanding how one of commands work and hope someone here can explain what exactly is going on. without copying all the code here, here is the gist of the problem: from operator import itemgetter class supertup(tuple): def __new__(cls, *args): return tuple.__new__(cls, args)
6
4947
by: Bob Kochem | last post by:
I am looking for a way via code to access all the menu itmes on a given form. I am looking for something like the Forms or Controls collections, but for menu items. Is there such a thing or method? I would prefer to avoid using the Win API but will do so if that's the only way available. This is for a language-translation (of an existing program) where I wish to change (English to Spanish initially) the Descriptions for all the menu...
4
1313
by: Panos Laganakos | last post by:
I want a class method to take action depending on the type of the arguement passed to it. ie: getBook(id) # get the book by ID getBook(name) # get the book by name .... Other languages use the term function/method overloading to cope with this. And when I googled about it seems that GvR is testing it for 3.0
14
18748
by: Paul_Madden via DotNetMonster.com | last post by:
Basically I have a listbox to which I add simple STRING items- I have a progress bar which I increment whenever I populate another portion of the complete set of items I wish to add. What I observe is that as more and more are added, population of the list box takes longer and longer. ie the first 10th of the item set are added much much quicker than the last 10th. THis occurs with about 40,000 listbox items. My worry is the listbox may...
0
1526
by: Gordon.E.Anderson | last post by:
short description: i've got a .net web site set up using a tableadapter attached to a sql server table - returning results only, no update of data. i've got a query (qry code below) set up to search and return based on description. i've got a textbox on an aspx page for input of the search term (@DESC). when i put in T% into the textbox on the aspx page i get 0 results - if i put in T% for @DESC in the query builder and preview the...
3
15297
by: Reg | last post by:
Hello, Is it possible to create WCF Web Service that runs without IIS? Any tips how to do it? Cheers, Reg
3
7835
HaLo2FrEeEk
by: HaLo2FrEeEk | last post by:
Ok, I have a menuStrip and a toolStrip. the menuStrip is laid out like this: Actions Connect Disconnect - Exit Pretty simple. The toolstrip has 1 item, a toolstripstatus. I decided I wanted to add a little icon next to the status text, so I opened up the image property in Design mode and imported 2 images. Both were PNG images and were 256x256 resolution. I decided that I wanted to use smaller versions since it was, after...
0
8987
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8826
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9366
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
9316
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9241
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8239
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
4597
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4867
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
2777
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.