473,799 Members | 2,734 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

"specialdic t" module

Hello,

in follow-up to the recent "dictionary accumulator" thread, I wrote a
little module with several subclassed dicts.

Comments (e.g. makes it sense to use super), corrections, etc.? Is this
PEP material?

Docstrings, Documentation and test cases are to be provided later.

mfg
Georg

----------------------------------------------------------------------

class defaultdict(dic t):
# _defaulttype: 0=no default, 1=defaultvalue, 2=defaultfactor y
__slots__ = ['_defaulttype', '_default']

def __init__(self, *args, **kwargs):
self._defaultty pe = 0

super(defaultdi ct, self).__init__( self, *args, **kwargs)

def setdefaultvalue (self, value):
self._defaultty pe = 1
self._default = value

def setdefaultfacto ry(self, factory, *args, **kwargs):
if not callable(factor y):
raise TypeError, 'default factory must be a callable'
self._defaultty pe = 2
self._default = (factory, args, kwargs)

def cleardefault(se lf):
self._defaultty pe = 0

def __getitem__(sel f, key):
try:
return super(defaultdi ct, self).__getitem __(key)
except KeyError:
if self._defaultty pe == 0:
raise
elif self._defaultty pe == 1:
return self.setdefault (key, self._default)
else:
return self.setdefault (key,
self._default[0](*self._default[1], **self._default[2]))

class keytransformdic t(dict):
__slots__ = ['_transformer']

def __init__(self, *args, **kwargs):
self._transform er = lambda x: x

super(keytransf ormdict, self).__init__( self, *args, **kwargs)

def settransformer( self, transformer):
if not callable(transf ormer):
raise TypeError, 'transformer must be a callable'
self._transform er = transformer

def __setitem__(sel f, key, value):
super(keytransf ormdict, self).__setitem __(self,
self._transform er(key), value)

def __getitem__(sel f, key):
return super(keytransf ormdict, self).__getitem __(self,
self._transform er(key))

def __delitem__(sel f, key):
super(keytransf ormdict, self).__delitem __(self,
self._transform er(key))

class sorteddict(dict ):
def __iter__(self):
for key in sorted(super(so rteddict, self).__iter__( self)):
yield key

def keys(self):
return list(self.iterk eys())

def items(self):
return list(self.iteri tems())

def values(self):
return list(self.iterv alues())

def iterkeys(self):
return iter(self)

def iteritems(self) :
return ((key, self[key]) for key in self)

def itervalues(self ):
return (self[key] for key in self)

if __name__ == '__main__':
x = sorteddict(a=1, b=3, c=2)

print x.keys()
print x.values()
print x.items()
Jul 18 '05 #1
12 1955
The software you used to post this message wrapped some of the lines of
code. For example:
def __delitem__(sel f, key):
super(keytransf ormdict, self).__delitem __(self,
self._transform er(key))


In defaultdict, I wonder whether everything should be viewed as a
factory:
def setdefaultvalue (self, value):
def factory(): return value
self.setdefault factory(factory )

and the "no-default" mode would either cease to exist, or
def cleardefault(se lf):
def factory():
raise KeyError, "key does not exist and no default defined"
self.setdefault factory(factory )
(too bad that the key isn't available in the factory, this degrades the
quality of the error messge)

if so, __getitem__ becomes simpler:
__slots__ = ['_default']
def __getitem__(sel f, key):
try:
return super(defaultdi ct, self).__getitem __(key)
except KeyError:
return self.setdefault (key, apply(*self._de fault))

I don't ever have an itch for sorted dictionaries, as far as I can
remember, and I don't immediately understand the use of
keytransformdic t. Can you give an example of it?

Jeff

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.6 (GNU/Linux)

iD8DBQFCUCb2Jd0 1MZaTXX0RAujvAJ 4mi7cu3l85k0eeT Usd42UDtGVAzACg p1um
6Iq2DhOo529q83o RXqquZ5I=
=Ytjv
-----END PGP SIGNATURE-----

