When a program runs, it stores the data it requires, in the memory(RAM). A variable is used to store a reference address of a memory. So the program can store that in the reference address and retrieve data when required.
In simple language-
A variable is a named identifier(of some memory location), and we can use the named identifier to store data on it.
A valid identifier contains a nonempty sequence of characters, with a starting character and then other characters. We have discussed the variable/identifier naming rules in later sections.
NOTES
Python variables are not data storage. Rather the data object is saved in memory, and the variable just references that data object.
Variable Declaration
To define a variable we just need an identifier(which is valid). We can assign any value to the identifier and use it as a variable.
Check the following code:
# variable.py
# Declare a variable and assign value
my_val = 100
print(my_val)
# Change the value of the variable
my_val = 900
print(my_val)
# Change the value again
my_val = my_val * 2
print(my_val)
PythonOutput:
100
900
1800
PlaintextHere are some more examples of variable declaration assignments in Python-
In the code below we have used 2 variables-
- siteName
- siteURL
As we can see, we can store data/values, in these named identifiers, and use these data/values when we need them, later in the program.
# site_info.py
# Here we have used the variable name
# "siteName" to store the name of the site
siteName = "BigBoxCode"
# Here we are using the variable
# "siteName" to print the value stored in it
print("Name of the site is:" + siteName)
# Here we are taking some input
# and saving in the variable "siteURL"
siteURL = input("Enter the URL of {}: ".format(siteName))
# the above line will prompt for an input and will continue after we input some string using keyboard
# Here we are using the "siteURL" variable
print("Entered url: " + siteURL)
PythonOutput:
It will generate output as below. In the process, the script will prompt for input. So we have to input some string, and then press enter “enter”
Name of the site is:BigBoxCode
Enter the URL of BigBoxCode: bigboxcode.com
Entered url: bigboxcode.com
PlaintextVariable Reassignment
We can assign any type of value in Python, and then replace it by reassigning some other type of value-
# variable_assign.py
# Assign some integer value
big_box = 20
print("Value of big_box: ", big_box)
print("Type of big_box: ", type(big_box))
# Assign string to the same variable
big_box = "Some string value here"
print("Value of big_box: ", big_box)
print("Type of big_box: ", type(big_box))
# Assign some float to the same variable
big_box = 99.99
print("Value of big_box: ", big_box)
print("Type of big_box: ", type(big_box))
PythonOutput:
Value of big_box: 20
Type of big_box: <class 'int'>
Value of big_box: Some string value here
Type of big_box: <class 'str'>
Value of big_box: 99.99
Type of big_box: <class 'float'>
PlaintextVariable Naming Rules
Variable names should follow certain rules. We can not just name a variable anything we want, as that can cause some readability issues.
WARNING
Variable(identifier) names are case-sensitive. So my_var, My_Var, and mY_VAR represent different variables.
Here are the criteria for a valid Python identifier. An identifier should be-
- A non-empty sequence of characters.
- Must start with a letter(a-z, A-Z, non-English Unicode characters) or an underscore(_).
- Can only contain letters(a-z, A-Z, non-English Unicode characters), numbers(0-9), and underscore(_).
- Can not be a reserved Python keyword(mentioned below).
WARNING
The following keywords are reserved keywords in Python, and can not be used as variable names in Python-
Try the following code-
for = 100
PythonOutput will be-
File "variable.py", line 1
for = 100
^
SyntaxError: invalid syntax
PlaintextIf you want to get the list of reserved(builtin) keywords, then use the following code-
dir()
dir(__builtins__)
PythonYou will get the list of all keywords, that can not be used as an identifier-
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__']
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BlockingIOError',
......
'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']
PlaintextVariable Naming Convention
Follow the conventions mentioned below for an appropriate name for a variable-
- The name should be meaningful and represent the purpose of the variable.
- If the variable name contains multiple words then separate those with an underscore(_). i.e. first_name, customer_id, etc.
- Do not use double underscore(__) in the beginning or end of the variable name.
- Though a single underscore(_) is a valid variable name, but do not use it. (only use in case you want to ignore the variable)
WARNING
Identifiers named with all capital letters are considered as constant by convention, and should not be changed once defined.
i.e. MY_CONST, MAX_FILE_SIZE, NUMBER_OF_BOX
Variable as Object Reference
In Python, the variables do not store some values. Instead, these variables work as references to objects.
Especially, for integer, float, string, etc. data types the variables behave just as references, because of the immutable behavior of those data.
Object Referencing
Let’s assign some integer value to variables and check the id-
i1 = 100
i2 = 100
i3 = 200
i4 = i1
print("integer i1: ", id(i1))
print("integer i2: ", id(i2))
print("integer i3: ", id(i3))
print("integer i4: ", id(i4))
PythonOutput:
The variable with the same value has the same ID, also the variable assigned with reference has the same ID.
ID of | ID | Note |
---|---|---|
integer i1 | 139663237303632 | Value is 100 |
integer i2 | 139663237303632 | Value is 100 |
integer i3 | 139663237306832 | |
integer i4 | 139663237303632 | Value assigned from i1 |
This is how it looks-
Check the same thing with float-
f1 = 99.99
f2 = 99.99
f3 = 3.5
f4 = f1
print("float f1: ", id(f1))
print("float f2: ", id(f2))
print("float f3: ", id(f3))
print("float f4: ", id(f4))
PythonOutput:
The variable with the same value has the same ID, also the variable assigned with reference has the same ID.
ID of | ID | Note |
---|---|---|
float f1 | 139663238335760 | Value is 99.99 |
float f2 | 139663238335760 | Value is 99.99 |
float f3 | 139663238342352 | |
float f4 | 139663238335760 | Value assigned from f1 |
This is how it looks-
And the same with strings-
s1 = "bigboxcode"
s2 = "bigboxcode"
s3 = "BigBoxCode"
s4 = s1
print("string s1: ", id(s1))
print("string s2: ", id(s2))
print("string s3: ", id(s3))
print("string s4: ", id(s4))
PythonOutput:
The variable with the same value has the same ID, also the variable assigned with reference has the same ID.
ID of | ID | Note |
---|---|---|
float s1 | 139663236856368 | Value is ‘bigboxcode’ |
float s2 | 139663236856368 | Value is ‘bigboxcode’ |
float s3 | 139663236856560 | |
float s4 | 139663236856368 | Value assigned from s1 |
This is how it looks-
Object Reference Rebounding
Once a variable is assigned a value, it works as an identifier to a reference of an object. But what happens when we reassign another value to that variable?
The variable will be rebound to another object reference.
Check the example below-
# Define integers i1 and i2
i1 = 100
i2 = 100
print(f"i1 => value: {i1} || type: {type(i1)} || id: {id(i1)}")
print(f"i2 => value: {i2} || type: {type(i2)} || id: {id(i2)}")
# Define another integer
i3 = 200
print(f"i3 => value: {i3} || type: {type(i3)} || id: {id(i3)}")
# Assign 200 to i2
i2 = 200
print(f"i2 => value: {i2} || type: {type(i2)} || id: {id(i2)}")
# Define a string s1
s1 = "bigboxcode"
print(f"s1 => value: {s1} || type: {type(s1)} || id: {id(s1)}")
# Change value of i2 to the same value of s2
i2 = "bigboxcode"
print(f"i2 => value: {i2} || type: {type(i2)} || id: {id(i2)}")
# Change value of i2 again to a float value
i2 = 99.99
print(f"i2 => value: {i2} || type: {type(i2)} || id: {id(i2)}")
# Define a float
f1 = 99.99
print(f"f1 => value: {f1} || type: {type(f1)} || id: {id(f1)}")
# Check the details of i2
print(f"i2 => value: {i2} || type: {type(i2)} || id: {id(i2)}")
PythonOutput:
After every reassignment, the value and type of “i2” changes. And also the reference changes. If the value already exists in memory, it refers to that existing object.
i1 => value: 100 || type: <class 'int'> || id: 139809004637520
i2 => value: 100 || type: <class 'int'> || id: 139809004637520
i3 => value: 200 || type: <class 'int'> || id: 139809004640720
i2 => value: 200 || type: <class 'int'> || id: 139809004640720
s1 => value: bigboxcode || type: <class 'str'> || id: 139809004190384
i2 => value: bigboxcode || type: <class 'str'> || id: 139809004190384
i2 => value: 99.99 || type: <class 'float'> || id: 139809003179280
f1 => value: 99.99 || type: <class 'float'> || id: 139809003179280
i2 => value: 99.99 || type: <class 'float'> || id: 139809003179280
PlaintextObject Reference Rebound on Type Change
What happens when a variable is assigned a different type of data, and the type is changed and the value already exists in memory?
The new value will be taken from the existing object reference.
# Assign some integer values
i1 = 100
i2 = 100
print(f"i1 => value: {i1} || type: {type(i1)} || id: {id(i1)}")
print(f"i2 => value: {i2} || type: {type(i2)} || id: {id(i2)}")
# Assign some string values
s1 = "100"
i2 = "100"
print(f"s1 => value: {s1} || type: {type(s1)} || id: {id(s1)}")
print(f"i2 => value: {i2} || type: {type(i2)} || id: {id(i2)}")
# Convert i2 to integer form string
print(f"i2 => value: {i2} || type: {type(int(i2))} || id: {id(int(i2))}")
PythonOutput:
After converting the value of “i2” from string(“100”) to integer(100), it started referencing the already exiting integer(100) object.
i1 => value: 100 || type: <class 'int'> || id: 140430198689104
i2 => value: 100 || type: <class 'int'> || id: 140430198689104
s1 => value: 100 || type: <class 'str'> || id: 140430198241456
i2 => value: 100 || type: <class 'str'> || id: 140430198241456
i2 => value: 100 || type: <class 'int'> || id: 140430198689104
PlaintextGet Object from ID
We have already seen that we can get the object ID of any Python object using the “id” function.
Now how to do the reverse? How to get the object if we have the ID?
We can use the package “ctypes” for that. Check the code below-
import ctypes
big_box_int = 100
big_box_int_id = id(big_box_int)
print(f'value of big_box_id is: {big_box_int}')
print(f'id of big_box_id is: {big_box_int_id}')
# Fetch value using the id
object_from_id = ctypes.cast(big_box_int_id, ctypes.py_object)
print("Object from id: ", object_from_id)
print("Value from object(of id): ", object_from_id.value)
PythonOutput:
value of big_box_id is: 100
id of big_box_id is: 139730918952272
Object from id: py_object(100)
Value from object(of id): 100
Plaintext