I have trouble completing the following function:
def fullyQualifiedMethodNameInStack(depth=1):
"""
The function should return <file>_<class>_<method> for the method in the
stack at specified depth.
"""
fileName=inspect.stack()[depth][1]
methodName=inspect.stack()[depth][3]
class= """ please help!!! """
baseName=os.path.splitext( os.path.basename( fileName ) )[0]
return '{0}_{1}_{2}'.format( baseName, className, methodName )
As you can see I want the class name of the method being executed. The stack that inspect returns only has the method name, and I do not know how to find the class belonging to the method.
You are always looking at a function context; the method context is already gone by the time the function executes. Technically speaking, functions act as descriptors when accessed as attributes on an instance (instance.method_name), which return a method object. The method object then, when called, in turn calls the original function with the instance as the first argument. Because this all happens in C code, no trace of the original method object remains on the Python stack.
The stack only needs to keep track of namespaces and the code to be executed for the local namespace. The original function object is no longer needed for these functions, only the attached code object still retains the name of the original function definition for traceback purposes.
If you know the function to be a method, you could search for a self local name. If present, type(self) is the class of the instance, which is not necessarily the class the method was defined on.
You would then have to search the class and it's bases (looping over the .__mro__ attribute) to try and locate what class defined that method.
There are a few more snags you need to take into account:
Naming the first argument of a method self is only a convention. If someone picked a different name, you won't be able to figure that out without parsing the Python source yourself, or by going up another step in the stack and trying to deduce from that line how the function was called, then retrieve the method and it's .im_self attribute.
You only are given the original name of the function, under which it was defined. That is not necessarily the name under which it was invoked. Functions are first-class objects and can be added to classes under different names.
Although a function was passed in self and was defined as part of a class definition, it could have been invoked by manually passing in a value for self instead of the usual route of the method (being the result of the function acting as a descriptor) passing in the self reference for the caller.
In Python 3.3 and up, the situation is marginally better; function objects have a new __qualname__ attribute, which would include the class name. The problem is then that you still need to locate the function object from the parent stack frame.
Related
This question already has answers here:
What is the purpose of the `self` parameter? Why is it needed?
(26 answers)
Closed 6 months ago.
Are you supposed to use self when referencing a member function in Python (within the same module)?
More generally, I was wondering when it is required to use self, not just for methods but for variables as well.
Adding an answer because Oskarbi's isn't explicit.
You use self when:
Defining an instance method. It is passed automatically as the first parameter when you call a method on an instance, and it is the instance on which the method was called.
Referencing a class or instance attribute from inside an instance method. Use it when you want to call a method or access a name (variable) on the instance the method was called on, from inside that method.
You don't use self when
You call an instance method normally. Using Oskarbi's example, if you do instance = MyClass(), you call MyClass.my_method as instance.my_method(some_var) not as instance.my_method(self, some_var).
You reference a class attribute from outside an instance method but inside the class definition.
You're inside a staticmethod.
These don'ts are just examples of when not to use self. The dos are when you should use it.
Use self to refer to instance variables and methods from other instance methods. Also put self as the first parameter in the definition of instance methods.
An example:
class MyClass(object):
my_var = None
def my_method(self, my_var):
self.my_var = my_var
self.my_other_method()
def my_other_method(self):
# do something...
There is nothing 'special' about the name self. It is the name preferred by convention by Pythonistas, to indicate what that parameter is expected to contain.
The Python runtime will pass a 'self' value when you call an instance method on an instance, whether you deliberately provide for it or not. This will usually result in an easily diagnosed/understood error (since the function will get called with the wrong number of parameters), but the use of *args can lead to rather more strange type errors.
The parameter is passed implicitly when you call an instance method on an instance. It contains the instance upon which you call the method. So you don't mention self in the function call because (a) as noted above, that wouldn't make any sense (there isn't a self in scope, in general, and self is not a keyword or special name or anything); (b) you've already indicated the instance to use (by writing my_instance.).
You can, of course, explicitly call an instance method by accessing it from the class. In this case, you'll need to pass the instance explicitly as the first parameter. You generally speaking don't want to do this. And you especially don't want to write code that considers the possibility that the first parameter is something else that's been explicitly passed in this way. This is akin to checking if (this == null) in C++: you don't do it, because if it could possibly mean anything, then the calling code is wrong, morally if not legally. (At least in Python you won't have problems with undefined behaviour, but it's still morally wrong.)
Within the instance method, since self is a parameter which has been assigned the instance as a value, you can write self.whatever to access attributes of the instance. Unlike in some other 'implicit this' style languages, the attribute names are not implicitly "in scope".
There are no other use cases for self, since again it's not a special name, and that is the one specific purpose that the naming convention addresses. If you needed to access a 'variable' (really an attribute) from another module, you would use the module name. If you wanted to access one from the current module, no prefix is needed, or really possible for that matter. (Well, you could explicitly look it up in the dict returned by globals(), but please don't do that.)
For instance variable and for methods it is mandatory to use self anytime.
Why it's required to use self keyword as an argument when calling the parent method from the child method?
Let me give an example,
class Account:
def __init__(self,filepath):
self.filepath = filepath
with open(self.filepath,"r") as file:
self.blanace = int(file.read())
def withDraw(self,amount):
self.blanace = self.blanace - amount
self.commit()
def deposite(self,amount):
self.blanace = self.blanace + amount
self.commit()
def commit(self):
with open(self.filepath,"w") as file:
file.write(str(self.blanace))
class Checking(Account):
def __init__(self,filepath):
Account.__init__(sellf,filepath) ######## I'm asking about this line.
Regarding this code,
I understand that self is automatically passed to the class when declaring a new object, so,
I expect when I declare new object, python will set self = the declared object, so now the self keyword will be available in the "'init'" child method, so no need to write it manually again like
Account.__init__(sellf,filepath) ######## I'm asking about this line.
All instance methods are just function-valued class attributes. If you access the attribute via an instance, some behind-the-scenes "magic" (known as the descriptor protocol) takes care of changing foo.bar() to type(foo).bar(foo). __init__ itself is also just another instance method, albeit one you usually only call explicitly when overriding __init__ in a child.
In your example, you are explicitly invoking the parent class's __init__ method via the class, so you have to pass self explicitly (self.__init__(filepath) would result in infinite recursion).
One way to avoid this is to not refer to the parent class explicitly, but to let a proxy determine the "closest" parent for you.
super().__init__(filepath)
There is some magic here: super with no arguments determines, with some help from the Python implementation, which class it statically occurs in (in this case, Checking) and passes that, along with self, as the implicit arguments to super. In Python 2, you always had to be explicit: super(Checking, self).__init__(filepath). (In Python 3, you can still pass argument explicitly, because there are some use cases, though rare, for passing arguments other than the current static class and self. Most commonly, super(SomeClass) does not get self as an implicit second argument, and handles class-level proxying.)
Specifically, the function class defines a __get__ method; if the result of an attribute lookup defines __get__, the return value of that method is returned instead of the attribute value itself. In other words,
foo.bar
becomes
foo.__dict__['bar'].__get__(foo, type(foo))
and that return value is an object of type method. Calling a method instance simply causes the original function to be called, with its first argument being the instance that __get__ took as its first argument, and its remaining arguments are whatever other arguments were passed to the original method call.
Generally speaking, I would tally this one up to the Zen of Python -- specifically, the following statements:
Explicit is better than implicit.
Readability counts.
In the face of ambiguity, refuse the temptation to guess.
... and so on.
It's the mantra of Python -- this, along with many other cases may seem redundant and overly simplistic, but being explicit is one of Python's key "goals." Perhaps another user can give more explicit examples, but in this case, I would say it makes sense to not have arguments be explicitly defined in one call, then vanish -- it might make things unclear when looking at a child function without also looking at its parent.
I have a piece of code where I pull a function out of a dictionary, then add an object attribute to it. However I am having some problems accessing it from within the function, presumably due to the namespace.
aFunction = FunctionsDictionary[key]
aFunction.someObject = someObject
aFunction()
def aFunction():
someObject.doSomething()
Gives NameError global name 'someObject' is not defined.
If I do a dir(aFunction) after I set the attribute I can see it, however a dir() from within the function does not show the attribute.
Although I can likely change the code to have the function accept the object as an argument, how do I refer to these attributes set on the 'instance' of the function?
Here is another example:
def myFunc():
print coolAttr
func = myFunc
func.coolAttr = "Cool Attribute"
func()
NameError: global name 'coolAttr' not defined
It doesn't seem like there's a (good) way to get a reference to the currently running function in Python; see Is there a generic way for a function to reference itself? and Python code to get current function into a variable? . In the case that all your functions are defined with names using def, you could just refer to the function by its name (e.g. aFunction in your example) to get its properties within the function body.
A bigger problem is that this may not have the effect you want... Functions are passed by reference in python, so if aFunction appears multiple times in the dict, there's still going to be only one copy of the function object. So if you set the property on multiple values of the dict, all of which happen to point to the same function, you'll only end up storing the last value of the property... Hard to know without more detail if that's what you need.
The best answer is probably to rewrite your code so the relevant value is passed as an argument.
Consider the following code:
class A(object):
def do(self):
print self.z
class B(A):
def __init__(self, y):
self.z = y
b = B(3)
b.do()
Why does this work? When executing b = B(3), attribute z is set. When b.do() is called, Python's MRO finds the do function in class A. But why is it able to access an attribute defined in a subclass?
Is there a use case for this functionality? I would love an example.
It works in a pretty simple way: when a statement is executed that sets an attribute, it is set. When a statement is executed that reads an attribute, it is read. When you write code that reads an attribute, Python does not try to guess whether the attribute will exist when that code is executed; it just waits until the code actually is executed, and if at that time the attribute doesn't exist, then you'll get an exception.
By default, you can always set any attribute on an instance of a user-defined class; classes don't normally define lists of "allowed" attributes that could be set (although you can make that happen too), they just actually set attributes. Of course, you can only read attributes that exist, but again, what matters is whether they exist when you actually try to read them. So it doesn't matter if an attribute exists when you define a function that tries to read it; it only matters when (or if) you actually call that function.
In your example, it doesn't matter that there are two classes, because there is only one instance. Since you only create one instance and call methods on one instance, the self in both methods is the same object. First __init__ is run and it sets the attribute on self. Then do is run and it reads the attribute from the same self. That's all there is to it. It doesn't matter where the attribute is set; once it is set on the instance, it can be accessed from anywhere: code in a superclass, subclass, other class, or not in any class.
Since new attributes can be added to any object at any time, attribute resolution happens at execution time, not compile time. Consider this example which may be a bit more instructive, derived from yours:
class A(object):
def do(self):
print(self.z) # references an attribute which we have't "declared" in an __init__()
#make a new A
aa = A()
# this next line will error, as you would expect, because aa doesn't have a self.z
aa.do()
# but we can make it work now by simply doing
aa.z = -42
aa.do()
The first one will squack at you, but the second will print -42 as expected.
Python objects are just dictionaries. :)
When retrieving an attribute from an object (print self.attrname) Python follows these steps:
If attrname is a special (i.e. Python-provided) attribute for objectname, return it.
Check objectname.__class__.__dict__ for attrname. If it exists and is a data-descriptor, return the descriptor result. Search all bases of objectname.__class__ for the same case.
Check objectname.__dict__ for attrname, and return if found. If objectname is a class, search its bases too. If it is a class and a descriptor exists in it or its bases, return the descriptor result.
Check objectname.__class__.__dict__ for attrname. If it exists and is a non-data descriptor, return the descriptor result. If it exists, and is not a descriptor, just return it. If it exists and is a data descriptor, we shouldn't be here because we would have returned at point 2. Search all bases of objectname.__class__ for same case.
Raise AttributeError
Source
Understanding get and set and Python descriptors
Since you instanciated a B object, B.__init__ was invoked and added an attribute z. This attribute is now present in the object. It's not some weird overloaded magical shared local variable of B methods that somehow becomes inaccessible to code written elsewhere. There's no such thing. Neither does self become a different object when it's passed to a superclass' method (how's polymorphism supposed to work if that happens?).
There's also no such thing as a declaration that A objects have no such object (try o = A(); a.z = whatever), and neither is self in do required to be an instance of A1. In fact, there are no declarations at all. It's all "go ahead and try it"; that's kind of the definition of a dynamic language (not just dynamic typing).
That object's z attribute present "everywhere", all the time2, regardless of the "context" from which it is accessed. It never matters where code is defined for the resolution process, or for several other behaviors3. For the same reason, you can access a list's methods despite not writing C code in listobject.c ;-) And no, methods aren't special. They are just objects too (instances of the type function, as it happens) and are involved in exactly the same lookup sequence.
1 This is a slight lie; in Python 2, A.do would be "bound method" object which in fact throws an error if the first argument doesn't satisfy isinstance(A, <first arg>).
2 Until it's removed with del or one of its function equivalents (delattr and friends).
3 Well, there's name mangling, and in theory, code could inspect the stack, and thereby the caller code object, and thereby the location of its source code.
Consider this example of a strategy pattern in Python (adapted from the example here). In this case the alternate strategy is a function.
class StrategyExample(object):
def __init__(self, strategy=None) :
if strategy:
self.execute = strategy
def execute(*args):
# I know that the first argument for a method
# must be 'self'. This is just for the sake of
# demonstration
print locals()
#alternate strategy is a function
def alt_strategy(*args):
print locals()
Here are the results for the default strategy.
>>> s0 = StrategyExample()
>>> print s0
<__main__.StrategyExample object at 0x100460d90>
>>> s0.execute()
{'args': (<__main__.StrategyExample object at 0x100460d90>,)}
In the above example s0.execute is a method (not a plain vanilla function) and hence the first argument in args, as expected, is self.
Here are the results for the alternate strategy.
>>> s1 = StrategyExample(alt_strategy)
>>> s1.execute()
{'args': ()}
In this case s1.execute is a plain vanilla function and as expected, does not receive self. Hence args is empty. Wait a minute! How did this happen?
Both the method and the function were called in the same fashion. How does a method automatically get self as the first argument? And when a method is replaced by a plain vanilla function how does it not get the self as the first argument?
The only difference that I was able to find was when I examined the attributes of default strategy and alternate strategy.
>>> print dir(s0.execute)
['__cmp__', '__func__', '__self__', ...]
>>> print dir(s1.execute)
# does not have __self__ attribute
Does the presence of __self__ attribute on s0.execute (the method), but lack of it on s1.execute (the function) somehow account for this difference in behavior? How does this all work internally?
You can read the full explanation here in the python reference, under "User defined methods". A shorter and easier explanation can be found in the python tutorial's description of method objects:
If you still don’t understand how methods work, a look at the implementation can perhaps clarify matters. When an instance attribute is referenced that isn’t a data attribute, its class is searched. If the name denotes a valid class attribute that is a function object, a method object is created by packing (pointers to) the instance object and the function object just found together in an abstract object: this is the method object. When the method object is called with an argument list, a new argument list is constructed from the instance object and the argument list, and the function object is called with this new argument list.
Basically, what happens in your example is this:
a function assigned to a class (as happens when you declare a method inside the class body) is... a method.
When you access that method through the class, eg. StrategyExample.execute you get an "unbound method": it doesn't "know" to which instance it "belongs", so if you want to use that on an instance, you would need to provide the instance as the first argument yourself, eg. StrategyExample.execute(s0)
When you access the method through the instance, eg. self.execute or s0.execute, you get a "bound method": it "knows" which object it "belongs" to, and will get called with the instance as the first argument.
a function that you assign to an instance attribute directly however, as in self.execute = strategy or even s0.execute = strategy is... just a plain function (contrary to a method, it doesn't pass via the class)
To get your example to work the same in both cases:
either you turn the function into a "real" method: you can do this with types.MethodType:
self.execute = types.MethodType(strategy, self, StrategyExample)
(you more or less tell the class that when execute is asked for this particular instance, it should turn strategy into a bound method)
or - if your strategy doesn't really need access to the instance - you go the other way around and turn the original execute method into a static method (making it a normal function again: it won't get called with the instance as the first argument, so s0.execute() will do exactly the same as StrategyExample.execute()):
#staticmethod
def execute(*args):
print locals()
You need to assign an unbound method (i.e. with a self parameter) to the class or a bound method to the object.
Via the descriptor mechanism, you can make your own bound methods, it's also why it works when you assign the (unbound) function to a class:
my_instance = MyClass()
MyClass.my_method = my_method
When calling my_instance.my_method(), the lookup will not find an entry on my_instance, which is why it will at a later point end up doing this: MyClass.my_method.__get__(my_instance, MyClass) - this is the descriptor protocol. This will return a new method that is bound to my_instance, which you then execute using the () operator after the property.
This will share method among all instances of MyClass, no matter when they were created. However, they could have "hidden" the method before you assigned that property.
If you only want specific objects to have that method, just create a bound method manually:
my_instance.my_method = my_method.__get__(my_instance, MyClass)
For more detail about descriptors (a guide), see here.
The method is a wrapper for the function, and calls the function with the instance as the first argument. Yes, it contains a __self__ attribute (also im_self in Python prior to 3.x) that keeps track of which instance it is attached to. However, adding that attribute to a plain function won't make it a method; you need to add the wrapper. Here is how (although you may want to use MethodType from the types module to get the constructor, rather than using type(some_obj.some_method).
The function wrapped, by the way, is accessible through the __func__ (or im_func) attribute of the method.
When you do self.execute = strategy you set the attribute to a plain method:
>>> s = StrategyExample()
>>> s.execute
<bound method StrategyExample.execute of <__main__.StrategyExample object at 0x1dbbb50>>
>>> s2 = StrategyExample(alt_strategy)
>>> s2.execute
<function alt_strategy at 0x1dc1848>
A bound method is a callable object that calls a function passing an instance as the first argument in addition to passing through all arguments it was called with.
See: Python: Bind an Unbound Method?