Python Quick Guide - Step 1 Basic Syntax and Data Types (6) - Lists (2)
- This course is designed to help you learn the basics of Python programming as quickly as possible through hands-on practice.
- The “Style Guide” sections primarily cover guidelines from PEP8 for writing clean Python code.
- You can run and see the results of each code example.
Feel free to experiment with the code - reloading the page will reset the content.
This is a continuation of “Step 1: Basic Syntax and Data Types”.
1.5. Organizing Data
1.5.1. Lists
List Operations
Existence Check (in
, not in
)
- To check if an element exists in a list, use the
in
operator.
- The
not in
operator performs the opposite check of thein
operator.
Slicing
- You can get a subset of a list by specifying a range as
[start:end]
.- This subset is called a slice.
- The slice includes elements from
start
up to but not includingend
(start <= x < end
). - Note that the element at the
end
index is not included.
- If the specified range exceeds the actual list range,
no error occurs and it returns a slice containing only elements within the actual range.- If there are no values in the specified range, an empty list (
[]
) is returned. - With slices, specifying an out-of-range index does not raise an
IndexError
.
- If there are no values in the specified range, an empty list (
- If you omit the start position (
[:end]
), the slice begins from the start of the list. - If you omit the end position (
[start:]
), the slice continues to the end of the list.
- You can specify
[start:end:step]
to get a slice with elements at intervals ofstep
.
- Specifying a negative value for
step
creates a reversed slice.- Since it proceeds in reverse order, the slice includes elements where
start >= x > end
(the element atend
is not included in the slice).
- Since it proceeds in reverse order, the slice includes elements where
- With a negative step:
- If you omit the start position, the slice begins from the end of the list.
- If you omit the end position, the slice continues to the beginning of the list.
Using a list containing numbers 1 to 20, perform the following:
- Output a slice containing numbers 5 to 15.
- Output a slice containing only multiples of 5.
- Output a reversed slice containing only multiples of 3.
Modifying Lists with Slices
- You can replace elements in a list using slices.
- Be careful as you can assign lists of different sizes without causing errors.
Copying Lists
In “1.4. Variables and Assignment”, we explained that variables are like “labels”. Here, we’ll demonstrate a common mistake in Python that illustrates how variables work as labels.
As you can see from running the above code, the original price list (original_prices
) has also changed.
This can be understood by thinking of variables as “labels”.
graph TD subgraph "Step 3: Modifying an Element" list3["[500, 1500, 5000]"] original_prices3[original_prices] --> list3 new_prices3[new_prices] --> list3 end subgraph "Step 2: Assigning to a New Variable" list2["[1000, 1500, 5000]"] original_prices2[original_prices] --> list2 new_prices2[new_prices] --> list2 end subgraph "Step 1: Initial State" list1["[1000, 1500, 5000]"] original_prices1[original_prices] --> list1 end style list1 fill:#fff3bf,stroke:#333,stroke-width:2px style list2 fill:#fff3bf,stroke:#333,stroke-width:2px style list3 fill:#fff3bf,stroke:#ff0000,stroke-width:2px
In Python, when you assign a variable to a new variable, the new variable doesn’t get a copy of the data. Instead, the new variable becomes another label pointing to the original data. (In other words, both the original variable and the new variable refer to the same underlying data.)
- To copy a list, use the
copy()
method.
graph TB %% Step 1: Initial State subgraph step1["Step 1: Initial State"] direction TB op1[original_prices] --> list1["[1000, 1500, 5000]"] end step1 --> step2 %% Step 2: After copy() method subgraph step2["Step 2: Copy the list using copy() method"] direction TB op2[original_prices] --> list2["[1000, 1500, 5000]"] list2 -. "copy()" .-> list2_copy["[1000, 1500, 5000] (copy)"] np2[new_prices] --> list2_copy end step2 --> step3 %% Step 3: After modification subgraph step3["Step 3: After modifying an element in the new list"] direction TB op3[original_prices] --> list3["[1000, 1500, 5000]"] np3[new_prices] --> list3_copy["[500, 1500, 5000]"] end %% Style settings style list1 fill:#fff3bf,stroke:#333,stroke-width:2px style list2 fill:#fff3bf,stroke:#333,stroke-width:2px style list3 fill:#fff3bf,stroke:#333,stroke-width:2px style list2_copy fill:#fff3bf,stroke:#333,stroke-width:2px style list3_copy fill:#fff3bf,stroke:#ff0000,stroke-width:2px linkStyle 3 stroke:#4285F4,stroke-width:2px
- You can also copy a list using the slice notation with omitted start and end positions
[:]
.
However, there are cases where even the copy()
method or the [:]
slice can cause problems.
Here’s an example:
This happens because the copy()
method or the [:]
slice only duplicates the outer list ([..., ..., ...]
),
but the inner values (["apple", 120]
, etc.) are not duplicated and still reference the same values as the original list.
This type of copy is called a “shallow copy”.
graph TB %% Step 1: Initial State subgraph step1["Step 1: Initial State"] direction TB np1[name_and_prices] --> outer1["[..., ..., ...]"] outer1 --> apple1["['apple', 120]"] outer1 --> orange1["['orange', 150]"] outer1 --> grape1["['grape', 180]"] end step1 --> step2 %% Step 2: After copy() method subgraph step2["Step 2: Copy the list using copy() method"] direction TB np2[name_and_prices] --> outer2["[..., ..., ...]"] nnp2[new_name_and_prices] --> outer2_copy["[..., ..., ...] (copy)"] outer2 --> apple2["['apple', 120]"] outer2 --> orange2["['orange', 150]"] outer2 --> grape2["['grape', 180]"] outer2_copy --> apple2 outer2_copy --> orange2 outer2_copy --> grape2 end step2 --> step3 %% Step 3: After modification subgraph step3["Step 3: After modifying an element inside a list element"] direction TB np3[name_and_prices] --> outer3["[..., ..., ...]"] nnp3[new_name_and_prices] --> outer3_copy["[..., ..., ...] (copy)"] outer3 --> apple3["['apple', 120]"] outer3 --> orange3["['orange', 200]"] outer3 --> grape3["['grape', 180]"] outer3_copy --> apple3 outer3_copy --> orange3 outer3_copy --> grape3 end %% Style settings style outer1 fill:#fff3bf,stroke:#333,stroke-width:2px style outer2 fill:#fff3bf,stroke:#333,stroke-width:2px style outer3 fill:#fff3bf,stroke:#333,stroke-width:2px style outer2_copy fill:#fff3bf,stroke:#333,stroke-width:2px style outer3_copy fill:#fff3bf,stroke:#333,stroke-width:2px style apple1 fill:#ffc078,stroke:#333,stroke-width:2px style orange1 fill:#ffc078,stroke:#333,stroke-width:2px style grape1 fill:#ffc078,stroke:#333,stroke-width:2px style apple2 fill:#ffc078,stroke:#333,stroke-width:2px style orange2 fill:#ffc078,stroke:#333,stroke-width:2px style grape2 fill:#ffc078,stroke:#333,stroke-width:2px style apple3 fill:#ffc078,stroke:#333,stroke-width:2px style orange3 fill:#ffc078,stroke:#ff0000,stroke-width:2px style grape3 fill:#ffc078,stroke:#333,stroke-width:2px
- When you replace an entire element (list) instead of modifying elements inside it, it works as a “reassignment of labels” as explained in “1.4.3. Variable Reassignment”, so it doesn’t affect the original list.
graph TB %% Step 1: Initial State subgraph step1["Step 1: Initial State"] direction TB np1[name_and_prices] --> outer1["[..., ..., ...]"] outer1 --> apple1["['apple', 120]"] outer1 --> orange1["['orange', 150]"] outer1 --> grape1["['grape', 180]"] end step1 --> step2 %% Step 2: After copy() method subgraph step2["Step 2: Copy the list using copy() method"] direction TB np2[name_and_prices] --> outer2["[..., ..., ...]"] nnp2[new_name_and_prices] --> outer2_copy["[..., ..., ...] (copy)"] outer2 --> apple2["['apple', 120]"] outer2 --> orange2["['orange', 150]"] outer2 --> grape2["['grape', 180]"] outer2_copy --> apple2 outer2_copy --> orange2 outer2_copy --> grape2 end step2 --> step3 %% Step 3: After replacing an element subgraph step3["Step 3: After replacing an entire element in the new list"] direction TB np3[name_and_prices] --> outer3["[..., ..., ...]"] nnp3[new_name_and_prices] --> outer3_copy["[..., ..., ...] (copy)"] outer3 --> apple3["['apple', 120]"] outer3 --> orange3["['orange', 150]"] outer3 --> grape3["['grape', 180]"] outer3_copy --> apple3 outer3_copy --> orange3 outer3_copy -. "before replacement" .-> grape3 outer3_copy -- "after replacement" --> banana3["['banana', 200]"] end %% Style settings style outer1 fill:#fff3bf,stroke:#333,stroke-width:2px style outer2 fill:#fff3bf,stroke:#333,stroke-width:2px style outer3 fill:#fff3bf,stroke:#333,stroke-width:2px style outer2_copy fill:#fff3bf,stroke:#333,stroke-width:2px style outer3_copy fill:#fff3bf,stroke:#333,stroke-width:2px style apple1 fill:#ffc078,stroke:#333,stroke-width:2px style orange1 fill:#ffc078,stroke:#333,stroke-width:2px style grape1 fill:#ffc078,stroke:#333,stroke-width:2px style apple2 fill:#ffc078,stroke:#333,stroke-width:2px style orange2 fill:#ffc078,stroke:#333,stroke-width:2px style grape2 fill:#ffc078,stroke:#333,stroke-width:2px style apple3 fill:#ffc078,stroke:#333,stroke-width:2px style orange3 fill:#ffc078,stroke:#333,stroke-width:2px style grape3 fill:#ffc078,stroke:#333,stroke-width:2px style banana3 fill:#ffc078,stroke:#ff0000,stroke-width:2px
Think about what would happen if we ran the above code without using the copy()
method.
In contrast to the shallow copy described above, a copy that completely duplicates all elements, including nested elements, is called a “deep copy”.
You can perform a deep copy using the deepcopy
function from the copy
library:
(We’ll explain more about “libraries” later)
Unpacking
- If you want to assign each element of a list to a separate variable, you can write variables separated by commas (
,
) on the left side of the equals sign (=
).- This operation is called unpacking.
- If the number of variables doesn’t match the number of elements, a
ValueError
occurs.
- Using the unpacking operator
*
, you can unpack elements into “the first element” and “the rest”. (This*
is different from the multiplication operator; it’s placed before a variable name.)
- Using multiple unpacking operators
*
in a single unpacking operation raises aSyntaxError
.
- When unpacking, you can use an underscore (
_
) to receive values you don’t need.- This is a Python convention to explicitly indicate that you’re not using that value.
Type Conversion with the bool
Function
- When the
bool
function is applied to a list, it returnsFalse
if the list is empty ([]
), andTrue
otherwise.