hello,here is my idea: var(): input var name (str), outputs var value example:
count1=1.34 var('count',1) 1.34thank you and have a nice day!
On Thu, Jan 2, 2014 at 3:57 AM, Liam Marsh <liam.marsh.home@gmail.com> wrote:
hello,here is my idea: var(): input var name (str), outputs var value example:
count1=1.34 var('count',1) 1.34thank you and have a nice day!
This is underspecified. What should it do for this code? count = 3 def foo(): print var('count', 1) foo() If the output is "1", then you're in luck and can already use vars().get('count', 1) Otherwise, I don't know a trivial one-liner to do it. Either way I'd be -1 on its inclusion in Python, it encourages a bad idiom. -- Devin
On Thu, Jan 02, 2014 at 12:57:49PM +0100, Liam Marsh wrote:
hello,here is my idea: var(): input var name (str), outputs var value example:
count1=1.34 var('count',1) 1.34thank you and have a nice day!
Hello Liam, and welcome! Is this your first post here? I don't recall seeing your name before. I'm afraid I don't quite understand your example above. The "thank you and have a nice day" confuses me, I don't understand where it comes from. Also, I'm not sure why you define a variable count1 = 1.34, and then pass "count", 1 as two separate arguments to the function. So I'm going to try to guess what your idea actually is, or at least what I think is reasonable, if I get it wrong please feel free to correct me. You want a function, var(), which takes a single argument, the name of a variable, and then returns the value of that variable. E.g. given a variable "count1" set to the value 1.34, the function call: var("count1") will return 1.34. Is this what you mean? If so, firstly, the name "var" is too close to the existing function "vars". This would cause confusion. Secondly, you can already do this, or at least *almost* this, using the locals() and globals() functions. Both will return a dict containing the local and global variables, so you can look up the variable name easily using locals() and standard dictionary methods: py> count1 = 1.34 py> locals()['count1'] 1.34 py> locals().get('count2', 'default') 'default' The only thing which is missing is that there's no way to look up a variable name if you don't know which scope it is in. Normally name resolution goes: locals nonlocals globals builtins You can easily look up a local name, or a global name, using the locals() and globals() function. With just a tiny bit more effort, you can also look in the builtins. But there's no way that I know of to look up a nonlocal name, or a name in an unspecified scope. Consequently, this *almost* works: def lookup(name): import builtins for namespace in (locals(), globals(), vars(builtins)): try: return namespace[name] except KeyError: pass raise NameError("name '%s' not found" % name) except for the nonlocal scope. I would have guessed that you could get this working with eval, but if there is such a way, I can't work it out. I think this would make a nice addition to the inspect module. I wouldn't want to see it as a builtin function, since it would encourage a style of programming which I think is poor, but for those occasional uses where you want to look up a variable from an unknown scope, I think this would be handy. -- Steven
dear Jeanpierre, sorry, no. for >>>count1=3, var('count1') or var(str('count',1)) will output 3 in fact, it is even better to use libraries, and it was stupid to send the first email before trying an other way. sorry. 2014/1/2 Devin Jeanpierre <jeanpierreda@gmail.com>
On Thu, Jan 2, 2014 at 3:57 AM, Liam Marsh <liam.marsh.home@gmail.com> wrote:
hello,here is my idea: var(): input var name (str), outputs var value example:
count1=1.34 var('count',1) 1.34
thank you and have a nice day!
This is underspecified. What should it do for this code?
count = 3 def foo(): print var('count', 1) foo()
If the output is "1", then you're in luck and can already use vars().get('count', 1)
Otherwise, I don't know a trivial one-liner to do it. Either way I'd be -1 on its inclusion in Python, it encourages a bad idiom.
-- Devin
On 01/02/2014 02:35 PM, Steven D'Aprano wrote:
On Thu, Jan 02, 2014 at 12:57:49PM +0100, Liam Marsh wrote:
hello,here is my idea: var(): input var name (str), outputs var value example:
count1=1.34 var('count',1) 1.34thank you and have a nice day!
Hello Liam, and welcome! Is this your first post here? I don't recall seeing your name before.
I'm afraid I don't quite understand your example above. The "thank you and have a nice day" confuses me, I don't understand where it comes from. Also, I'm not sure why you define a variable count1 = 1.34, and then pass "count", 1 as two separate arguments to the function. So I'm going to try to guess what your idea actually is, or at least what I think is reasonable, if I get it wrong please feel free to correct me.
You want a function, var(), which takes a single argument, the name of a variable, and then returns the value of that variable. E.g. given a variable "count1" set to the value 1.34, the function call:
var("count1")
will return 1.34.
Is this what you mean?
If so, firstly, the name "var" is too close to the existing function "vars". This would cause confusion.
Secondly, you can already do this, or at least *almost* this, using the locals() and globals() functions. Both will return a dict containing the local and global variables, so you can look up the variable name easily using locals() and standard dictionary methods:
py> count1 = 1.34 py> locals()['count1'] 1.34 py> locals().get('count2', 'default') 'default'
The only thing which is missing is that there's no way to look up a variable name if you don't know which scope it is in. Normally name resolution goes:
locals nonlocals globals builtins
You can easily look up a local name, or a global name, using the locals() and globals() function. With just a tiny bit more effort, you can also look in the builtins. But there's no way that I know of to look up a nonlocal name, or a name in an unspecified scope. Consequently, this *almost* works:
def lookup(name): import builtins for namespace in (locals(), globals(), vars(builtins)): try: return namespace[name] except KeyError: pass raise NameError("name '%s' not found" % name)
except for the nonlocal scope.
I would have guessed that you could get this working with eval, but if there is such a way, I can't work it out.
I think this would make a nice addition to the inspect module. I wouldn't want to see it as a builtin function, since it would encourage a style of programming which I think is poor, but for those occasional uses where you want to look up a variable from an unknown scope, I think this would be handy.
I once used a direct try ... except NameError, which automagically looks up in the whole scope cascade: i = 1 try: x = i except NameError: x = None # no "lookup-able" symbol 'j' try: y = j except NameError: y = None print (x,y) # ==> 1 None Pretty practicle. [Actually, I've never had any need for this in real python code, it was to simulate variable strings (implanted as eg "Hello, {username}!"), which requires variable lookup by name, itself variable. But python already has the final feature (even twice, with % or format).] Denis
On Thu, Jan 2, 2014 at 3:35 AM, Steven D'Aprano <steve@pearwood.info> wrote:
I would have guessed that you could get this working with eval, but if there is such a way, I can't work it out.
It's trivial if you directly invoke eval(): x = 42 def example(): print 'first:', eval('x') y = 'hello world' print 'second:', eval('y') example() will print first: 42 second: hello world Writing Liam's var() as a regular function would require using sys._getframe() and won't access intermediate scopes; something like this would at least find locals and globals: def var(*args): name = ''.join(map(str, args)) # So var('count', 1) is the same as var('count1') frame = sys._getframe(1) # Caller's frame return eval(name, frame.f_globals, frame.f_locals) Now this works as desired: x = 42 def example(): print 'first:', var('x') y = 'hello world' print 'second:', var('y') example() All in all, agreed this doesn't need to be added to the language, given that it's easy enough() to invoke eval() directly. (And advanced programmers tend to use all kinds of other tricks to avoid the need.) Two more things, especially for Liam: (1) There was nothing stupid about your post -- welcome to the Python community! (2) eval() is much more powerful than just variable lookup; if you write a program that asks its user for a variable name and then pass that to eval(), a clever user could trick your program into running code you might not like to run, by typing an expression with a side-effect as the "variable name". But if you're just beginning it's probably best not to worry too much about such possibilities -- most likely you yourself are the only user of your programs! -- --Guido van Rossum (python.org/~guido)
On Thu, Jan 02, 2014 at 02:16:39PM -1000, Guido van Rossum wrote:
On Thu, Jan 2, 2014 at 3:35 AM, Steven D'Aprano <steve@pearwood.info> wrote:
I would have guessed that you could get this working with eval, but if there is such a way, I can't work it out.
It's trivial if you directly invoke eval():
That's what I thought too, but I get surprising results with nonlocals. a = b = "global" def test1(): b = c = "nonlocal" def inner(): d = "local" return (a, b, c, d) return inner() def test2(): b = c = "nonlocal" def inner(): d = "local" c # Need this or the function fails with NameError. return (eval('a'), eval('b'), eval('c'), eval('d')) return inner() assert test1() == test2() # Fails. test1() returns ('global', 'nonlocal', 'nonlocal', 'local'), which is what I expect. But test2() returns ('global', 'global', 'nonlocal', 'local'), which surprises me. If I understand what is going on in test2's inner function, eval('b') doesn't see the nonlocal b so it picks up the global b. (If there is no global b, you get NameError.) But eval('c') sees the nonlocal c because we have a closure, due to the reference to c in the previous line. If there's a way to get eval('b') to return "nonlocal" without having a closure, I don't know it. This suggests to me that you can't reliably look-up a nonlocal from an inner function using eval. -- Steven
Right, that's why I said "won't access intermediate scopes"... On Thursday, January 2, 2014, Steven D'Aprano wrote:
On Thu, Jan 02, 2014 at 02:16:39PM -1000, Guido van Rossum wrote:
On Thu, Jan 2, 2014 at 3:35 AM, Steven D'Aprano <steve@pearwood.info<javascript:;>> wrote:
I would have guessed that you could get this working with eval, but if there is such a way, I can't work it out.
It's trivial if you directly invoke eval():
That's what I thought too, but I get surprising results with nonlocals.
a = b = "global"
def test1(): b = c = "nonlocal" def inner(): d = "local" return (a, b, c, d) return inner()
def test2(): b = c = "nonlocal" def inner(): d = "local" c # Need this or the function fails with NameError. return (eval('a'), eval('b'), eval('c'), eval('d')) return inner()
assert test1() == test2() # Fails.
test1() returns ('global', 'nonlocal', 'nonlocal', 'local'), which is what I expect. But test2() returns ('global', 'global', 'nonlocal', 'local'), which surprises me.
If I understand what is going on in test2's inner function, eval('b') doesn't see the nonlocal b so it picks up the global b. (If there is no global b, you get NameError.) But eval('c') sees the nonlocal c because we have a closure, due to the reference to c in the previous line.
If there's a way to get eval('b') to return "nonlocal" without having a closure, I don't know it. This suggests to me that you can't reliably look-up a nonlocal from an inner function using eval.
-- Steven _______________________________________________ Python-ideas mailing list Python-ideas@python.org <javascript:;> https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/
-- --Guido van Rossum (on iPad)
participants (5)
-
Devin Jeanpierre
-
Guido van Rossum
-
Liam Marsh
-
spir
-
Steven D'Aprano