I want to clarify how variables are declared in Python.
- I have seen variable declaration as
class writer:
path = ""
sometimes, there is no explicit declaration but just initialization using __init__:
def __init__(self, name):
self.name = name
I understand the purpose of __init__, but is it advisable to declare variable in any other functions?
- How can I create a variable to hold a custom type?
class writer:
path = "" # string value
customObj = ??
Okay, first things first.
There is no such thing as “variable declaration” or “variable initialization” in Python.
There is simply what we call “assignment”, but should probably just call “naming”.
Assignment means “this name on the left-hand side now refers to the result of evaluating the right-hand side, regardless of what it referred to before (if anything)”.
As such, Python’s names (a better term than “variables”, arguably) don’t have associated types; the values do. You can re-apply the same name to anything regardless of its type, but the thing still has behaviour that’s dependent upon its type. The name is simply a way to refer to the value (object). This answers your second question: You don’t create variables to hold a custom type. You don’t create variables to hold any particular type. You don’t “create” variables at all. You give names to objects.
Second point: Python follows a very simple rule when it comes to classes, that is actually much more consistent than what languages like Java, C++ and C# do: everything declared inside the
classblock is part of the class. So, functions (def) written here are methods, i.e. part of the class object (not stored on a per-instance basis), just like in Java, C++ and C#; but other names here are also part of the class. Again, the names are just names, and they don’t have associated types, and functions are objects too in Python. Thus:Classes are objects too, in Python.
So now we have created an object named
Example, which represents the class of all things that areExamples. This object has two user-supplied attributes (In C++, “members”; in C#, “fields or properties or methods”; in Java, “fields or methods”). One of them is nameddata, and it stores the integer value42. The other is namedmethod, and it stores a function object. (There are several more attributes that Python adds automatically.)These attributes still aren’t really part of the object, though. Fundamentally, an object is just a bundle of more names (the attribute names), until you get down to things that can’t be divided up any more. Thus, values can be shared between different instances of a class, or even between objects of different classes, if you deliberately set that up.
Let’s create an instance:
Now we have a separate object named
x, which is an instance ofExample. Thedataandmethodare not actually part of the object, but we can still look them up viaxbecause of some magic that Python does behind the scenes. When we look upmethod, in particular, we will instead get a “bound method” (when we call it,xgets passed automatically as theselfparameter, which cannot happen if we look upExample.methoddirectly).What happens when we try to use
x.data?When we examine it, it’s looked up in the object first. If it’s not found in the object, Python looks in the class.
However, when we assign to
x.data, Python will create an attribute on the object. It will not replace the class’ attribute.This allows us to do object initialization. Python will automatically call the class’
__init__method on new instances when they are created, if present. In this method, we can simply assign to attributes to set initial values for that attribute on each object:Now we must specify a
namewhen we create anExample, and each instance has its ownname. Python will ignore the class attributeExample.namewhenever we look up the.nameof an instance, because the instance’s attribute will be found first.One last caveat: modification (mutation) and assignment are different things!
In Python, strings are immutable. They cannot be modified. When you do:
You do not change the original ‘hi ‘ string. That is impossible in Python. Instead, you create a new string
'hi mom', and causeato stop being a name for'hi ', and start being a name for'hi mom'instead. We madeba name for'hi 'as well, and after re-applying theaname,bis still a name for'hi ', because'hi 'still exists and has not been changed.But lists can be changed:
Now
bis [1, 2, 3, 4] as well, because we madeba name for the same thing thatanamed, and then we changed that thing. We did not create a new list forato name, because Python simply treats+=differently for lists.This matters for objects because if you had a list as a class attribute, and used an instance to modify the list, then the change would be “seen” in all other instances. This is because (a) the data is actually part of the class object, and not any instance object; (b) because you were modifying the list and not doing a simple assignment, you did not create a new instance attribute hiding the class attribute.