"I" inside a simple function?
I have a bunch of functions (outside of any class) where I set attributes on them, for example funcname.fields = 'xxx' . I was hoping that I could then access these variables from within the function using self.fields , but of course this tells me:
the global name "I" is not defined
So ... what can I do? Is there some kind of magic variable that I can access? How is __this__.fields ?
Several people asked "why?" You probably will not agree with my reasoning, but I have a set of functions that everyone should use the same signature (accept only one argument). For the most part, this single argument is enough to perform the required calculation. However, in a few limited cases, additional information is needed. Instead of forcing each function to accept a long list of mostly unused variables, I decided to just set them in functions so that they could be easily ignored.
Although now it seems to me that you can just use **kwargs as your last argument if you don't need additional arguments. Oh good...
Edit: Actually, some of the functions that I did not write will not change to accept additional arguments. By passing additional arguments as attributes, my code can work both with my custom functions, which take advantage of additional arguments, and with third-party code that does not require additional arguments.
Thanks for the quick answers :)
You cannot correctly use this function to access your own attributes for all situations - see details here how can a python function access its own attributes? - but here is a quick demonstration:
>>> def f(): return fx ... >>> fx = 7 >>> f() 7 >>> g = f >>> g() 7 >>> del f >>> g() Traceback (most recent call last): File "<interactive input>", line 1, in <module> File "<interactive input>", line 1, in f NameError: global name 'f' is not defined Basically, most methods rely directly or indirectly on accessing a function object by searching by name in global variables; and if the name of the original function is deleted, it stops working. There are other ways to do this, such as defining a class or factory, but thanks to your explanation, it is clear that you really don't need it.
Just specify the catch-all key argument mentioned, for example:
def fn1(oneArg): // do the due def fn2(oneArg, **kw): if 'option1' in kw: print 'called with option1=', kw['option1'] //do the rest fn2(42) fn2(42, option1='something') Not sure what you mean in your comment on handling TypeError - this does not occur when using ** kw. This approach works very well for some python system functions - check min (), max (), sort (). Recently sorted(dct,key=dct.get,reverse=True) I really liked the CodeGolf challenge :)
self not a keyword in python, its just the regular variable name. When creating instance methods, you can specify the first parameter that you want, and itself is just a convention.
You almost always prefer to pass arguments to functions over setting properties for input, but if necessary, you can do this by using the actual name of the function to access the variables inside it:
def a: if a.foo: #blah a.foo = false a() see python function attributes - use and abuse when convenient: D
def foo(): print(foo.fields) foo.fields=[1,2,3] foo() # [1, 2, 3] There is nothing wrong with adding attributes to functions. Many memories use this to cache the results of the function itself.
For example, pay attention to using func.cache :
from decorator import decorator @decorator def memoize(func, *args, **kw): # Author: Michele Simoniato # Source: http://pypi.python.org/pypi/decorator if not hasattr(func, 'cache'): func.cache = {} if kw: # frozenset is used to ensure hashability key = args, frozenset(kw.iteritems()) else: key = args cache = func.cache # attribute added by memoize if key in cache: return cache[key] else: cache[key] = result = func(*args, **kw) return result Example:
>>> def x(): pass >>> x <function x at 0x100451050> >>> x.hello = "World" >>> x.hello "World" You can set attributes for functions, since these are just simple objects, but I really never saw something like this in real code.
Plus self is not a keyword, just another variable name that is a concrete instance of the class. self is passed implicitly, but explicitly received.
If you want to set global parameters for the called βthingβ, can you always create a class and implement the __call__ method?
There is no special way in the function body to refer to the function object whose code is executed. The easiest way is to simply use funcname.field (with funcname being the name of the function in the namespace in which you specify it will be harder otherwise).
This is not what you should do. I canβt think of any way to do what you ask for, except to walk in the call stack and some kind of strange introspection - this is not what should happen in the production code.
However, I think this really does what you requested:
import inspect _code_to_func = dict() def enable_function_self(f): _code_to_func[f.func_code] = f return f def get_function_self(): f = inspect.currentframe() code_obj = f.f_back.f_code return _code_to_func[code_obj] @enable_function_self def foo(): me = get_function_self() print me foo() While I agree with the others that this is probably not a very good design, the question intrigued me. Here is my first solution that I can update as soon as I get the decorators. Be that as it may, it relies heavily on the ability to read the stack, which may not be possible in all implementations (something about sys._getframe () is not necessarily present ...)
import sys, inspect def cute(): this = sys.modules[__name__].__dict__.get(inspect.stack()[0][3]) print "My face is..." + this.face cute.face = "very cute" cute() What do you think ?: 3
You can use the following (terribly ugly) code:
class Generic_Object(object): pass def foo(a1, a2, self=Generic_Object()): self.args=(a1,a2) print "len(self.args):", len(self.args) return None ... as you can see, this will allow you to use the "I" as you described. You cannot use "object ()" directly because you cannot use the values ββ"monkey patch (*)" in an instance of object() . However, the usual subclasses of the object (such as Generic_Object() , which I showed here) can be "disabled"
If you want to always call your function with a reference to some object as the first argument that would be possible. First you can put the default argument, and then the * args and optional ** kwargs parameters (through which any other arguments or option dictionaries can be passed during calls to this function).
This, as I said, is terribly ugly . Please, never post any code like this or share it with anyone in the Python community. I just show it here as a kind of strange educational exercise.
The instance method is similar to a function in Python. However, it exists in the class namespace (thus, it must be accessible through an instance ... myobject.foo() for example), and it is called with a reference to "self" (similar to the "this" pointer in C ++) as the first argument. There is also a process for resolving a method that forces the interpreter to search for the namespace of the instance, then its class, and then each of the parent classes, etc ... through the inheritance tree.
An unbound function is called with any arguments you pass to it. The argument list cannot contain any automatically linked reference to an object / object instance. Thus, writing a function with an initial argument named "I" does not make sense. (This is legal because Python does not put any special meaning on the name βI.β But itβs pointless because the calling functions of your function had to manually specify some kind of object reference in the argument list, and itβs not at all clear what this should Just be some kind of fancy "Generic_Object" that then floats in the global variable space?).
I hope this clarifies things a bit. It sounds like you are suffering from some very fundamental misconceptions about how Python and other object-oriented systems work.
- ("Monkey patch" is a term used to describe the direct manipulation of attributes of objects - or "instance variables" by code that is not part of the class hierarchy whose object is an instance of the object).
As another alternative, you can make functions in methods of related classes as follows:
class _FooImpl(object): a = "Hello " @classmethod def foo(cls, param): return cls.a + param foo = _FooImpl.foo # later... print foo("World") # yes, Hello World # and if you have to change an attribute: foo.im_self.a = "Goodbye " If you want functions to share namespaecs attributes, you just make them part of the same class. If not, give each one their own class.
What exactly is the self hoping for if a function is defined outside any class? If your function needs some global information to work properly, you need to send this information to the function in the form of an argument.
If you want your function to be contextual, you need to declare it within the scope of the object.