2

In lisp you can say:

(setf (aref a 1) 5)

In perl you can say:

substr( $string, $start, $stop ) =~ s/a/b/g

Is it possible something like this in python? I mean is it possible to use function result as a lvalue (as a target for assignment operation)?

Igor Chubin
  • 61,765
  • 13
  • 122
  • 144
  • possible duplicate of [Returning an lvalue from a function in python](http://stackoverflow.com/questions/9965115/returning-an-lvalue-from-a-function-in-python) – Wooble Jul 31 '12 at 21:48
  • 1
    I don't think it is. This deals with dynamically creating variables by name that are generated by a function, whereas your post ended up dealing with data structures. If someone had actually answered his question, it would be a duplicate, but they just told him to do it a different way (and rightly so). – Logan Jul 31 '12 at 22:49
  • Also keep in mind that Python strings are immutable. – Sean McSomething Aug 08 '12 at 21:00

4 Answers4

3

No. Assigning to the result of a function call is specifically prohibited at the compiler level:

>>> foo() = 3
  File "<stdin>", line 1
SyntaxError: can't assign to function call

There are however two special cases in the Python syntax:

# Slice assignment
a = [1,2,3,4]
a[0:2] = 98, 99  # (a will become [98, 99, 3, 4])

# Tuple assignment
(x, y, z) = (10, 20, 30)

Note also that in Python there is a statement/function duality and an assignment or an augmented assignment (+=, *= ...) is not just a normal operator, but a statement and has special rules.

Moreover in Python there is no general concept of "pointer"... the only way to pass to a function a place where to store something is to pass a "setter" closure because to find an assignable place you need to use explicit names, indexing or you need to work with the instance dictionary if the place is an object instance member).

# Pass the function foo where to store the result
foo( lambda value : setattr(myObject, "member", value) )
6502
  • 112,025
  • 15
  • 165
  • 265
0

No, there isn't any way to do this in general. The slice notation comes close in a limited case, as you can do things like this:

>>> a = [1, 2, 3]
>>> a[1:2] = [5, 6]
>>> a
[1, 5, 6, 3]
Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
-1

In short, no.

However, if you define __setitem__, you can assign to a subscript, e.g.

foo['subscript'] = 7

And you could return foo (and also the subscript, if you wanted) from a function.

container, subscript = whatevs()
container[subscript] = 7

or, in one line:

operator.setitem(*(whatevs()+(7,)))

See operator.

Marcin
  • 48,559
  • 18
  • 128
  • 201
-1

Generally, no (don't stop reading!!!!). Observe the following:

class test:
    test = 4

test().test = 5
# we can no longer refer to the created object.
x = test().test = 6
x # 6

However, doing some searching I found this (which looks like bad practice, but usable):

globals()["varname"] = 5
varname # 5

So, mixing your Perl with my Python we get:

globals()[substr( $string, $start, $stop )]  = something
substr( $string, $start, $stop ) # something

# Note: wouldn't work because the function returns a string. 
# I just don't know what the function returns. 
# so exec("print " +substr( $string, $start, $stop ) I guess

# similarly, and possibly a little better practice
locals()["somethingdif"] = somethingelse
somethingdif # somethingelse

To mitigate massive downvoting, I should mention you can totally screw up your program with this. But you probably know that. Just make sure you don't overwrite existing variables when using this method by checking "somevar" not in locals() or "somevar" not in globals().

Community
  • 1
  • 1
Logan
  • 1,614
  • 1
  • 14
  • 27
  • This isn't the same thing as returning an lvalue. You can't return any of those things from a function such that `whatev() = 7` would work. – Marcin Jul 31 '12 at 22:49
  • @Marcin I didn't say it would. Read my first example. I simply provide similar functionality. Why are you voting down a solution that both answers his question and provides a working alternative? – Logan Jul 31 '12 at 22:54
  • @Marcin Why did you downvote me? I answer his question and my solution works with no change to his coding style, just a wrapper around his assignment statements. – Logan Aug 01 '12 at 00:02
  • 1
    You can't be certain that a given person was the one who down-voted your post. – Brad Gilbert Aug 01 '12 at 00:13
  • Touche. I probably shouldn't have assumed that, but he was the only one who commented. – Logan Aug 01 '12 at 00:19
  • OKay, to whoever is downvoting me: Why? – Logan Aug 01 '12 at 00:45
  • @Marcin But I acknowledge that AND give an example where the lvalue is, at least in part, determined by a function return and functions the same was as if you could return an lvalue? I never claimed it to be the same thing... – Logan Aug 01 '12 at 12:59
  • @Logan It's still not an answer to the question. – Marcin Aug 01 '12 at 14:20
  • @Marcin Then neither is yours. Our answers follow the same format: 1. We both say no, you can't. 2. Then we say, "but if you do this..." you can get similar functionality. – Logan Aug 01 '12 at 15:17
  • @Marcin, For the record, your solution is probably better (to use a dict, even a dict not created by the function return). I didn't think of that and merely presented another possible solution (which, in reality is exactly the same thing, I'm just screwing with environment variables while I'm at it). – Logan Aug 01 '12 at 16:28
  • +1 I was led to read again my answer there (http://stackoverflow.com/a/5036827/551449) and I saw your reference to your present answer. – eyquem Mar 21 '13 at 11:35