Python列表(List)介绍

Python列表(List)介绍

文章目录

  • Python列表(List)介绍
    • 基本特性
    • 代码示例
      • [1. 创建列表](#1. 创建列表)
      • [2. 访问列表元素](#2. 访问列表元素)
      • [3. 修改列表](#3. 修改列表)
      • [4. 列表操作](#4. 列表操作)
      • [5. 列表方法](#5. 列表方法)
      • [6. 列表推导式](#6. 列表推导式)
      • [7. 嵌套列表(多维列表)](#7. 嵌套列表(多维列表))
      • [8. 列表复制](#8. 列表复制)
      • [9. 列表解包](#9. 列表解包)
    • 总结
  • C++中存储多种类型的方法
    • [1. 使用 `std::any` (C++17)](#1. 使用 std::any (C++17))
    • [2. 使用 `std::variant` (C++17)](#2. 使用 std::variant (C++17))
    • [3. 使用继承和多态](#3. 使用继承和多态)
    • [4. 使用结构体和枚举](#4. 使用结构体和枚举)
    • [5. 比较各种方法的优缺点](#5. 比较各种方法的优缺点)
    • [6. 综合示例:JSON-like数据结构](#6. 综合示例:JSON-like数据结构)
    • 总结

列表(List)是Python中最常用的数据结构之一,它是一个有序、可变(可修改)的元素集合。

基本特性

  1. 有序 - 元素有固定的顺序
  2. 可变 - 可以添加、删除或修改元素
  3. 可包含任意类型 - 同一个列表中可以包含不同类型的数据
  4. 可重复 - 元素可以重复出现

代码示例

1. 创建列表

python 复制代码
# 创建空列表
empty_list = []
empty_list2 = list()

# 创建包含元素的列表
numbers = [1, 2, 3, 4, 5]
fruits = ['apple', 'banana', 'cherry']
mixed = [1, 'hello', 3.14, True]

print(f"空列表: {empty_list}")
print(f"数字列表: {numbers}")
print(f"混合类型列表: {mixed}")

2. 访问列表元素

python 复制代码
fruits = ['apple', 'banana', 'cherry', 'date', 'elderberry']

# 通过索引访问
print(fruits[0])    # 输出: apple
print(fruits[2])    # 输出: cherry

# 负数索引(从末尾开始)
print(fruits[-1])   # 输出: elderberry
print(fruits[-2])   # 输出: date

# 切片操作
print(fruits[1:3])  # 输出: ['banana', 'cherry']
print(fruits[:3])   # 输出: ['apple', 'banana', 'cherry']
print(fruits[2:])   # 输出: ['cherry', 'date', 'elderberry']
print(fruits[::2])  # 输出: ['apple', 'cherry', 'elderberry'](步长为2)

3. 修改列表

python 复制代码
colors = ['red', 'green', 'blue']

# 修改元素
colors[1] = 'yellow'
print(colors)  # 输出: ['red', 'yellow', 'blue']

# 添加元素
colors.append('purple')      # 在末尾添加
print(colors)  # 输出: ['red', 'yellow', 'blue', 'purple']

colors.insert(1, 'orange')   # 在指定位置插入
print(colors)  # 输出: ['red', 'orange', 'yellow', 'blue', 'purple']

# 删除元素
removed = colors.pop()       # 删除并返回最后一个元素
print(f"删除的元素: {removed}")
print(colors)  # 输出: ['red', 'orange', 'yellow', 'blue']

colors.remove('yellow')      # 删除指定元素
print(colors)  # 输出: ['red', 'orange', 'blue']

del colors[0]                # 删除指定索引的元素
print(colors)  # 输出: ['orange', 'blue']

4. 列表操作

python 复制代码
# 合并列表
list1 = [1, 2, 3]
list2 = [4, 5, 6]
combined = list1 + list2
print(f"合并后的列表: {combined}")  # 输出: [1, 2, 3, 4, 5, 6]

# 重复列表
repeated = list1 * 3
print(f"重复3次: {repeated}")  # 输出: [1, 2, 3, 1, 2, 3, 1, 2, 3]

# 检查元素是否存在
if 3 in list1:
    print("3在列表中")
    
# 获取列表长度
print(f"list1长度: {len(list1)}")  # 输出: 3

5. 列表方法

python 复制代码
numbers = [5, 2, 8, 1, 9, 3]

# 排序
numbers.sort()  # 升序排序
print(f"升序排序: {numbers}")  # 输出: [1, 2, 3, 5, 8, 9]

numbers.sort(reverse=True)  # 降序排序
print(f"降序排序: {numbers}")  # 输出: [9, 8, 5, 3, 2, 1]

# 反转
numbers.reverse()
print(f"反转: {numbers}")  # 输出: [1, 2, 3, 5, 8, 9]

# 查找元素索引
index = numbers.index(5)
print(f"元素5的索引: {index}")  # 输出: 3

# 统计元素出现次数
count_list = [1, 2, 2, 3, 2, 4]
count = count_list.count(2)
print(f"2出现的次数: {count}")  # 输出: 3

# 清空列表
count_list.clear()
print(f"清空后: {count_list}")  # 输出: []

6. 列表推导式

python 复制代码
# 创建平方数列表
squares = [x**2 for x in range(1, 6)]
print(f"平方数列表: {squares}")  # 输出: [1, 4, 9, 16, 25]

# 筛选偶数
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even_numbers = [x for x in numbers if x % 2 == 0]
print(f"偶数列表: {even_numbers}")  # 输出: [2, 4, 6, 8, 10]

# 转换元素类型
str_numbers = [str(x) for x in numbers]
print(f"字符串列表: {str_numbers}")  # 输出: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']

7. 嵌套列表(多维列表)

python 复制代码
# 创建二维列表(矩阵)
matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]

print(f"矩阵: {matrix}")
print(f"第二行: {matrix[1]}")        # 输出: [4, 5, 6]
print(f"第二行第三列: {matrix[1][2]}")  # 输出: 6

# 遍历二维列表
print("遍历矩阵:")
for row in matrix:
    for element in row:
        print(element, end=' ')
    print()

8. 列表复制

python 复制代码
original = [1, 2, 3, [4, 5]]

# 浅复制
shallow_copy = original.copy()
shallow_copy2 = original[:]  # 另一种浅复制方式

# 深复制(需要导入copy模块)
import copy
deep_copy = copy.deepcopy(original)

# 修改原始列表中的嵌套列表
original[3][0] = 99

print(f"原始列表: {original}")          # 输出: [1, 2, 3, [99, 5]]
print(f"浅复制: {shallow_copy}")        # 输出: [1, 2, 3, [99, 5]](受影响)
print(f"深复制: {deep_copy}")           # 输出: [1, 2, 3, [4, 5]](不受影响)

9. 列表解包

python 复制代码
# 基本解包
a, b, c = [1, 2, 3]
print(f"a={a}, b={b}, c={c}")  # 输出: a=1, b=2, c=3

# 扩展解包
first, *middle, last = [1, 2, 3, 4, 5]
print(f"first={first}, middle={middle}, last={last}")  # 输出: first=1, middle=[2, 3, 4], last=5

总结

Python列表是一个功能强大且灵活的数据结构,常用于:

  • 存储有序的数据集合
  • 需要频繁修改的数据
  • 实现栈、队列等数据结构
  • 分组和聚合数据

列表在Python编程中无处不在,掌握好列表的使用是Python编程的基础。

C++中存储多种类型的方法

你说得完全正确!C++是静态类型语言,但现代C++提供了多种方式来处理需要在同一容器中存储不同类型数据的需求。以下是几种主要方法:

1. 使用 std::any (C++17)

std::any 可以存储任意类型的值,类似于Python的动态类型。

cpp 复制代码
#include <iostream>
#include <vector>
#include <any>
#include <string>
#include <typeinfo>

int main() {
    std::vector<std::any> mixed_data;
    
    // 存储不同类型的数据
    mixed_data.push_back(42);               // int
    mixed_data.push_back(3.14159);          // double
    mixed_data.push_back(std::string("Hello")); // std::string
    mixed_data.push_back("C-string");       // const char*
    mixed_data.push_back(true);             // bool
    
    // 访问数据
    for (const auto& item : mixed_data) {
        if (item.type() == typeid(int)) {
            std::cout << "整数: " << std::any_cast<int>(item) << std::endl;
        } else if (item.type() == typeid(double)) {
            std::cout << "浮点数: " << std::any_cast<double>(item) << std::endl;
        } else if (item.type() == typeid(std::string)) {
            std::cout << "字符串: " << std::any_cast<std::string>(item) << std::endl;
        } else if (item.type() == typeid(const char*)) {
            std::cout << "C字符串: " << std::any_cast<const char*>(item) << std::endl;
        } else if (item.type() == typeid(bool)) {
            std::cout << "布尔值: " << std::boolalpha 
                      << std::any_cast<bool>(item) << std::endl;
        }
    }
    
    // 使用try-catch避免异常
    std::cout << "\n安全访问示例:" << std::endl;
    for (const auto& item : mixed_data) {
        try {
            // 尝试作为int访问
            int value = std::any_cast<int>(item);
            std::cout << "作为int: " << value << std::endl;
        } catch (const std::bad_any_cast&) {
            // 不是int类型
            std::cout << "不是int类型" << std::endl;
        }
    }
    
    return 0;
}

2. 使用 std::variant (C++17)

std::variant 是一种类型安全的联合体,可以存储一组预定义类型中的一种。

cpp 复制代码
#include <iostream>
#include <vector>
#include <variant>
#include <string>
#include <optional>

// 定义variant类型
using VariantType = std::variant<int, double, std::string, bool>;

int main() {
    std::vector<VariantType> mixed_data;
    
    // 添加数据
    mixed_data.push_back(42);              // int
    mixed_data.push_back(3.14159);         // double
    mixed_data.push_back("Hello World");   // const char* 转换为 std::string
    mixed_data.push_back(true);            // bool
    
    // 使用std::visit访问
    auto print_visitor = [](const auto& value) {
        using T = std::decay_t<decltype(value)>;
        if constexpr (std::is_same_v<T, int>) {
            std::cout << "整数: " << value << std::endl;
        } else if constexpr (std::is_same_v<T, double>) {
            std::cout << "浮点数: " << value << std::endl;
        } else if constexpr (std::is_same_v<T, std::string>) {
            std::cout << "字符串: " << value << std::endl;
        } else if constexpr (std::is_same_v<T, bool>) {
            std::cout << "布尔值: " << std::boolalpha << value << std::endl;
        }
    };
    
    std::cout << "使用std::visit:" << std::endl;
    for (const auto& item : mixed_data) {
        std::visit(print_visitor, item);
    }
    
    // 使用index()和get()访问
    std::cout << "\n使用index()和get():" << std::endl;
    for (const auto& item : mixed_data) {
        switch (item.index()) {
            case 0: // int
                std::cout << "整数: " << std::get<0>(item) << std::endl;
                break;
            case 1: // double
                std::cout << "浮点数: " << std::get<1>(item) << std::endl;
                break;
            case 2: // std::string
                std::cout << "字符串: " << std::get<2>(item) << std::endl;
                break;
            case 3: // bool
                std::cout << "布尔值: " << std::boolalpha 
                          << std::get<3>(item) << std::endl;
                break;
        }
    }
    
    // 使用std::get_if安全访问
    std::cout << "\n使用std::get_if安全访问:" << std::endl;
    for (const auto& item : mixed_data) {
        if (auto int_ptr = std::get_if<int>(&item)) {
            std::cout << "整数: " << *int_ptr << std::endl;
        } else if (auto double_ptr = std::get_if<double>(&item)) {
            std::cout << "浮点数: " << *double_ptr << std::endl;
        } else if (auto str_ptr = std::get_if<std::string>(&item)) {
            std::cout << "字符串: " << *str_ptr << std::endl;
        } else if (auto bool_ptr = std::get_if<bool>(&item)) {
            std::cout << "布尔值: " << std::boolalpha << *bool_ptr << std::endl;
        }
    }
    
    return 0;
}

3. 使用继承和多态

这是面向对象的经典方法,通过基类指针存储派生类对象。

cpp 复制代码
#include <iostream>
#include <vector>
#include <memory>
#include <string>
#include <typeinfo>

// 基类
class DataItem {
public:
    virtual ~DataItem() = default;
    virtual void print() const = 0;
    virtual std::string typeName() const = 0;
    virtual std::unique_ptr<DataItem> clone() const = 0;
};

// 模板派生类
template<typename T>
class TypedDataItem : public DataItem {
    T value_;
    
public:
    explicit TypedDataItem(const T& value) : value_(value) {}
    
    void print() const override {
        std::cout << value_;
    }
    
    std::string typeName() const override {
        return typeid(T).name();
    }
    
    std::unique_ptr<DataItem> clone() const override {
        return std::make_unique<TypedDataItem<T>>(value_);
    }
    
    const T& get() const { return value_; }
    T& get() { return value_; }
};

// 特化模板以提供更好的类型名
template<>
std::string TypedDataItem<int>::typeName() const { return "int"; }

template<>
std::string TypedDataItem<double>::typeName() const { return "double"; }

template<>
std::string TypedDataItem<std::string>::typeName() const { return "string"; }

template<>
std::string TypedDataItem<bool>::typeName() const { return "bool"; }

template<>
void TypedDataItem<bool>::print() const {
    std::cout << std::boolalpha << value_;
}

int main() {
    std::vector<std::unique_ptr<DataItem>> data_list;
    
    // 添加不同类型的数据
    data_list.push_back(std::make_unique<TypedDataItem<int>>(42));
    data_list.push_back(std::make_unique<TypedDataItem<double>>(3.14159));
    data_list.push_back(std::make_unique<TypedDataItem<std::string>>("Hello"));
    data_list.push_back(std::make_unique<TypedDataItem<bool>>(true));
    
    // 遍历和访问
    std::cout << "使用多态:" << std::endl;
    for (const auto& item : data_list) {
        std::cout << "类型: " << item->typeName() << ", 值: ";
        item->print();
        std::cout << std::endl;
    }
    
    // 动态类型转换
    std::cout << "\n动态类型转换:" << std::endl;
    for (const auto& item : data_list) {
        if (auto int_item = dynamic_cast<TypedDataItem<int>*>(item.get())) {
            std::cout << "找到整数: " << int_item->get() << std::endl;
        } else if (auto double_item = dynamic_cast<TypedDataItem<double>*>(item.get())) {
            std::cout << "找到浮点数: " << double_item->get() << std::endl;
        }
        // 可以继续添加其他类型的检查
    }
    
    return 0;
}

4. 使用结构体和枚举

对于简单的场景,可以使用枚举和联合体(或std::variant)结合。

cpp 复制代码
#include <iostream>
#include <vector>
#include <string>
#include <variant>

// 方法1:枚举 + variant
struct Data {
    enum class Type { INT, DOUBLE, STRING, BOOL };
    Type type;
    std::variant<int, double, std::string, bool> value;
    
    Data(int v) : type(Type::INT), value(v) {}
    Data(double v) : type(Type::DOUBLE), value(v) {}
    Data(const std::string& v) : type(Type::STRING), value(v) {}
    Data(const char* v) : type(Type::STRING), value(std::string(v)) {}
    Data(bool v) : type(Type::BOOL), value(v) {}
    
    void print() const {
        switch (type) {
            case Type::INT:
                std::cout << std::get<int>(value);
                break;
            case Type::DOUBLE:
                std::cout << std::get<double>(value);
                break;
            case Type::STRING:
                std::cout << std::get<std::string>(value);
                break;
            case Type::BOOL:
                std::cout << std::boolalpha << std::get<bool>(value);
                break;
        }
    }
    
    std::string typeName() const {
        switch (type) {
            case Type::INT: return "int";
            case Type::DOUBLE: return "double";
            case Type::STRING: return "string";
            case Type::BOOL: return "bool";
            default: return "unknown";
        }
    }
};

// 方法2:使用可区分联合
struct DiscriminatedUnion {
    enum { INT, DOUBLE, STRING, BOOL } tag;
    union {
        int int_value;
        double double_value;
        char* string_value;  // 注意:需要手动管理内存
        bool bool_value;
    };
    
    // 构造函数
    DiscriminatedUnion(int v) : tag(INT), int_value(v) {}
    DiscriminatedUnion(double v) : tag(DOUBLE), double_value(v) {}
    DiscriminatedUnion(const char* v) : tag(STRING) {
        string_value = new char[strlen(v) + 1];
        strcpy(string_value, v);
    }
    DiscriminatedUnion(bool v) : tag(BOOL), bool_value(v) {}
    
    // 需要手动管理拷贝和析构
    ~DiscriminatedUnion() {
        if (tag == STRING) {
            delete[] string_value;
        }
    }
};

int main() {
    std::vector<Data> data_list;
    
    data_list.emplace_back(42);
    data_list.emplace_back(3.14159);
    data_list.emplace_back("Hello World");
    data_list.emplace_back(true);
    
    std::cout << "使用结构体:" << std::endl;
    for (const auto& data : data_list) {
        std::cout << "类型: " << data.typeName() << ", 值: ";
        data.print();
        std::cout << std::endl;
    }
    
    return 0;
}

5. 比较各种方法的优缺点

方法 优点 缺点 适用场景
std::any 1. 可存储任意类型 2. 类型安全 3. 无需预定义类型集合 1. 性能开销较大 2. 需要运行时类型检查 3. 类型信息可能丢失 需要最大灵活性的场景,类型不确定
std::variant 1. 类型安全 2. 编译时类型检查 3. 性能较好 4. 无需动态内存分配 1. 需要预知所有可能类型 2. 类型集合固定 类型集合已知且有限的场景
继承多态 1. 面向对象设计 2. 支持运行时多态 3. 可扩展性强 1. 动态内存分配开销 2. 虚函数调用开销 3. 需要继承层次 需要复杂行为多态的场景
结构体枚举 1. 简单直接 2. 性能最好 1. 手动类型检查 2. 容易出错 3. 维护困难 简单场景,性能敏感

6. 综合示例:JSON-like数据结构

cpp 复制代码
#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <variant>
#include <memory>

class JsonValue {
public:
    using Object = std::map<std::string, JsonValue>;
    using Array = std::vector<JsonValue>;
    
private:
    using Value = std::variant<
        std::nullptr_t,      // null
        bool,                // boolean
        int,                 // integer
        double,              // number
        std::string,         // string
        Array,               // array
        std::shared_ptr<Object> // object
    >;
    
    Value value_;
    
public:
    // 各种构造函数
    JsonValue() : value_(nullptr) {}
    JsonValue(bool b) : value_(b) {}
    JsonValue(int i) : value_(i) {}
    JsonValue(double d) : value_(d) {}
    JsonValue(const char* s) : value_(std::string(s)) {}
    JsonValue(const std::string& s) : value_(s) {}
    JsonValue(const Array& arr) : value_(arr) {}
    JsonValue(const Object& obj) : value_(std::make_shared<Object>(obj)) {}
    
    // 类型检查
    bool isNull() const { return std::holds_alternative<std::nullptr_t>(value_); }
    bool isBool() const { return std::holds_alternative<bool>(value_); }
    bool isInt() const { return std::holds_alternative<int>(value_); }
    bool isDouble() const { return std::holds_alternative<double>(value_); }
    bool isNumber() const { return isInt() || isDouble(); }
    bool isString() const { return std::holds_alternative<std::string>(value_); }
    bool isArray() const { return std::holds_alternative<Array>(value_); }
    bool isObject() const { return std::holds_alternative<std::shared_ptr<Object>>(value_); }
    
    // 获取值(不安全,需先检查类型)
    bool asBool() const { return std::get<bool>(value_); }
    int asInt() const { return std::get<int>(value_); }
    double asDouble() const {
        if (isInt()) return static_cast<double>(asInt());
        return std::get<double>(value_);
    }
    std::string asString() const { return std::get<std::string>(value_); }
    Array& asArray() { return std::get<Array>(value_); }
    const Array& asArray() const { return std::get<Array>(value_); }
    Object& asObject() { return *std::get<std::shared_ptr<Object>>(value_); }
    const Object& asObject() const { return *std::get<std::shared_ptr<Object>>(value_); }
    
    // 安全获取值
    template<typename T>
    std::optional<T> get() const {
        if (auto ptr = std::get_if<T>(&value_)) {
            return *ptr;
        }
        return std::nullopt;
    }
    
    // 打印
    void print(int indent = 0) const {
        std::string indent_str(indent, ' ');
        
        if (isNull()) {
            std::cout << "null";
        } else if (isBool()) {
            std::cout << std::boolalpha << asBool();
        } else if (isInt()) {
            std::cout << asInt();
        } else if (isDouble()) {
            std::cout << asDouble();
        } else if (isString()) {
            std::cout << '"' << asString() << '"';
        } else if (isArray()) {
            std::cout << "[\n";
            const auto& arr = asArray();
            for (size_t i = 0; i < arr.size(); ++i) {
                std::cout << indent_str << "  ";
                arr[i].print(indent + 2);
                if (i != arr.size() - 1) std::cout << ",";
                std::cout << "\n";
            }
            std::cout << indent_str << "]";
        } else if (isObject()) {
            std::cout << "{\n";
            const auto& obj = asObject();
            size_t i = 0;
            for (const auto& [key, val] : obj) {
                std::cout << indent_str << "  \"" << key << "\": ";
                val.print(indent + 2);
                if (++i != obj.size()) std::cout << ",";
                std::cout << "\n";
            }
            std::cout << indent_str << "}";
        }
    }
};

int main() {
    // 创建复杂的JSON-like结构
    JsonValue obj = JsonValue::Object{
        {"name", "John"},
        {"age", 30},
        {"isStudent", false},
        {"grades", JsonValue::Array{85, 92, 78}},
        {"address", JsonValue::Object{
            {"street", "123 Main St"},
            {"city", "New York"}
        }},
        {"nullValue", JsonValue()}
    };
    
    std::cout << "JSON-like结构:\n";
    obj.print();
    std::cout << std::endl;
    
    return 0;
}

总结

现代C++提供了多种方式来处理异构数据集合:

  1. std::any:最灵活,适合需要最大动态性的场景
  2. std::variant:类型安全且高效,适合已知类型集合的场景
  3. 继承多态:适合需要复杂行为多态和扩展性的场景
  4. 结构体+枚举:适合简单场景或性能敏感的场景

选择哪种方法取决于具体需求:

  • 如果需要完全动态类型(类似Python),用std::any
  • 如果类型集合已知且有限,用std::variant
  • 如果需要复杂的行为多态,用继承
  • 如果追求极致性能且类型简单,用结构体

现代C++(C++17/20)的这些特性使得处理异构数据变得更加安全和方便,虽然语法比Python复杂,但提供了更好的类型安全和性能保证。

相关推荐
独行soc1 小时前
2025年渗透测试面试题总结-273(题目+回答)
网络·python·安全·web安全·网络安全·渗透测试·安全狮
独行soc1 小时前
2025年渗透测试面试题总结-274(题目+回答)
网络·python·安全·web安全·网络安全·渗透测试·安全狮
Byron Loong1 小时前
【Debug】vscode 调试python,如何配置固定调试文件
ide·vscode·python
cicada151 小时前
如何在Windows系统下使用Linux环境?
linux·运维·windows
qq_356196951 小时前
day31函数专题2:装饰器@浙大疏锦行
python
电子_咸鱼1 小时前
【QT SDK 下载安装步骤详解 + QT Creator 导航栏使用教程】
服务器·开发语言·网络·windows·vscode·qt·visual studio code
爱学习的梵高先生1 小时前
Python:变量
python
齐齐大魔王2 小时前
python爬虫学习进程(四)
爬虫·python·学习
永远都不秃头的程序员(互关)2 小时前
昇腾CANN算子开发实践:从入门到性能优化
人工智能·python·机器学习