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.
Related
Classes, methods, and instances have me thoroughly confused. Why is it that this works:
class Computer:
def config(self):
print('i5, 16gb, 1TB')
com1 = Computer()
com1.config()
But this does not?:
class Computer:
def config(self):
print('i5, 16gb, 1TB')
com1 = Computer()
Computer.config()
But, if you modify the code directly above to include the instance as an argument when calling the method, like so:
Computer.config(com1)
it works? I see the difference between the two, but I don't understand it.
In your example Computer.config is an instance method, means it is bound to an object, or in other words requires an object. Therefore in your second example you would write:
com1.config()
You can also write it in the following style:
Computer.config(com1)
which is the same and just syntactic sugar. In same special cases you might prefer the latter one, e.g. when duck typing is required, but the first one is definitely the preferred way.
In addition, there are staticmethod or classmethod functions, which don't require any objects. An example would be this:
class Computer
#staticmethod
def config():
print("Foo")
Computer.config() # no object required at all, because its a staticmethod
Please notice the missing self reference. Technically Computer.config as a staticmethod is just a simple function, but it helps to group functionalities so to make them a class member.
This is because config() is an instance method, and not a static method. An instance method, simply said, is shared across all objects of a class, and cannot be accessed by just using the class name. If you want to call config() by just using class name, you have to tell compiler that it is static. To do this use #staticmethod tag, and remove the self argument:
class Computer:
#staticmethod
def config():
print('i5, 16gb, 1TB')
com1 = Computer()
com1.config()
And as you said:
if you modify the code directly above to include the instance as an
argument when calling the method, like so:
This is because, every instance function takes self as it's first argument. Basically self is somewhat similar to this in C++ or Java, and it tells which object to work upon, i.e., self acts as a pointer to the current object. When you passed the com1 object to the argument, it took self for com1.
That means that when you invoke com1.config() what you are actually doing is calling config with com1 as its argument. So com1.config(() is the same as Computer.config(com1).
Why doesn't the second approach work?
Because Computer is an instance of something called a meta-class. It is somewhat the class definition and not actually an instance of Computer. com1 is an instance created by Computer. You can use com1 to invoke its non-static functions but you can't use the meta-class Computer to invoke non-static functions, which need an object to be ran on.
Why does the third approach work?
Have you noticed the self in the definition of the config function? That means that when you invoke com1.config() what you are actually doing is calling config with com1 as its argument. So com1.config() is the same as Computer.config(com1).
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.
In JavaScript, we can do the following to any object or function
const myFn = () => {};
Object.defineProperties(myFn, {
property: {
get: () => console.log('property accessed')
}
});
This will allow for a #property like syntax by defining a getter function for the property property.
myFn.property
// property accessed
Is there anything similar for functions in Python?
I know we can't use property since it's not a new-style class, and assigning a lambda with setattr will not work since it'll be a function.
Basically what I want to achieve is that whenever my_fn.property is to return a new instance of another class on each call.
What I currently have with setattr is this
setattr(my_fn, 'property', OtherClass())
My hopes are to design an API that looks like this my_fn.property.some_other_function().
I would prefer using a function as my_fn and not an instance of a class, even though I realize that it might be easier to implement.
Below is the gist of what I'm trying to achieve
def my_fn():
pass
my_fn = property('property', lambda: OtherClass())
my_fn.property
// will be a new instance of OtherClass on each call
It's not possible to do exactly what you want. The descriptor protocol that powers the property built-in is only invoked when:
The descriptor is defined on a class
The descriptor's name is accessed on an instance of said class
Problem is, the class behind functions defined in Python (aptly named function, exposed directly as types.FunctionType or indirectly by calling type() on any function defined at the Python layer) is a single shared, immutable class, so you can't add descriptors to it (and even if you could, they'd become attributes of every Python level function, not just one particular function).
The closest you can get to what you're attempting would be to define a callable class (defining __call__) that defines the descriptor you're interested in as well. Make a single instance of that class (you can throw away the class itself at this point) and it will behave as you expect. Make __call__ a staticmethod, and you'll avoid changing the signature to boot.
For example, the behavior you want could be achieved with:
class my_fn:
# Note: Using the name "property" for a property has issues if you define
# other properties later in the class; this is just for illustration
#property
def property(self):
return OtherClass()
#staticmethod
def __call__(...whatever args apply; no need for self...):
... function behavior goes here ...
my_fn = my_fn() # Replace class with instance of class that behaves like a function
Now you can call the "function" (really a functor, to use C++ parlance):
my_fn(...)
or access the property, getting a brand new OtherClass each time:
>>> type(my_fn.property) is type(my_fn.property)
True
>>> my_fn.property is my_fn.property
False
No, this isn't what you asked for (you seem set on having a plain function do this for you), but you're asking for a very JavaScript specific thing which doesn't exist in Python.
What you want is not currently possible, because the property would have to be set on the function type to be invoked correctly. And you are not allowed to monkeypatch the function type:
>>> type(my_fn).property = 'anything else'
TypeError: can't set attributes of built-in/extension type 'function'
The solution: use a callable class instead.
Note: What you want may become possible in Python 3.8 if PEP 575 is accepted.
Is __init__ in python a constructor or a method?
Somewhere it says constructor and somewhere it says method, which is quite confusing.
It is correct to call it a method. It is incorrect, or at best inaccurate, to call it a constructor.
Specifically, it is a magic method. They are also called special methods, "dunders", and a few other names.
This particular method is used to define the initialisation behavior of an object. It is not really similar to a constructor, and it is not even the first method to be called on a new instance.
We use __init__ to set up the state of an already-created instance. It will be automatically called when we use the syntax A() to create an instance of a class A, which is why someone might loosely refer to it as a "constructor". But the responsibility of __init__ is not related to instance construction, really the __new__ magic method is more similar to a constructor in that respect.
In addition to the answer by #wim it is worth noting that the object has already been created by the time __init__ is called i.e. __init__ is not a constructor. Furthermore, __init__ methods are optional: you do not have to define one. Finally, an __init__ method is defined first only by convention i.e. it could be defined after any of the other methods.
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.