0

I am a Java programmer making his way into Python, and some things are just baffling. For example, adding variables to functions, dynamically. For example:

def main():
    print ("Hello World")


main.temp = 50

print (main.temp)

What does that even mean? Why would you want to add a variable to a function? Why is that allowed? And why am I allowed to reference the function via main.temp?

Aran-Fey
  • 39,665
  • 11
  • 104
  • 149
ng.newbie
  • 2,807
  • 3
  • 23
  • 57
  • Have you read https://www.python.org/dev/peps/pep-0232/? – Mazdak May 04 '18 at 11:56
  • 2
    Well, everything in python is an object, even functions. – Susensio May 04 '18 at 11:58
  • Not unlike Javascript in this regard – Dexygen May 04 '18 at 11:58
  • @GeorgeJempty Why allow this? javascript has one of the worst syntaxes in this regards. – ng.newbie May 04 '18 at 12:01
  • 1
    @ng.newbie why forbid it ? Being able to annotate a function with any arbitrary attribute is actually quite useful (and indeed used by some well-known frameworks). – bruno desthuilliers May 04 '18 at 12:09
  • @brunodesthuilliers Can you give a real-life example where this is actually used? – ng.newbie May 04 '18 at 12:12
  • Most objects in Python permit you to add attributes, the exception being those defined in C, like most of the built-in types (int, str, list, etc). – PM 2Ring May 04 '18 at 12:16
  • 1
    FWIW, I quite like function attributes, but I admit they aren't popular, and there are generally better ways to do stuff that you can do using function attributes. But IMHO they are a convenient way to attach data to a function, and they're better than having a stray object floating around in the global space that's supposed to be associated with the function. – PM 2Ring May 04 '18 at 12:17
  • @PM2Ring Could you please elaborate by what you mean by "the exception being those defined in C"? You can define objects in C in Python? I am now completely lost. – ng.newbie May 04 '18 at 12:22
  • I ought to mention that the lookup time on a function attribute is somewhat slow: first a lookup in the global namespace is performed to find the function itself, and then another lookup is performed to find the attribute. Take a look [here](https://stackoverflow.com/a/34036910/4014959) to see some timeit tests I wrote that compare various caching strategies, the one using a function attribute is the slowest. – PM 2Ring May 04 '18 at 12:22
  • 1
    Django templates (to prevent some methods from being called from a template), Django admin (to give meaningfull label to computed listview fields), I know I've seen it in other frameworks but can't remember which ATM, and I've personnaly used this in at least a dozen projects for similar reasons: adding meta data to a function so some other piece of code can apply special treatments to those functions. – bruno desthuilliers May 04 '18 at 12:23
  • 1
    Standard Python is often known as CPython, because the interpreter is written in C, and the built-in types it defines are defined using C structures. It's also possible to write your own extensions to Python in C, although that's not often done by mere mortals. ;) But take a look [here](https://github.com/python/cpython/blob/master/Objects/listobject.c) for the C source of the standard `list` object. – PM 2Ring May 04 '18 at 12:26

1 Answers1

1

Functions in Python are first-class objects which means you can do almost whatever you want to do with them. Heck, you can even do this:

def foo(): pass

foo.inner_foo = lambda: print('inner foo')

foo.inner_foo()
# inner foo

Yes, it is a function with an attribute which is a function. And yes, we can go deeper:

def foo(): pass

foo.inner_foo = lambda: None

foo.inner_foo.inner_inner_foo = lambda: print('inner inner foo')

foo.inner_foo.inner_inner_foo()
# inner inner foo

And yes, we can go deeper, but you get the idea...

DeepSpace
  • 78,697
  • 11
  • 109
  • 154
  • When was this ever helpful? Why allow this feature? Just because functions are objects you shouldn't be allowed to add variables to it. – ng.newbie May 04 '18 at 12:02
  • Django makes extensive use of this. Just because you don't immediately see the utility does not make it worthless. – James May 04 '18 at 12:04
  • 1
    @ng.newbie "just because functions are objects you shouldn't be allowed to add variables to it." **why?** that is almost literally the definition of first-class objects. And yes, this is very useful, see the answers to the linked duplicated question. – DeepSpace May 04 '18 at 12:04
  • @DeepSpace Objects in Java don't allow the addition of variables after it is created. So that's why I said what I said. Is the definition of the object different in Python? – ng.newbie May 04 '18 at 12:07
  • @James Could you please give an example of how Django uses this? Maybe if I saw a real life warranted use, then maybe this feature would annoy me a little less. – ng.newbie May 04 '18 at 12:08