Skip to content

Chapter 3: Built-in Functions and Function Calls

Updated: 2026-10-10 13:30 · English
Table of contents (10)

Navigation: Previous: Chapter 2 - Functions

Language: English | 中文版

In Chapter 2, we used def to define functions. A function lets us apply the same calculation or processing rule to different inputs without copying the code each time.

Many data processing tasks recur across programs: measuring text length, converting data types, finding the smallest or largest value, rounding numbers, and splitting or joining strings. Python already provides tools for these tasks:

  1. Built-in functions can be called directly as function_name(data). Examples include len(s), abs(x), and round(n).
  2. Built-in methods belong to objects of particular types. We call them as object.method_name(...), as in text.split(",") or text.find("@").

A business calculation often needs several of these tools. We can pass the return value of one function to another, or let a function call smaller functions to complete separate steps.


Part 1: Core Concepts

3.1 Understanding Function Calls

3.1.1 Argument Evaluation and Call Order

In Chapter 1 and Chapter 2, we used calls such as amount = calculate_subtotal(28.5, 4). The arguments were values written directly in the code.

An argument can also be an expression. In that case, Python evaluates the argument expressions before passing their values to the function.

Example: Calculate a purchase total after a price increase. Follow the argument calculations before the function begins its work.

python
def calculate_subtotal(unit_price: float, quantity: int) -> float:
    return unit_price * quantity

# Base price: 20 yuan; increase: 5 yuan; purchase: 2 sets of 2 items
total = calculate_subtotal(20 + 5, 2 * 2)
print(total)

Output:

text
100

The call calculate_subtotal(20 + 5, 2 * 2) proceeds as follows:

  1. Python evaluates the argument expressions from left to right: 20 + 5 gives 25, and 2 * 2 gives 4.
  2. It binds these values to the parameters unit_price and quantity.
  3. The function body computes 25 * 4 and returns 100.
  4. The assignment stores the return value in total.

3.1.2 Composing Calls: Passing One Function's Result to Another

In mathematics, the composition (g \circ f)(x) = g(f(x)) means that we first compute f(x), then use its result as the input to g.

We can use the same pattern in Python: an inner call produces a return value, which becomes an argument to an outer call. This is a nested function call.

Example: Convert an integer order ID to text and count its digits.

python
order_id = 10086315

# Separate steps: convert to text, then measure its length
order_str = str(order_id)
digit_count = len(order_str)
print(digit_count)

# Nested calls: pass the result of str() directly to len()
print(len(str(order_id)))

Output:

text
8
8

In print(len(str(order_id))):

  1. str(order_id) returns the string "10086315".
  2. len("10086315") returns the integer 8.
  3. print() displays 8 in the terminal.

Nested calls can reduce the need for temporary variables. Too many levels in one line can make the calculation hard to follow. For example, if a line contains more than three nested calls, consider writing the calculation in two or three separate statements.

3.1.3 Calling a Function from Another Function

A larger task can be divided into smaller tasks. One function can call another function to carry out a step. Each function then has a clear job and can be tested or reused on its own.

Example: Calculate an order payment. A helper function computes the item subtotal. The main function calls the helper, subtracts a coupon discount, and adds the shipping fee.

python
def calculate_subtotal(unit_price: float, quantity: int) -> float:
    """Return the subtotal for an item purchase."""
    return unit_price * quantity


def calculate_order_payment(
    unit_price: float,
    quantity: int,
    coupon_discount: float,
    shipping_fee: float,
) -> float:
    """Return the amount payable for an order."""
    # 1. Call the helper to obtain the item subtotal
    subtotal = calculate_subtotal(unit_price, quantity)
    # 2. Apply the coupon discount and add shipping
    final_amount = subtotal - coupon_discount + shipping_fee
    return final_amount


# Unit price: 80 yuan; quantity: 2; coupon: 20 yuan; shipping: 6 yuan
bill = calculate_order_payment(80.0, 2, 20.0, 6.0)
print(bill)

Output:

text
146.0

