How to Call Setattr() on the Current Module

How do I call setattr() on the current module?

import sys

thismodule = sys.modules[__name__]

setattr(thismodule, name, value)

or, without using setattr (which breaks the letter of the question but satisfies the same practical purposes;-):

globals()[name] = value

Note: at module scope, the latter is equivalent to:

vars()[name] = value

which is a bit more concise, but doesn't work from within a function (vars() gives the variables of the scope it's called at: the module's variables when called at global scope, and then it's OK to use it R/W, but the function's variables when called in a function, and then it must be treated as R/O -- the Python online docs can be a bit confusing about this specific distinction).

What is the pythonic way to setattr() for a module?

Your suggested approach

globals()["var_name"] = value

is indeed the most Pythonic way. In particular, it's significantly more Pythonic than using eval, which would be your main (though not only) alternative.

However, if you still want to use setattr, you may do so by using sys.modules to get a reference to the current module object with the current module's __name__ variable (explained here) as follows:

import sys
setattr(sys.modules[__name__], "var_name", value)

Python setattr() to function takes initial function name

function.__name__ is the name under which the function has been initially defined, it has nothing to do with the name under which it is accessed. Actually, the whole point of function.__name__ is to correctly identify the function whatever name is used to access it. You definitly want to read this for more on what Python's "names" are.

One of the possible solutions here is replace the static definition of condition with a closure:

class Filter(object):
def __init__(self, column=['poi_id', 'tp.event'], access=['con', 'don']):
self.column = column
self.access = access
self.accessor_column = dict(zip(self.access, self.column))
self.set_conditions()

def set_conditions(self):
mapping = list(zip(self.column, self.access))
for column_name, accessor_name in mapping:
def accessor(name):
print("in {}.accessor '{}' for column '{}'".format(self, accessor_name, column_name))
return name

# this is now technically useless but helps with inspection
accessor.__name__ = accessor_name
setattr(self, accessor_name, accessor)

As a side note (totally unrelated but I thought you may want to know this), using mutable objects as function arguments defaults is one of the most infamous Python gotchas and may yield totally unexpected results, ie:

>>> f1 = Filter()
>>> f2 = Filter()
>>> f1.column
['poi_id', 'tp.event']
>>> f2.column
['poi_id', 'tp.event']
>>> f2.column.append("WTF")
>>> f1.column
['poi_id', 'tp.event', 'WTF']

EDIT:

thank you for your answer, but it doesn't touch my issue here. My problem is not how functions are named or defined, my problem it that when i use setattr() and i set an attribute and i give it a function as it's value, i can access the value and perform what the value does, but since it's a function, why doesn't it return it's name as the function name

Because as I already explained above, the function's __name__ attribute and the name of the Filter instance attribute(s) refering to this function are totally unrelated, and the function knows absolutely nothing about the names of variables or attributes that reference it, as explained in the reference article I linked to.

Actually the fact that the object you're passing to setattr is a function is totally irrelevant, from the object's POV it's just a name and an object, period. And actually the fact you're binding this object (function or just whatever object) to an instance attribute (whether directly or using setattr(), it works just the same) instead of a plain variable is also totally irrelevant - none of those operation will have any impact on the object that is bound (except for increasing it's ref counter but that's a CPython implementation detail - other implementations may implement garbage collection diffently).

Using Python setattr to set an attribute reference to a method or function

Most trivial approach would be something like:

module_name, function_name = "module.func".rsplit('.', 1)
f = getattr(sys.modules[module_name], function_name)
f() # f is now callable, analogous to anothermodule.some_function in your code snippets.

Obviously, a lot potential issues are not addressed. First of all, it assumes that module is already imported. To address that you may refer to Dynamic module import in Python and use return value of __import__. Don't worry, CPython will optimize it internally and same module wouldn't be interpreted more than once.

Slightly better version would be:

module_name, function_name = "module.func".rsplit('.', 1)
f = getattr(__import__(module_name), function_name)
f()

Using setattr() in python

You are setting self.name to the string "get_thing", not the function get_thing.

If you want self.name to be a function, then you should set it to one:

setattr(self, 'name', self.get_thing)

However, that's completely unnecessary for your other code, because you could just call it directly:

value_returned = self.get_thing()

A module's __setattr__ and __getattr__ when accessing globals

You can't.

The basic problem is that attribute overloads only work when you are accessing an attribute, specifically that means:


expr . ident

Without the dot, there can be no attribute overload. Thus, no matter what you do, a sequence like


a

Can never invoke an attribute overload, no matter what else may equate to the value of a.

Why does setattr not affect the return value?

It did work, just not as you're expecting:

f = foo.bar

print(f()) # baz

bar is a nested function inside foo; not an attribute of it. As far as I know, there is no way of reassigning an inner function like this.

Your best best is probably to have an externally-accessible variable that foo relies on, and reassign that as needed. Or give it a mutable object that you mutate externally into a desired state. I can't say I'd recommend these options, but given the current requirements, they should work.

Using setattr() and getattr() in Python descriptors

But why should it be doing that if setattr() is modifying the obj __dict__?

setattr doesn't just modify the __dict__. It sets attributes, exactly like x.y = z would, and for the attribute you're trying to set, "set this attribute" means "call the setter you're already in". Hence, infinite recursion.

And why does this work if we use internal_name?

That name doesn't correspond to a property, so it just gets a __dict__ entry.

__getattr__ on a module

A while ago, Guido declared that all special method lookups on
new-style classes bypass __getattr__ and __getattribute__. Dunder methods had previously worked on modules - you could, for example, use a module as a context manager simply by defining __enter__ and __exit__, before those tricks broke.

Recently some historical features have made a comeback, the module __getattr__ among them, and so the existing hack (a module replacing itself with a class in sys.modules at import time) should be no longer necessary.

In Python 3.7+, you just use the one obvious way. To customize attribute access on a module, define a __getattr__ function at the module level which should accept one argument (name of attribute), and return the computed value or raise an AttributeError:

# my_module.py

def __getattr__(name: str) -> Any:
...

This will also allow hooks into "from" imports, i.e. you can return dynamically generated objects for statements such as from my_module import whatever.

On a related note, along with the module getattr you may also define a __dir__ function at module level to respond to dir(my_module). See PEP 562 for details.



Related Topics



Leave a reply



Submit