internals - Why is __code__ for a function(Python) mutable -


in previous question yesterday, in comments, came know in python __code__ atrribute of function mutable. hence can write code following

def foo():     print "hello"  def foo2():     print "hello 2"  foo() foo.__code__ = foo2.__code__ foo() 

output

hello hello 2 

i tried googling, either because there no information(i highly doubt this), or keyword (__code__) not searchable, couldn't find use case this.

it doesn't seem "because things in python mutable" reasonable answer either, because other attributes of functions — __closure__ , __globals__ — are explicitly read-only (from objects/funcobject.c):

static pymemberdef func_memberlist[] = {     {"__closure__",   t_object,     off(func_closure),      restricted|readonly},     {"__doc__",       t_object,     off(func_doc), py_write_restricted},     {"__globals__",   t_object,     off(func_globals),      restricted|readonly},     {"__module__",    t_object,     off(func_module), py_write_restricted},     {null}  /* sentinel */ }; 

why __code__ writable while other attributes read-only?

the fact is, things in python are mutable. real question is, why __closure__ , __globals__ not?

the answer appears simple. both of these things containers variables function might need. code object not carry closed-over , global variables around it; merely knows how them function. grabs actual values out of these 2 attributes when function called.

but scopes mutable, answer unsatisfying. need explain why modifying these things in particular break stuff.

for __closure__, can structure. not mapping, tuple of cells. doesn't know names of closed-over variables. when code object looks closed-over variable, needs know position in tuple; match one-to-one co_freevars read-only. , if tuple of wrong size or not tuple @ all, mechanism breaks down, violently (read: segfaults) if underlying c code isn't expecting such situation. forcing c code check type , size of tuple needless busy-work can eliminated making attribute read-only. if try replace __code__ taking different number of free variables, you error, size right.

for __globals__, explanation less obvious, i'll speculate. scope lookup mechanism expects have access global namespace @ times. indeed, bytecode may hard-coded go straight global namespace, if compiler can prove no other namespace have variable particular name. if global namespace none or other non-mapping object, c code could, once again, violently misbehave. again, making code perform needless type checks waste of cpu cycles.

another possibility (normally-declared) functions borrow reference module's global namespace, , making attribute writable cause reference count messed up. imagine design, i'm not sure it's great idea since functions can constructed explicitly objects lifetimes might shorter of owning module, , these need special-cased.


Comments

Popular posts from this blog

python - pip install -U PySide error -

arrays - C++ error: a brace-enclosed initializer is not allowed here before ‘{’ token -

cytoscape.js - How to add nodes to Dagre layout with Cytoscape -