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() 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-----
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
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
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
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
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
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
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
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) This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
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?
|
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).
|
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
==============
==============
|
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?
|
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
| |
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...
|
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.
|
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()
|
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.
|
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.
|
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...
| |
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,...
|
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...
|
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...
|
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...
|
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...
|
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();...
| |
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...
|
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
| |