The flow of execution is:

  1. Python reaches bill = calculate_order_payment(80.0, 2, 20.0, 6.0).
  2. It enters the body of calculate_order_payment.
  3. The first statement calls calculate_subtotal(unit_price, quantity).
  4. The main function waits while the helper function runs.
  5. The helper computes 80.0 * 2 and returns 160.0.
  6. The main function resumes and assigns that return value to its local variable subtotal.
  7. It computes 160.0 - 20.0 + 6.0 = 146.0.
  8. Its return statement passes 146.0 back to the caller, where the value is assigned to bill.

The helper calculate_subtotal remains available for other calculations. Calling it from the main function does not restrict where else it can be used.


Practice: Change the purchase quantity to 3. Predict the payment before running the code, then check the result. It should be 226.0.


3.2 Built-in Functions for Length and Numeric Calculations

3.2.1 Measuring Length: len()

The built-in function len() returns the number of elements in an object. For a string, it counts the characters, including Chinese characters, English letters, digits, spaces, and punctuation.

Example: Check whether a phone number has 11 characters and whether a password meets a minimum length of 8 characters.

python
phone = "13812345678"
password = "safe_password_99"

phone_length = len(phone)
password_length = len(password)

print("Phone number length:", phone_length)
print("Phone number has 11 characters:", phone_length == 11)
print("Password meets the length requirement:", password_length >= 8)

Output:

text
Phone number length: 11
Phone number has 11 characters: True
Password meets the length requirement: True

len() works with objects that have a length, such as strings and the lists, tuples, and dictionaries introduced in later chapters. An integer or floating-point number does not have a length, so len(123) raises TypeError. To count the digits of a positive integer, first convert it to a string with str().

3.2.2 Absolute Values and Rounding: abs() and round()

Absolute Value: abs()

For real numbers, abs() returns the absolute value. Positive numbers and zero stay the same; a negative number becomes its positive counterpart.

Example: Measure the size of the difference between a branch's monthly revenue and its budget target.

python
target_budget = 50000.0   # Target: 50,000 yuan
actual_revenue = 46200.0  # Actual revenue: 46,200 yuan

# Measure the difference without its sign
gap = abs(actual_revenue - target_budget)
print(f"Absolute revenue gap: {gap} yuan")

Output:

text
Absolute revenue gap: 3800.0 yuan

The absolute value measures how far revenue is from the target, whether revenue is above or below it.

Rounding: round()

round(number, ndigits) rounds a number to the specified number of decimal places:

  • number is the value to round.
  • ndigits gives the number of decimal places. If it is omitted, the function rounds to the nearest integer for the numeric types used here.

Example: Divide a discounted total equally among three items, then round the price per item to two decimal places.

python
original_price = 199.0
discount_rate = 0.85
item_count = 3

total_discounted = original_price * discount_rate
price_per_item = total_discounted / item_count

print("Unrounded price per item:", price_per_item)
print("Rounded to two decimal places:", round(price_per_item, 2))

Output:

text
Unrounded price per item: 56.38333333333333
Rounded to two decimal places: 56.38

Rounding ties to even: When a value lies exactly halfway between two rounding choices, Python's round() chooses the one whose last retained digit is even. This rule is also called banker's rounding or round half to even. For example, round(2.5) is 2, whereas round(3.5) is 4. The rule avoids always rounding exact halfway cases upward.

3.2.3 Minimums, Maximums, and Business Limits: min() and max()

min() returns the smallest of its arguments, and max() returns the largest. We can pass two or more numbers:

python
print(min(10, 25, 8, 30))  # Output: 8
print(max(10, 25, 8, 30))  # Output: 30

These functions also express business rules that set an upper or lower limit:

  1. Upper limit (cap): Use min(calculated_value, upper_limit). For example, a promotion may offer a 15% discount, capped at 50 yuan per order.
  2. Lower limit (floor): Use max(calculated_value, lower_limit). For example, a delivery charge may depend on distance but have a minimum fee of 15 yuan.

Example: Apply a 50-yuan cap to a coupon discount and a 15-yuan minimum to a local delivery fee.

python
# 1. Cap the coupon discount
order_amount = 400.0
discount_calculated = order_amount * 0.15  # Before the cap: 60 yuan
max_discount_allowed = 50.0               # Maximum discount: 50 yuan

# Keep the actual discount at or below 50 yuan
actual_discount = min(discount_calculated, max_discount_allowed)
print("Actual discount:", actual_discount)

