Dictionary self lookup

N

Norberto Lopes

Hi all.
Assuming that python dictionaries already provide a bit of "shoot
yourself in the foot", I think what I have in mind would not be so
bad.

What do you think of dictionaries having a self lookup in their
declaration?

Be able to do this:

a = {"foo" : "foo1", "bar" : a["foo"]} # or with another syntax

instead of:

a = { "foo" : "foo1" }
a["bar"] = a["foo"]

Maybe I'm murdering python syntax/philosophy right here so let me know
if that's the case.
I was thinking this could probably be done in python abstract tree but
as I never looked into it I may be wrong. I'm willing to make the
effort, provided I get some directions and that this idea is worth it.

Any feedback is welcome.

Cheers,
Norberto
 
D

Diez B. Roggisch

Norberto said:
Hi all.
Assuming that python dictionaries already provide a bit of "shoot
yourself in the foot", I think what I have in mind would not be so
bad.

What kind of foot-shooting do you have in mind?
What do you think of dictionaries having a self lookup in their
declaration?

Be able to do this:

a = {"foo" : "foo1", "bar" : a["foo"]} # or with another syntax

instead of:

a = { "foo" : "foo1" }
a["bar"] = a["foo"]

Maybe I'm murdering python syntax/philosophy right here so let me know
if that's the case.
I was thinking this could probably be done in python abstract tree but
as I never looked into it I may be wrong. I'm willing to make the
effort, provided I get some directions and that this idea is worth it.

Any feedback is welcome.

Obviously the proposed syntax can't work, as at the time of the dictionary
construction the name the dict is bound to is either not known, or even
bound to *another* dict.

Additionally, the code would be by no means more efficient than the
above "long" version, as whatever notation you chose, it won't help to deal
with the fact that the dict-object itself, and also a potentially reference
key, aren't already available.

So behind the curtain, the exact same logic would apply, with all
runtime-costs.

Which leaves us with the question: why the heck do you want this?

Diez
 
C

Chris Rebert

Hi all.
Assuming that python dictionaries already provide a bit of "shoot
yourself in the foot", I think what I have in mind would not be so
bad.

What do you think of dictionaries having a self lookup in their
declaration?

Be able to do this:

a = {"foo" : "foo1", "bar" : a["foo"]} # or with another syntax

instead of:

a = { "foo" : "foo1" }
a["bar"] = a["foo"]

Maybe I'm murdering python syntax/philosophy right here so let me know
if that's the case.

The idea sounds quite confusing and seems unnecessary.

Specifically, your proposal appears to contravene the following points
of the holy Zen of Python:

- Explicit is better than implicit.
- Readability counts.
- Special cases aren't special enough to break the rules.
- In the face of ambiguity, refuse the temptation to guess.
- If the implementation is hard to explain, it's a bad idea.

Cheers,
Chris
 
D

Diez B. Roggisch

Norberto said:
Hi all.
Assuming that python dictionaries already provide a bit of "shoot
yourself in the foot", I think what I have in mind would not be so
bad.

What do you think of dictionaries having a self lookup in their
declaration?

Be able to do this:

a = {"foo" : "foo1", "bar" : a["foo"]} # or with another syntax

instead of:

a = { "foo" : "foo1" }
a["bar"] = a["foo"]

Maybe I'm murdering python syntax/philosophy right here so let me know
if that's the case.
I was thinking this could probably be done in python abstract tree but
as I never looked into it I may be wrong. I'm willing to make the
effort, provided I get some directions and that this idea is worth it.

Any feedback is welcome.

I doubt this will ever be accepted, but out of curiosity: *why* do you want
this?

And if you are willing to put some constraints on you keys, it would be easy
enough to do this:

