Unit III · Basics of Python Programming for Pharmaceutical Sciences (BP101T) · As per PCI B.Pharmacy Syllabus, NEP 2020
Once you know how to build lists, tuples, and dictionaries, the next essential skill is pulling data back out of them precisely — a single value, a sub-section, or a reversed copy. This post covers indexing and slicing on lists, the everyday operations used on lists and dictionaries, and the string manipulation techniques that let you clean and reformat text such as drug labels and prescription notes. Every technique is demonstrated with pharmacy-flavoured examples.

Indexing in Lists
Indexing means picking out one particular element of a list by referring to its position, called its index. Python numbers positions starting from zero, so the first item sits at index 0 and the second at index 1. The index must be a whole number, written inside square brackets right after the list’s name.
Positive and Negative Indexing
Python lists support two directions of indexing. Positive indexing counts from left to right starting at 0 — the everyday way of pulling out a known element. Negative indexing counts backward from the right-hand end, with the very last element sitting at -1. Negative indexing is especially handy when you want the last item (or one near the end) without knowing exactly how many elements the list holds.
drugs = ["Paracetamol", "Ibuprofen", "Aspirin"]
print(drugs[1]) # Ibuprofen (positive index, second item)
print(drugs[-1]) # Aspirin (negative index, last item)
Two important rules follow from this. First, trying to access an index that does not exist in the list raises an IndexError. Second, indexing always retrieves exactly one element — never a group. Because Python can jump straight to the correct memory location, indexing runs in constant time, O(1).
Slicing in Lists
Slicing lets you pull out a continuous section (a sub-list) of an existing list without changing the original list at all. It is one of Python’s general sequence operations, so the same technique also works on tuples and strings. The general form is list[start : stop : step].
The Three Slice Components
- start — the index where the slice begins; this element is included. Defaults to 0 if omitted.
- stop — the index where the slice ends; Python stops just before this index, so the element at “stop” itself is excluded.
- step — how many positions to move forward between selected elements; defaults to 1 if left out.
medicines = ["Paracetamol", "Ibuprofen", "Amoxicillin", "Aspirin", "Cetirizine"]
print(medicines[1:4]) # ['Ibuprofen', 'Amoxicillin', 'Aspirin'] basic slice
print(medicines[:3]) # ['Paracetamol', 'Ibuprofen', 'Amoxicillin'] from start
print(medicines[2:]) # ['Amoxicillin', 'Aspirin', 'Cetirizine'] till end
print(medicines[::2]) # ['Paracetamol', 'Amoxicillin', 'Cetirizine'] every 2nd
print(medicines[::-1]) # ['Cetirizine', 'Aspirin', 'Amoxicillin',
# 'Ibuprofen', 'Paracetamol'] reversed
Slicing always builds and returns a brand-new list; it never alters the list it was taken from. This makes it safe for exploring or filtering part of a larger dataset without corrupting the source. Because copying several elements takes proportionally longer as the slice grows, its time complexity is O(n), where n is the number of elements copied.
a[::-1] or a[1:4] on a given list. Practice tracing start/stop/step manually — remember stop is always excluded, and a step of -1 reverses direction entirely.Basic Operations on Lists and Dictionaries
Beyond indexing and slicing, both lists and dictionaries support a common set of operations you will use in nearly every pharmacy script.
List Operations
a = [10, 20, 30]
a.append(50) # [10, 20, 30, 50] add to end
a.insert(1, 15) # [10, 15, 20, 30, 50] add at position
a.remove(20) # removes the value 20
a.pop() # removes and returns the last element
del a[1] # deletes the element at index 1
a[0] = 100 # update by index
print(30 in a) # membership test -> True/False
print(a + [60, 70]) # concatenation
print(a * 2) # repetition
print(len(a)) # length
Traversal — visiting every element in turn, typically with a for loop — is essential whenever the same processing step needs to run across an entire dataset, such as printing every drug in a stock list.
Dictionary Operations
d = {"name": "Ram", "age": 20}
print(d["name"]) # Ram access by key
d["city"] = "Mumbai" # add a new key-value pair
d["age"] = 21 # update an existing value
d.pop("age") # remove by key
del d["name"] # remove using del
for key in d:
print(key, d[key]) # traverse the dictionary
print("city" in d) # membership test on keys
print(d.keys()) # all keys
print(d.values()) # all values
print(d.items()) # key-value pairs together
print(len(d)) # number of key-value pairs
Dictionary values are looked up by key rather than by numeric position, and this key-based lookup is, on average, considerably faster than scanning through a list to find a matching value — a distinction that matters once a dataset grows beyond a handful of records.
String Manipulation Techniques
A string is a sequence of characters written inside quotation marks, and string manipulation covers all the operations used to create, change, examine, and format text — essential whenever you’re standardising a drug label or parsing text from a prescription. Strings share four defining traits with lists: they are ordered, indexed, and iterable, but unlike lists, they are immutable — once created, a string’s contents cannot be changed in place.
Common String Methods
| Method / Operation | Purpose | Example |
|---|---|---|
| Indexing / Slicing | Retrieve one character or a substring | s[0], s[1:4] |
upper() / lower() / capitalize() |
Change letter case | "paracetamol".upper() |
strip() |
Remove leading/trailing whitespace | " hello ".strip() |
replace() |
Swap a substring for another | label.replace("500mg","650mg") |
split() |
Break a string into a list of pieces | "apple,banana".split(",") |
join() |
Stitch a list of strings into one string | ", ".join(["a","b"]) |
find() |
Return index of first match, or -1 | "Python".find("th") |
label = "paracetamol 500mg"
print(label.upper()) # PARACETAMOL 500MG
new_label = label.replace("500mg", "650mg")
print(new_label) # paracetamol 650mg
words = label.split()
print(words) # ['paracetamol', '500mg']
name = "Ram"
age = 20
print(f"My name is {name} and age is {age}") # f-string formatting
Formatted strings, or f-strings, let you insert the values of variables directly into a piece of text using curly braces — the standard way to build dynamic, human-readable output such as a formatted patient summary line.
s.upper() returns a new string rather than changing s itself. A common trick question asks what print(s) outputs after calling a string method without reassigning the result — the answer is the original, unchanged string.Worked Program: Managing a Drug Stock List and Patient Prescription
The following combined example applies indexing, slicing, list operations, dictionary operations, and string formatting together, mirroring how a small pharmacy inventory script might look.
drugs = ["Paracetamol", "Ibuprofen", "Aspirin", "Amoxicillin"]
# Indexing and slicing
print(drugs[0]) # Paracetamol first drug
print(drugs[-1]) # Amoxicillin last drug
print(drugs[1:3]) # ['Ibuprofen', 'Aspirin'] middle drugs
# Managing a drug stock list
stock = ["Paracetamol", "Ibuprofen"]
stock.append("Aspirin")
stock.insert(1, "Cetrizine")
stock.remove("Ibuprofen")
stock[0] = "Paracetamol 650mg"
print(stock) # ['Paracetamol 650mg', 'Cetrizine', 'Aspirin']
# Patient prescription as a dictionary
patient = {"name": "Anita", "drug": "Paracetamol", "dose": "500mg"}
patient["dose"] = "650mg"
print(f"Patient: {patient['name']}")
print(f"Drug: {patient['drug'].upper()}")
print(f"Dose: {patient['dose']}")
This single script shows lists holding drug inventories, a dictionary holding a structured patient record, and string methods formatting the final output — three techniques that, together, cover most everyday pharmacy data-handling tasks in Python.
Frequently Asked Questions
Does slicing a list change the original list?
No. Slicing always creates and returns a completely new list object; the original list is left untouched. If you want to modify the original, you must explicitly reassign, e.g. a = a[1:].
What is the difference between remove() and pop() on a list?
remove(value) deletes the first occurrence of a given value and does not return anything useful. pop(index) deletes the element at a given position (or the last element, if no index is given) and returns that removed value, so you can capture it in a variable.
Why can’t I change a single character of a string directly, like s[0] = "P"?
Strings are immutable in Python, so this raises a TypeError. To “change” a string, you must build a new one — either through slicing and concatenation, or by using a method such as replace() that returns a new string.
Summary
Indexing retrieves a single list element by position, using positive indices from the front or negative indices from the back, while slicing extracts a whole sub-list using the start:stop:step pattern without touching the original data. Lists and dictionaries share operations like adding, updating, removing, traversing, and checking membership, though a dictionary’s key-based lookup is far faster than scanning a list. Strings, though immutable, offer a rich toolkit of methods — case conversion, trimming, replacing, splitting, joining, and f-string formatting — that are constantly used to clean and present pharmacy text data such as drug labels and prescription details.
References
- Pharmacy Council of India (PCI), B.Pharm Regulations, NEP 2020 — BP101T Syllabus, Basics of Python Programming for Pharmaceutical Sciences
- Python Software Foundation, “Sequence Types — list, tuple, range” — official Python documentation, docs.python.org
- Python Software Foundation, “String Methods” — official Python documentation, docs.python.org