# 2. Apply a minimum delivery fee
distance_km = 3.5
shipping_calculated = distance_km * 3.0  # Distance charge: 10.5 yuan
min_shipping_fee = 15.0                 # Minimum fee: 15 yuan

# Keep the actual delivery fee at or above 15 yuan
actual_shipping = max(shipping_calculated, min_shipping_fee)
print("Actual delivery fee:", actual_shipping)

Output:

text
Actual discount: 50.0
Actual delivery fee: 15.0

3.3 Common String Methods

In Chapter 1, we used strip() and replace(). These are string methods. A string method is called through a string object, using the form text.method_name(...).

3.3.1 Splitting Text: split()

split() divides a string at a specified separator and returns the resulting pieces in a list.

The call has the form text.split(separator).

Example: Split a simple comma-separated transaction record, then extract the product name, unit price, and quantity.

python
# A transaction record with comma-separated fields
record = "2026-09-08,Wireless Mechanical Keyboard,299.0,2"

fields = record.split(",")
print("Fields after splitting:", fields)

# Extract the fields and convert the numeric values
product_name = fields[1]
unit_price = float(fields[2])
quantity = int(fields[3])

subtotal = unit_price * quantity
print(f"Product: {product_name}, total: {subtotal} yuan")

Output:

text
Fields after splitting: ['2026-09-08', 'Wireless Mechanical Keyboard', '299.0', '2']
Product: Wireless Mechanical Keyboard, total: 598.0 yuan

Splitting without a separator: A call to split() with no arguments splits on whitespace, including spaces, tabs (\t), and newlines (\n). It treats consecutive whitespace characters as one separator and discards leading and trailing whitespace.

Example: Split a search query whose keywords are separated by uneven spaces.

python
raw_query = "  Python    business-data-analysis     beginner-guide  "
keywords = raw_query.split()
print(keywords)

Output:

text
['Python', 'business-data-analysis', 'beginner-guide']

3.3.2 Joining Text: join()

join() combines a sequence of strings into one string, placing a chosen separator between them.

The call has the form separator.join(string_sequence).

Which object calls the method? The separator comes before .join(), and the sequence of strings goes inside the parentheses. For example, use "-".join(parts), rather than parts.join("-").

Example: Join year, month, and day strings into a date, then join product categories into a navigation path.

python
# 1. Join the parts of a date
date_parts = ["2026", "09", "08"]
formatted_date = "-".join(date_parts)
print("Formatted date:", formatted_date)

# 2. Join the levels of a product category
categories = ["Digital and Office", "Computer Peripherals", "Mechanical Keyboards"]
breadcrumb = " > ".join(categories)
print("Product category path:", breadcrumb)

Output:

text
Formatted date: 2026-09-08
Product category path: Digital and Office > Computer Peripherals > Mechanical Keyboards

Every element passed to join() must be a string. Convert any numeric elements to strings first; otherwise, join() raises TypeError.

3.3.3 Finding and Counting Substrings: find() and count()

Finding a Substring: find()

find(sub) searches a string for the substring sub:

  • If it finds a match, it returns the starting index of the first occurrence, counting from 0.
  • If there is no match, it returns -1.

Example: Find the @ symbol in an email address and extract the username before it.

python
email = "li_minghui@university.edu.cn"

at_index = email.find("@")
print("Index of @:", at_index)

# Extract the username before @
username = email[:at_index]
print("Extracted username:", username)

# Search for a substring that is absent
print(email.find("#"))

Output:

text
Index of @: 10
Extracted username: li_minghui
-1

A missing substring does not cause find() to raise an error. It returns -1, so a presence check must distinguish that value from a valid index. The example above assumes that the email address contains @.

Counting Occurrences: count()

count(sub) returns the number of non-overlapping occurrences of a substring.

Example: Count the words "how" and "why" in a customer message as a first step toward identifying requests for help.

python
feedback = "Please tell me how to request an invoice and how to change the delivery address."

count_how = feedback.count("how")
count_why = feedback.count("why")

print("Occurrences of 'how':", count_how)
print("Occurrences of 'why':", count_why)

Output:

text
Occurrences of 'how': 2
Occurrences of 'why': 0