Jul 18 '05 #2
Jeff Epler wrote:
The software you used to post this message wrapped some of the lines of
code. For example:
def __delitem__(sel f, key):
super(keytransf ormdict, self).__delitem __(self,
self._transform er(key))

Somehow I feared that this would happen.
In defaultdict, I wonder whether everything should be viewed as a
factory:
def setdefaultvalue (self, value):
def factory(): return value
self.setdefault factory(factory )
That's a reasonable approach. __init__ must be changed too, but this
shouldn't hurt too badly.
and the "no-default" mode would either cease to exist, or
def cleardefault(se lf):
def factory():
raise KeyError, "key does not exist and no default defined"
self.setdefault factory(factory )
(too bad that the key isn't available in the factory, this degrades the
quality of the error messge)
That can be worked around with a solution in __getitem__, see below.
if so, __getitem__ becomes simpler:
__slots__ = ['_default']
def __getitem__(sel f, key):
try:
return super(defaultdi ct, self).__getitem __(key)
except KeyError:
return self.setdefault (key, apply(*self._de fault))
You are peculating the kwargs. Also, apply() is on the verge of being
deprecated, so better not use it.

def __getitem__(sel f, key):
try:
return super(defaultdi ct, self).__getitem __(key)
except KeyError, err:
try:
return self.setdefault (key,
self._default[0](*self._default[1],
**self._default[2]))
except KeyError:
raise err

Although I'm not sure whether KeyError would be the right one to raise
(perhaps a custom error?).
I don't ever have an itch for sorted dictionaries, as far as I can
remember, and I don't immediately understand the use of
keytransformdic t. Can you give an example of it?


See the thread "Case-insensitive dict, non-destructive, fast, anyone?",
starting at 04/01/05 12:38.

mfg
Georg
Jul 18 '05 #3
Georg Brandl wrote:
Hello,

in follow-up to the recent "dictionary accumulator" thread, I wrote a
little module with several subclassed dicts.

Comments (e.g. makes it sense to use super), corrections, etc.? Is this
PEP material?

Docstrings, Documentation and test cases are to be provided later.

mfg
Georg


Georg:

A few reactions:

1. Given that these are specializations , why not have:

class defaultvaluedic t(dict):
...

class defaultfactoryd ict(dict):
...

rather than having to jump through hoops to make one implementation satisfy both
cases

2. I would really prefer to have the default value specified in the constructor

I realize that this is tricky due to the kw arguments of dict.__init__, but I
would favor either breaking compatibility with that interface, or adopting some
workaround to make something like d= defaultvaluedic t(__default__ = 0) possible.

One worksaround would be to store the default in the dict, not as an attribute
of the dict. By default the default value would be associated with the key
"__default_ _", but that keyname could be changed for the (I guess very few)
cases where that key conflicted with non-default content of the dict. Then
dict.__init__ would simply take __default__ = value as a keyword argument, as it
does today, and __getitem__ for a missing key would return
dict.__getitem_ _(self, "__default_ _")

Alternatively, you could provide factory functions to construct the defaultdict.
Someone (Michele?) recently posted an implementation of this

3. Can you work in the tally and listappend methods that started this whole
thread off?

4. On super, no I don't think it's necessary or particularly desirable. These
specializations have a close association with dict. dict.method(sel f,...) feels
more appropriate in this case.

Michael
Jul 18 '05 #4
Michael Spencer wrote:
1. Given that these are specializations , why not have:

class defaultvaluedic t(dict):
...

class defaultfactoryd ict(dict):
...

rather than having to jump through hoops to make one implementation satisfy both
cases
I think I like Jeff's approach more (defaultvalues are just special
cases of default factories); there aren't many "hoops" required.
Apart from that, the names just get longer ;)
2. I would really prefer to have the default value specified in the constructor

