0

Let's say we have a function foo()

def foo():
  foo.a = 2

foo.a = 1
foo()

>> foo.a
>> 2

Is this pythonic or should I wrap the variable in mutable objects such as a list?

Eg:

a = [1]

def foo(a):
  a[0] = 2
foo()

>> a

>> 2
yask
  • 3,918
  • 4
  • 20
  • 29
  • 1
    What is your goal? Do you want to mutate an object in the calling scope? In global scope? Something else? – Steven Rumbalski Oct 18 '16 at 14:25
  • I want to mutate the variable so that the changes are effected in global scope as well. Also, I don't quite understand what `function_name.a`(Eg 1) means and why does it simulate mutable object? – yask Oct 18 '16 at 14:27
  • Also check this: http://stackoverflow.com/questions/39975659/python-27-how-to-fix-store-a-value-to-a-method-to-preserve-its-interface/39975900#39975900 – jbndlr Oct 18 '16 at 14:37
  • 1
    If you use python 3 and are not required to support 2.x, your first example is perfectly pythonic: Bind attributes to the resources they belong to. – jbndlr Oct 18 '16 at 14:41
  • @jbndlr I have to totally disagree here - whatever Python version, blindly adding / mutating attributes on a global name (which we DONT know what it will resolve to at call time) is unpythonic. The fact you can find quite few examples of this antipattern on the net (and even in some books IIRC) doesn't make it more pythonic nor less of an antipattern. – bruno desthuilliers Oct 18 '16 at 15:18
  • 1
    @brunodesthuilliers As we don't know the purpose, we cannot tell whether or not this is a *do* or a *don't* -- but binding attributes to their respective scopes is way better (and more pythonic) than dealing with data structures in global scope (or even ``global`` keywords). – jbndlr Oct 18 '16 at 15:24
  • @jbndlr in the first example, there's no "binding attributes to their respective scope" - attributes are bound to just _whatever_ the global name "foo" refers to at call time (and which may change from one call to another). If you want to "bind attributes to their repective scope" you either use a proper OO design (in this case making a callable class) or a closure. That was my point. – bruno desthuilliers Oct 19 '16 at 07:20

2 Answers2

1

Since you "want to mutate the variable so that the changes are effected in global scope as well" use the global keyword to tell your function that the name a is a global variable. This means that any assignment to a inside of your function affects the global scope. Without the global declaration assignment to a in your function would create a new local variable.

>>> a = 0
>>> def foo():
...     global a
...     a = 1
...
>>> foo()
>>> a
1
Steven Rumbalski
  • 44,786
  • 9
  • 89
  • 119
  • Can you also explain what `foo.a` means where `foo` is a function name. How does the example 1 (as mentioned in the question) work like a mutable variable? – yask Oct 18 '16 at 14:33
  • @yask: Python functions are callable objects. Since they are objects you can add attributes using dot notation (such as `foo.a = 2`). This is a legal but not common practice (but not totally uncommon). If you need to pair behavior with state what you want is to declare a class. – Steven Rumbalski Oct 18 '16 at 14:35
  • @StevenRumbalski ``a`` is no attribute in your example, this may be misleading. – jbndlr Oct 18 '16 at 14:36
  • @jbndlr: I'm addressing yask's goal as stated in his comment to the question. – Steven Rumbalski Oct 18 '16 at 14:38
0

Use a class (maybe a bit overkill):

class Foo:
    def __init__(self):
        self.a = 0

def bar(f):
    f.a = 2

foo = Foo()
foo.a = 1
bar(foo)
print(foo.a)
Oxben
  • 44
  • 3