3.3.4 Checking Prefixes and Suffixes: startswith() and endswith()

  • startswith(prefix) checks whether a string begins with the specified prefix.
  • endswith(suffix) checks whether a string ends with the specified suffix.

Both methods return a Boolean value: True or False.

Example: Identify a refund ticket by its "REF-" prefix and check whether a report filename ends in ".csv".

python
order_code = "REF-20260908-8801"
filename = "monthly_sales_report.csv"

is_refund = order_code.startswith("REF-")
is_csv_file = filename.endswith(".csv")

print("Refund order:", is_refund)
print("CSV report:", is_csv_file)

Output:

text
Refund order: True
CSV report: True

These methods are case-sensitive. For example, filename.endswith(".CSV") returns False for the filename above.


Core Exercises

Exercise 1: Validate a Membership Card ID

Task: Write validate_member_card(card_id: str) -> bool to check whether a card ID follows the issuing rules.

Rules:

  • The ID must contain exactly 10 characters.
  • It must begin with "VIP-".
  • Return True when both conditions hold, and False otherwise.

Check the return values with these calls:

Test call Expected return value Explanation
validate_member_card("VIP-100869") True Contains 10 characters and begins with VIP-
validate_member_card("VIP-88") False Fewer than 10 characters
validate_member_card("REG-100869") False Does not begin with VIP-
validate_member_card("VIP-100869001") False More than 10 characters

Exercise 2: Calculate an Order Payment with a Capped Discount

Task: Write two functions that divide an order calculation into separate steps.

Rules:

  1. The helper function calculate_subtotal(unit_price, quantity) returns unit_price * quantity.
  2. The main function calculate_order_payment(unit_price, quantity, coupon_rate, max_coupon, shipping_fee):
    • Calls calculate_subtotal to obtain the item subtotal.
    • Computes the discount before the cap as subtotal * coupon_rate.
    • Applies the cap with min(calculated_discount, max_coupon).
    • Computes the payment as subtotal - actual_discount + shipping_fee.
    • Uses round() to round the payment to two decimal places and returns it.

Annotate quantity as int. Annotate the other parameters and both return values as float.

Check the return values with these calls:

Test call Expected return value Calculation
calculate_order_payment(100.0, 3, 0.2, 50.0, 10.0) 260.0 Subtotal: 300 yuan; calculated discount: 60 yuan; capped discount: 50 yuan; payment: 300 - 50 + 10 = 260.0 yuan
calculate_order_payment(100.0, 1, 0.2, 50.0, 10.0) 90.0 Subtotal: 100 yuan; discount: 20 yuan, below the 50-yuan cap; payment: 100 - 20 + 10 = 90.0 yuan

Exercise 3: Clean and Reformat a Transaction Record

Task: Write format_transaction_record(raw_record: str) -> str to parse a record with extra spaces and return a formatted message.

Input and rules:

  • The input contains four fields separated by vertical bars: " 2026-09-08 | Li Minghui | 299.0 | 2 ".
  • Split the fields with split("|").
  • Remove leading and trailing whitespace from each field.
  • Compute the total as float(unit_price_text) * int(quantity_text).
  • Return "Customer Li Minghui purchased 2 items on 2026-09-08. Total payable: ¥598.00", with the amount displayed to two decimal places.

Check the result:

  • Call: format_transaction_record(" 2026-09-08 | Li Minghui | 299.0 | 2 ").
  • Expected return value: "Customer Li Minghui purchased 2 items on 2026-09-08. Total payable: ¥598.00".

Part 2: Advanced Topics

These sections provide optional material on object identity, console input, and method chaining. The core exercises do not require them.

3.4 Object Identity: id() and is

3.4.1 Inspecting an Object's Identity: id()

id() returns an integer that identifies an object. That identity remains unchanged during the object's lifetime and differs from the identity of every other object that exists at the same time. In CPython, it is the object's memory address.

Example: Inspect the identities of objects referred to by different variables.

python
name_a = "Li Minghui"
name_b = "Li Minghui"
name_c = "Zhao Lin"

print("id of name_a:", id(name_a))
print("id of name_b:", id(name_b))
print("id of name_c:", id(name_c))

Two variables may refer to the same object. For example, Python may reuse an equal string object for name_a and name_b. Their identities describe which objects they refer to, not whether the variable names are different.