I realize that this is tricky due to the kw arguments of dict.__init__, but I
would favor either breaking compatibility with that interface, or adopting some
workaround to make something like d= defaultvaluedic t(__default__ = 0) possible.
Too much specialcased for my liking.
One worksaround would be to store the default in the dict, not as an attribute
of the dict. By default the default value would be associated with the key
"__default_ _", but that keyname could be changed for the (I guess very few)
cases where that key conflicted with non-default content of the dict. Then
dict.__init__ would simply take __default__ = value as a keyword argument, as it
does today, and __getitem__ for a missing key would return
dict.__getitem_ _(self, "__default_ _")
I thought about this too (providing a singleton instance named Default,
just like None is, and using it as a key), but you would have to
special-case the (iter)keys,valu es,items methods to exclude the default
- definitely too much work, and too much magic.
Alternatively, you could provide factory functions to construct the defaultdict.
Someone (Michele?) recently posted an implementation of this
Yes, I think this could be reasonable.
3. Can you work in the tally and listappend methods that started this whole
thread off?
They aren't necessary any longer.

Use defaultdict.set defaultvalue(0) instead of the tally approach and
defaultdict.set defaultfactory( list) instead of listappend.
4. On super, no I don't think it's necessary or particularly desirable. These
specializations have a close association with dict. dict.method(sel f,...) feels
more appropriate in this case.


Any other opinions on this?

Thanks for the comments,

mfg
Georg
Jul 18 '05 #5
Georg Brandl wrote:

I think I like Jeff's approach more (defaultvalues are just special
cases of default factories); there aren't many "hoops" required.
Apart from that, the names just get longer ;)
Yes Jeff's approach does simplify the implementation and more-or-less eliminates
my complexity objection

But why do you write:

def __getitem__(sel f, key):
try:
return super(defaultdi ct, self).__getitem __(key)
except KeyError, err:
try:
return self.setdefault (key,
self._default[0](*self._default[1],
**self._default[2]))
except KeyError:
raise err

rather than:

def __getitem__(sel f, key):
return self.setdefault (key,
self._default[0](*self._default[1],
**self._default[2]))

(which could catch AttributeError in the case of _default not set)
I'm sure there's a reason, but I can't see it.

2. I would really prefer to have the default value specified in the constructor ....

Too much specialcased for my liking.
It does set up some gotchas I concede ;-)
....
Alternatively , you could provide factory functions to construct the defaultdict.
Someone (Michele?) recently posted an implementation of this

Yes, I think this could be reasonable.

....though this would more naturally complement a fixed-default dictionary IMO
Your design permits - even encourages (by providing convenient setters) the
default to change over the lifetime of the dictionary. I'm not sure whether
that's good or bad, but it's a feature worth discussing.
3. Can you work in the tally and listappend methods that started this whole
thread off?

They aren't necessary any longer.

Use defaultdict.set defaultvalue(0) instead of the tally approach and
defaultdict.set defaultfactory( list) instead of listappend.


Oops, I see what you mean... then use += or append as required. I still prefer
the clarity of tally for its specific use-case, but it does suffer from lack of
generality.

Michael

Jul 18 '05 #6
Michael Spencer wrote:
Georg Brandl wrote:

I think I like Jeff's approach more (defaultvalues are just special
cases of default factories); there aren't many "hoops" required.
Apart from that, the names just get longer ;)


Yes Jeff's approach does simplify the implementation and more-or-less eliminates
my complexity objection

But why do you write:

def __getitem__(sel f, key):
try:
return super(defaultdi ct, self).__getitem __(key)
except KeyError, err:
try:
return self.setdefault (key,
self._default[0](*self._default[1],
**self._default[2]))
except KeyError:
raise err

rather than:

def __getitem__(sel f, key):
return self.setdefault (key,
self._default[0](*self._default[1],
**self._default[2]))

(which could catch AttributeError in the case of _default not set)
I'm sure there's a reason, but I can't see it.


In your version, the default factory is called every time a value is
retrieved, which might be a performance problem.
Alternativel y, you could provide factory functions to construct the defaultdict.
Someone (Michele?) recently posted an implementation of this

Yes, I think this could be reasonable.

