Chapter 3: Built-in Functions and Function Calls
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:
- Built-in functions can be called directly as
function_name(data). Examples includelen(s),abs(x), andround(n). - Built-in methods belong to objects of particular types. We call them as
object.method_name(...), as intext.split(",")ortext.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.
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:
100
The call calculate_subtotal(20 + 5, 2 * 2) proceeds as follows:
- Python evaluates the argument expressions from left to right:
20 + 5gives25, and2 * 2gives4. - It binds these values to the parameters
unit_priceandquantity. - The function body computes
25 * 4and returns100. - 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.
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:
8
8
In print(len(str(order_id))):
str(order_id)returns the string"10086315".len("10086315")returns the integer8.print()displays8in 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.
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:
146.0
The flow of execution is:
- Python reaches
bill = calculate_order_payment(80.0, 2, 20.0, 6.0). - It enters the body of
calculate_order_payment. - The first statement calls
calculate_subtotal(unit_price, quantity). - The main function waits while the helper function runs.
- The helper computes
80.0 * 2and returns160.0. - The main function resumes and assigns that return value to its local variable
subtotal. - It computes
160.0 - 20.0 + 6.0 = 146.0. - Its
returnstatement passes146.0back to the caller, where the value is assigned tobill.
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.
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:
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.
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:
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:
numberis the value to round.ndigitsgives 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.
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:
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)is2, whereasround(3.5)is4. 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:
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:
- Upper limit (cap): Use
min(calculated_value, upper_limit). For example, a promotion may offer a 15% discount, capped at 50 yuan per order. - 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.
# 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:
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.
# 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:
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.
raw_query = " Python business-data-analysis beginner-guide "
keywords = raw_query.split()
print(keywords)
Output:
['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 thanparts.join("-").
Example: Join year, month, and day strings into a date, then join product categories into a navigation path.
# 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:
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.
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:
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.
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:
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".
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:
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) -> boolto check whether a card ID follows the issuing rules.
Rules:
- The ID must contain exactly 10 characters.
- It must begin with
"VIP-". - Return
Truewhen both conditions hold, andFalseotherwise.
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:
- The helper function
calculate_subtotal(unit_price, quantity)returnsunit_price * quantity. - The main function
calculate_order_payment(unit_price, quantity, coupon_rate, max_coupon, shipping_fee):- Calls
calculate_subtotalto 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.
- Calls
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) -> strto 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.
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 withid(a) == id(b).
Example: Create two separate lists with equal contents.
# 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:
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:
- Use
==to compare the values of numbers or strings.- Use
iswhen object identity matters. A common example is checking for the singletonNone, as inif 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.
promptis the message displayed to the user.input()returns the entered text as a string.
Example: Read a user's name and display a greeting.
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:
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
100produces the string"100", not the integer100. Convert numeric input withint()orfloat()before using it in a numeric calculation. For example, adding the string"100"to the number1raisesTypeError.
Example: Read an item's unit price and purchase quantity, then calculate the payment.
# 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:
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.
dirty_input = " Python_DATA_ANALYSIS_GUIDE "
# Apply strip(), then lower(), then replace()
clean_text = dirty_input.strip().lower().replace("_", " ")
print(clean_text)
Output:
python data analysis guide
The intermediate values are:
dirty_input.strip()returns"Python_DATA_ANALYSIS_GUIDE"..lower()returns"python_data_analysis_guide"..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:
- Assign
score = 90, then displayid(score). - Execute
score = score + 5. - Display
id(score)again. - Compare the two IDs. Recall string immutability from Chapter 1. Strings and numbers are immutable; this assignment binds
scoreto the object representing the new value rather than changing the original object. Use this distinction to explain the result.
Navigation: Previous: Chapter 2 - Functions