def wicked_dict(**kwargs):
mappings = [(name, source) for name, source in kwargs.iteritems() if
name.startswith("_")
res = dict((key, value) for key, value in kwarges.iteritems() if not
name.startswith("_"))
for name, source in mappings:
res[name] = res[source]
return res


Diez
 
N

Norberto Lopes

What kind of foot-shooting do you have in mind?

a = { "foo" : { "bar" : "moo" }}
a["bar"] = a["foo"]
print a
{'foo': {'bar': 'moo'}, 'bar': {'bar': 'moo'}}
a["foo"]["bar"] = a["foo"]
print a
{'foo': {'bar': {...}}, 'bar': {'bar': {...}}}

(I know it's not a C shoot in the foot or something but still...)
What do you think of dictionaries having a self lookup in their
declaration?
Be able to do this:
a = {"foo" : "foo1", "bar" : a["foo"]} # or with another syntax
instead of:
a = { "foo" : "foo1" }
a["bar"] = a["foo"]
Maybe I'm murdering python syntax/philosophy right here so let me know
if that's the case.
I was thinking this could probably be done in python abstract tree but
as I never looked into it I may be wrong. I'm willing to make the
effort, provided I get some directions and that this idea is worth it.
Any feedback is welcome.

Obviously the proposed syntax can't work, as at the time of the dictionary
construction the name the dict is bound to is either not known
With just more thatn syntactic sugar this could be done
, or even bound to *another* dict.
doh! Didn't thought about that one. Nice catch.
Additionally, the code would be by no means more efficient than the
above "long" version, as whatever notation you chose, it won't help to deal
with the fact that the dict-object itself, and also a potentially reference
key, aren't already available.

So behind the curtain, the exact same logic would apply, with all
runtime-costs.

Which leaves us with the question: why the heck do you want this?
Syntactic sugar basically. I'm not ranting about performance, just
easier write up.

config = {"home" : "/home/test", "user1": config["home"] + "/user1",
"user2" : config["home"] + "/user2", "python-dev" : config["user1"] +
"/Projects/py-dev" }

config = {"home" : "/home/test"}
config["user1"] = config["home"] + "/user1"
config["user2"] = config["home"] + "/user2"
config["python-dev"] = config["user1"] + "/py-dev"


Now, if you change config["home"] you'd have to redo all of the other
entries. With the first one (assuming pointers to the entries)
everything would get updated. Although python does not handles dict
keys/values this way. Now that I think of this there would be a lot
more than just syntactic sugar for this.

(ignore the path concatenation without os.path)
 
N

Norberto Lopes

Hi all.
Assuming that python dictionaries already provide a bit of "shoot
yourself in the foot", I think what I have in mind would not be so
bad.
What do you think of dictionaries having a self lookup in their
declaration?
Be able to do this:
a = {"foo" : "foo1", "bar" : a["foo"]} # or with another syntax
instead of:
a = { "foo" : "foo1" }
a["bar"] = a["foo"]
Maybe I'm murdering python syntax/philosophy right here so let me know
if that's the case.

The idea sounds quite confusing and seems unnecessary.

Specifically, your proposal appears to contravene the following points
of the holy Zen of Python:

- Explicit is better than implicit.
- Readability counts.
- Special cases aren't special enough to break the rules.
- In the face of ambiguity, refuse the temptation to guess.
- If the implementation is hard to explain, it's a bad idea.

Cheers,
Chris
--http://blog.rebertia.com


Ok, no arguments against this one :(

/agree
 
D

Diez B. Roggisch

Norberto said:
What kind of foot-shooting do you have in mind?

a = { "foo" : { "bar" : "moo" }}
a["bar"] = a["foo"]
print a
{'foo': {'bar': 'moo'}, 'bar': {'bar': 'moo'}}
a["foo"]["bar"] = a["foo"]
print a
{'foo': {'bar': {...}}, 'bar': {'bar': {...}}}

(I know it's not a C shoot in the foot or something but still...)

And something working alike for lists and objects. Cyclic references are a
fact of (programming)-life unless you go fully functional - and then you'd
certainly miss it sometimes..
config = {"home" : "/home/test"}
config["user1"] = config["home"] + "/user1"
config["user2"] = config["home"] + "/user2"
config["python-dev"] = config["user1"] + "/py-dev"


Now, if you change config["home"] you'd have to redo all of the other
entries. With the first one (assuming pointers to the entries)
everything would get updated. Although python does not handles dict
keys/values this way. Now that I think of this there would be a lot
more than just syntactic sugar for this.

Things that are re-done usually are useful being put into a function. Then
redoing becomes easier :)

Diez
 
N

Norberto Lopes

a = { "foo" : { "bar" : "moo" }}
a["bar"] = a["foo"]
print a
{'foo': {'bar': 'moo'}, 'bar': {'bar': 'moo'}}
a["foo"]["bar"] = a["foo"]
print a
{'foo': {'bar': {...}}, 'bar': {'bar': {...}}}
(I know it's not a C shoot in the foot or something but still...)

And something working alike for lists and objects. Cyclic references are a
fact of (programming)-life unless you go fully functional - and then you'd
certainly miss it sometimes..
Yes. (and sometimes you miss functional :D)
config = {"home" : "/home/test"}
config["user1"] = config["home"] + "/user1"
config["user2"] = config["home"] + "/user2"
config["python-dev"] = config["user1"] + "/py-dev"
Now, if you change config["home"] you'd have to redo all of the other
entries. With the first one (assuming pointers to the entries)
everything would get updated. Although python does not handles dict
keys/values this way. Now that I think of this there would be a lot
more than just syntactic sugar for this.

Things that are re-done usually are useful being put into a function. Then
redoing becomes easier :)

Diez

True.
In any case, reading from your pov, it seems that the solution would
cause more problems than solving one.

Thanks for the feedback though.
Much appreciated :)
 
N

Norberto Lopes

Norberto said:
Norberto Lopes wrote: ...
config = {"home" : "/home/test"}
config["user1"] = config["home"] + "/user1"
config["user2"] = config["home"] + "/user2"
config["python-dev"] = config["user1"] + "/py-dev"

I'd write this as:
    home = "/home/test"
    config = {"home" : home, "user1" : home + "/user1",
              "user2" : home + "/user2", "python-dev" : home + "/py-dev"}

or even (if the list gets much longer):

    home = "/home/test"
    config = {"home" : "", "user1" : "/user1", "user2" : "/user2",
              "python-dev" : "/py-dev"}
    for key, entry in config.iteritems():
        config[key] = home + entry

--Scott David Daniels
(e-mail address removed)

Yeah, there are a lot of options. That was just an example. Btw, I had
"python-dev" depending on "user1" and "user1" depending on "home"
precisely so that the way you suggested would get complicated. Yours
examples fail in the python-dev key-value. You'd need an "extra"
step ;)
 
C

Carl Banks

Hi all.
Assuming that python dictionaries already provide a bit of "shoot
yourself in the foot", I think what I have in mind would not be so
bad.

What do you think of dictionaries having a self lookup in their
declaration?

Be able to do this:

a = {"foo" : "foo1", "bar" : a["foo"]} # or with another syntax

instead of:

a = { "foo" : "foo1" }
a["bar"] = a["foo"]

Maybe I'm murdering python syntax/philosophy right here so let me know
if that's the case.
I was thinking this could probably be done in python abstract tree but
as I never looked into it I may be wrong. I'm willing to make the
effort, provided I get some directions and that this idea is worth it.

Any feedback is welcome.


If you don't mind abusing Python syntax, you can do it using something
like this:


def DictMaker(name,bases,dct):
dct.pop('__metaclass__',None)
return dct


class a:
__metaclass__ = DictMaker

home = "/home/test"
user1 = home + "/user1"
user2 = home + "/user2"
python_dev = user1 + "/py-dev"


print a



Carl Banks
 
G

Gabriel Genellina

What do you think of dictionaries having a self lookup in their
declaration?

Be able to do this:

a = {"foo" : "foo1", "bar" : a["foo"]} # or with another syntax

instead of:

a = { "foo" : "foo1" }
a["bar"] = a["foo"]

If you don't mind abusing Python syntax, you can do it using something
like this:


def DictMaker(name,bases,dct):
dct.pop('__metaclass__',None)
return dct


class a:
__metaclass__ = DictMaker

home = "/home/test"
user1 = home + "/user1"
user2 = home + "/user2"
python_dev = user1 + "/py-dev"

Certainly an abuse of syntax, but it's a nice trick!
 
J

Jure Erznožnik

Norberto,

While certainly useful, this kind of functionality contradicts the way
today's "string" libraries work.
What you are proposing isn't dict self referencing, but rather strings
referencing other external data (in this case other strings from the
same dict).

When you write code like
config = {"home" : "/home/test"}
config["user1"] = config["home"] + "/user1"

config["user1"] isn't stored in memory as config["home"] + "/user1",
but as a concatenated string ("/home/test/user1"), composed of both
those strings. The reference to original composing strings is lost at
the moment the expression itself is evaluated to be inserted into the
dict.
There's no compiler / interpreter that would do this any other way. At
least not that I know of.

So best suggestion would be to simply do an object that would parse
strings before returning them. In the string itself, you can have
special blocks that tell your parser that they are references to other
objects. You can take good old DOS syntax for that: "%variable%" or
something more elaborate if "%" is used in your strings too much.

Anyway, your code would then look like (one possible way):
config = {"home" : "/home/test"}
config["user1"] = "%config["home"]%" + "/user1"

or

config = {"home" : "/home/test", "user1" : "%config[\"home\"]%/user1"}

The parser would then just match "%(something)%" and replace it with
actual value found in referenced variable. Eval() can help you there.
Maybe there's already something in Python's libraries that matches
your need.

But you sure better not expect this to be included in language syntax.
It's a pretty special case.

Jure
 
C

Carl Banks

When you write code like
config = {"home" : "/home/test"}
config["user1"] = config["home"] + "/user1"

config["user1"] isn't stored in memory as config["home"] + "/user1",
but as a concatenated string ("/home/test/user1"), composed of both
those strings. The reference to original composing strings is lost at
the moment the expression itself is evaluated to be inserted into the
dict.
There's no compiler / interpreter that would do this any other way. At
least not that I know of.

It's called Lazy Evaluation and there are a bunch of tools that do it
implicitly and automatically. Off hand I can think of make and
Mathematica. I know there are some functional programming languages
that do it as well.

Also there are languages like Lisp that have strong syntactic support
for lazy evaluation although it's not done implicitly.

Not Python, though.

So best suggestion would be to simply do an object that would parse
strings before returning them. In the string itself, you can have
special blocks that tell your parser that they are references to other
objects.

[snip example]
But you sure better not expect this to be included in language syntax.
It's a pretty special case.

That is a very good suggestion that might be a better solution to the
OP's problem.

You are right that is would require a bit of work. Python does have
string interpolation methods that can do keyword-based substitution,
but they don't work recursively, and it's not straightforward to get
it to work recursively.


Carl Banks
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top