...though this would more naturally complement a fixed-default dictionary IMO
Your design permits - even encourages (by providing convenient setters) the
default to change over the lifetime of the dictionary. I'm not sure whether
that's good or bad, but it's a feature worth discussing.


It's certainly more in the spirit of Python -- we're consenting adults,
and so we are allowed to change the default.

mfg
Georg
Jul 18 '05 #7
Michael Spencer:
Alternatively, you could provide factory functions to construct the defaultdict. Someone (Michele?) recently posted an implementation of this


Yes, here is the link for the ones who missed that thread:

http://groups-beta.google.com/group/...67d30b796423c7

Jul 18 '05 #8
About not using super: you might have problems in multiple inheritance.
Suppose I want to use both your defaultdict and a thirdpartdict. A
subclass

class mydict(defaultd ict, thirdpartdict):
pass

would not work if thirdpartdict requires a non-trivial __init__ , since
without super in defaultdict.__i nit__ you would just call dict.__init__
and not thirdpartdict.

Michele Simionato

Jul 18 '05 #9
Michele Simionato wrote:
About not using super: you might have problems in multiple inheritance.
Suppose I want to use both your defaultdict and a thirdpartdict. A
subclass

class mydict(defaultd ict, thirdpartdict):
pass

would not work if thirdpartdict requires a non-trivial __init__ , since
without super in defaultdict.__i nit__ you would just call dict.__init__
and not thirdpartdict.


Right. I thought about a combined defaultdict/keytransformdic t,
which seems to be easy to create with the current implementation:

class defaultkeytrans formdict(defaul tdict, keytransformdic t):
pass

At least I hope so. This is another argument against the initializing
of defaultfactory or keytransformer in __init__.

mfg
Georg

Here comes the current module (keytransformdi ct should be working now
for all dict methods):

# specialdict - subclasses of dict for common tasks
#

class NoDefaultGiven( Exception):
pass

class defaultdict(dic t):
__slots__ = ['_default']

def __init__(self, *args, **kwargs):
self._defaultty pe = 0

super(defaultdi ct, self).__init__( *args, **kwargs)

def setdefaultvalue (self, value):
def defaultfactory( ):
return value
self._default = (defaultfactory , (), {})

def setdefaultfacto ry(self, factory, *args, **kwargs):
if not callable(factor y):
raise TypeError, 'default factory must be a callable'
self._default = (factory, args, kwargs)

def cleardefault(se lf):
def defaultfactory( ):
raise NoDefaultGiven
self._default = (defaultfactory , (), {})

def __getitem__(sel f, key):
try:
return super(defaultdi ct, self).__getitem __(key)
except KeyError, err:
try:
return self.setdefault (key, self._default[0](*self._default[1], **self._default[2]))
except NoDefaultGiven:
raise err

class keytransformdic t(dict):
__slots__ = ['_transformer']

def __init__(self, *args, **kwargs):
self._transform er = lambda x: x

super(keytransf ormdict, self).__init__( *args, **kwargs)

def settransformer( self, transformer):
if not callable(transf ormer):
raise TypeError, 'transformer must be a callable'
self._transform er = transformer

def __setitem__(sel f, key, value):
print "setitem"
super(keytransf ormdict, self).__setitem __(self._transf ormer(key), value)

def __getitem__(sel f, key):
print "getitem"
return super(keytransf ormdict, self).__getitem __(self._transf ormer(key))

def __delitem__(sel f, key):
super(keytransf ormdict, self).__delitem __(self._transf ormer(key))

def has_key(self, key):
return super(keytransf ormdict, self).has_key(s elf._transforme r(key))

def __contains__(se lf, key):
return self.has_key(ke y)

def get(self, key, default):
return super(keytransf ormdict, self).get(self. _transformer(ke y), default)

def setdefault(self , key, default):
return super(keytransf ormdict, self).setdefaul t(self._transfo rmer(key), default)

def pop(self, key, default):
return super(keytransf ormdict, self).pop(self. _transfomer(key ), default)