3.4.2 Equality and Identity: == and is

== and is answer different questions:

  • == (equality) compares the values of the objects used in these examples.
  • is (identity) checks whether two variables refer to the very same object, equivalent to comparing their IDs with id(a) == id(b).

Example: Create two separate lists with equal contents.

python
# Create two lists with the same numbers; Chapter 4 covers lists in detail
list_1 = [1, 2, 3]
list_2 = [1, 2, 3]

# Compare their contents
print(list_1 == list_2)

# Check whether they are the same object
print(list_1 is list_2)
print("id of list_1:", id(list_1))
print("id of list_2:", id(list_2))

One possible output is:

text
True
False
id of list_1: 2548231950400
id of list_2: 2548231948864

The numeric IDs vary between runs. The two lists are separate objects, so their IDs differ and is returns False. Their contents are equal, so == returns True.

Usage guidelines:

  1. Use == to compare the values of numbers or strings.
  2. Use is when object identity matters. A common example is checking for the singleton None, as in if x is None:.

3.5 Interactive Input: input()

3.5.1 Reading Keyboard Input

So far, the example data have been written directly into the code. input(prompt) lets a user supply data through the terminal. The program waits until the user types a line and presses Enter.

  • prompt is the message displayed to the user.
  • input() returns the entered text as a string.

Example: Read a user's name and display a greeting.

python
user_name = input("Enter your name: ")
print(f"Hello, {user_name}! Welcome to the Python learning system.")

If the user enters Li Minghui, the terminal displays:

text
Enter your name: Li Minghui
Hello, Li Minghui! Welcome to the Python learning system.

3.5.2 Converting Input to Numbers

Input is text: Entering 100 produces the string "100", not the integer 100. Convert numeric input with int() or float() before using it in a numeric calculation. For example, adding the string "100" to the number 1 raises TypeError.

Example: Read an item's unit price and purchase quantity, then calculate the payment.

python
# Read the input strings and convert them to numbers
raw_price = input("Enter the unit price (yuan): ")
unit_price = float(raw_price)

raw_qty = input("Enter the quantity (items): ")
quantity = int(raw_qty)

total = unit_price * quantity
print(f"Total purchase amount: {total:.2f} yuan")

We can also combine input and conversion in one statement:

python
unit_price = float(input("Enter the unit price: "))
quantity = int(input("Enter the quantity: "))

3.6 Method Chaining

Many string methods return a string. We can call another method directly on that return value. A sequence of calls joined by dots is called method chaining.

The method calls run from left to right: each method receives the result of the preceding call.

Example: Clean a search phrase by removing surrounding whitespace, converting letters to lowercase, and replacing underscores with spaces.

python
dirty_input = "   Python_DATA_ANALYSIS_GUIDE   "

# Apply strip(), then lower(), then replace()
clean_text = dirty_input.strip().lower().replace("_", " ")
print(clean_text)

Output:

text
python data analysis guide

The intermediate values are:

  1. dirty_input.strip() returns "Python_DATA_ANALYSIS_GUIDE".
  2. .lower() returns "python_data_analysis_guide".
  3. .replace("_", " ") returns "python data analysis guide".

The chain records the cleaning steps in order without requiring a separate variable for each intermediate string.


Advanced Exercises

Exercise 1: Build an Interactive Currency Converter

Task: Write an interactive function named run_currency_converter() -> None.

Rules:

  • Prompt the user with "Enter the amount in US dollars (USD): ".
  • Convert the input string with float().
  • Use the fixed rate 1 US dollar = 7.15 yuan for this exercise.
  • Round the result to two decimal places with round().
  • Display the converted amount, for example: "Amount in Chinese yuan (CNY): 715.00 yuan".

Exercise 2: Observe Object Identity after Reassignment

Task: Write a script to observe how id() changes when a variable is assigned a new value.

Steps:

  1. Assign score = 90, then display id(score).
  2. Execute score = score + 5.
  3. Display id(score) again.
  4. Compare the two IDs. Recall string immutability from Chapter 1. Strings and numbers are immutable; this assignment binds score to the object representing the new value rather than changing the original object. Use this distinction to explain the result.

Navigation: Previous: Chapter 2 - Functions