def update(self, other=None, **kwargs):
if other is not None:
if hasattr(other, "keys"):
super(keytransf ormdict, self).update((s elf._transforme r(k), other[k]) for k in other.keys())
else:
super(keytransf ormdict, self).update((s elf._transforme r(k), v) for (k, v) in other)
if kwargs:
super(keytransf ormdict, self).update((s elf._transforme r(k), v) for (k, v) in kwargs.iteritem s())

class sorteddict(dict ):
def __iter__(self):
for key in sorted(super(so rteddict, self).__iter__( )):
yield key

def keys(self):
return list(self.iterk eys())

def items(self):
return list(self.iteri tems())

def values(self):
return list(self.iterv alues())

def iterkeys(self):
return iter(self)

def iteritems(self) :
return ((key, self[key]) for key in self)

def itervalues(self ):
return (self[key] for key in self)
Jul 18 '05 #10

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

Similar topics

2
1570
by: Jim Jewett | last post by:
I have often wanted to pass arguments to a module. Tyically, these are globals, such as DEBUG or VERBOSE that are set at the top of the module -- and I want to use a different value. For modules that provide a service (such as logging), I would like to make my changes before the defaults are set up. Assuming that the loaded module is cooperative, what is the least ugly way to pass these parameters?
8
3868
by: Bo Peng | last post by:
Dear list, I am writing a Python extension module that needs a way to expose pieces of a big C array to python. Currently, I am using NumPy like the following: PyObject* res = PyArray_FromDimsAndData(1, int*dim, PyArray_DOUBLE, char*buf); Users will get a Numeric Array object and can change its values (and actually change the underlying C array).
5
2020
by: dody suria wijaya | last post by:
I found this problem when trying to split a module into two. Here's an example: ============== #Module a (a.py): from b import * class Main: pass ============== ==============
3
16520
by: David T. Ashley | last post by:
Hi, Red Hat Enterprise Linux 4.X. I'm writing command-line PHP scripts for the first time. I get the messages below. What do they mean? Are these operating system library modules, or something in PHP that I don't have? Do I need to install more Linux packages? Or adjust PHP in some way?
10
5500
by: Bonzol | last post by:
vb.net Hey there, could someone just tell me what the differnce is between classes and modules and when each one would be used compared to the other? Any help would be great Thanx in advance
21
34444
KevinADC
by: KevinADC | last post by:
Note: You may skip to the end of the article if all you want is the perl code. Introduction Uploading files from a local computer to a remote web server has many useful purposes, the most obvious of which is the sharing of files. For example, you upload images to a server to share them with other people over the Internet. Perl comes ready equipped for uploading files via the CGI.pm module, which has long been a core module and allows users...
40
3503
by: rjcarr | last post by:
Sorry if this is a completely newbie question ... I was trying to get information about the logging.handlers module, so I imported logging, and tried dir(logging.handlers), but got: AttributeError: 'module' object has no attribute 'handlers' The only experience I have in modules is os and os.path ... if I do the same thing, simply import os and then type dir(os.path), it displays the contents as expected.
4
2184
by: rkmr.em | last post by:
Hi I have a function data, that I need to import from a file data, in the directory data If I do this from python interactive shell (linux fedora core 8) from dir /home/mark it works fine: cwd = data os.chdir(cwd) print os.getcwd()
0
2171
by: Fredrik Lundh | last post by:
Jeff Dyke wrote: so how did that processing use the "mymodulename" name? the calling method has nothing to do with what's considered to be a local variable in the method being called, so that only means that the name is indeed available in the global scope.
6
2275
by: dudeja.rajat | last post by:
Hi, I found on the net that there is something called module initialization. Unfortunately, there is not much information for this. However, small the information I found module initialization can be of use to me in my project. I'm currently messing with a problem where I'm keeping my global variables ( or symbols) in a module and the other mdoules in the project acess these global variables.
0
9688
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
9544
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
10490
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10259
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...
0
10030
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...
1
7570
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6809
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5467
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...
1
4145
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system

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.