引言:为什么SW技能在当今职场至关重要

在数字化转型的时代浪潮中,软件(Software)技能已成为职场竞争力的核心要素。无论您是刚毕业的学生、转行者还是希望提升现有职业技能的职场人士,系统学习SW技能都能为您打开新的职业大门。本课程设计遵循”从零基础到精通”的渐进式学习路径,通过实战项目驱动教学,确保学员不仅能掌握理论知识,更能将所学应用到实际工作中。

学习SW技能的职场价值

根据2023年LinkedIn职场报告,具备编程技能的专业人士平均薪资比不具备者高出35%,且就业机会多出2.5倍。特别是在人工智能、大数据、云计算等领域,SW技能几乎是必备门槛。更重要的是,编程思维能提升解决复杂问题的能力,这种能力在任何岗位都极具价值。

第一阶段:零基础入门(第1-4周)

1.1 计算机基础知识储备

在正式开始编程前,我们需要建立必要的计算机科学基础。这包括:

  • 计算机工作原理:了解CPU、内存、硬盘的基本功能
  • 操作系统基础:文件管理、命令行操作(Windows/Linux)
  • 网络基础:IP地址、DNS、HTTP协议简介

实践任务:安装Python开发环境,使用命令行创建文件夹和文件,配置网络代理(如有需要)。

1.2 Python编程基础语法

Python是当前最适合初学者的编程语言。我们将从最基础的语法开始:

# 1. 变量与数据类型
name = "张三"  # 字符串
age = 25      # 整数
height = 1.75 # 浮点数
is_student = True  # 布尔值

# 2. 基本运算
salary = 8000
bonus = 2000
total = salary + bonus  # 10000
average = total / 2     # 5000.0

# 3. 控制结构
# if-else 条件判断
if total > 5000:
    print("恭喜!您本月收入超过5000元")
elif total > 3000:
    print("收入中等")
else:
    print("收入较低")

# 4. 循环结构
for i in range(5):  # 0到4
    print(f"这是第{i+1}次循环")

# 5. 函数定义
def calculate_tax(income):
    """计算个人所得税"""
    if income <= 5000:
        return 0
    elif income <= 8000:
        return (income - 5000) * 0.1
    else:
        return (income - 5000) * 0.2 + (income - 8000) * 0.1

# 使用函数
tax = calculate_tax(10000)
print(f"应缴税款:{tax}元")

学习要点

  • 理解变量的命名规则和赋值
  • 掌握基本数据类型及其运算
  • 熟练使用if-else和for/while循环
  • 理解函数的定义和调用方式

1.3 数据结构入门

掌握基本数据结构是编程的核心能力:

# 1. 列表(List)- 可变序列
employees = ["张三", "李四", "王五"]
employees.append("赵六")  # 添加元素
employees.remove("李四")  # 删除元素
print(employees[0])      # 访问第一个元素

# 2. 字典(Dictionary)- 键值对
employee_info = {
    "name": "张三",
    "age": 25,
    "department": "技术部",
    "salary": 8000
}
employee_info["position"] = "工程师"  # 添加新键值对
print(employee_info["salary"])        # 访问值

# 3. 集合(Set)- 无序不重复元素
departments = {"技术部", "市场部", "人事部"}
departments.add("财务部")
departments.add("技术部")  # 重复添加无效
print(departments)

# 4. 元组(Tuple)- 不可变序列
coordinates = (100, 200)
print(coordinates[0])  # 访问元素
# coordinates[0] = 150  # 这行会报错,元组不可修改

实战练习:创建一个员工信息管理系统,使用字典存储单个员工信息,使用列表存储多个员工信息。

第二阶段:进阶技能(第5-8周)

2.1 面向对象编程(OOP)

OOP是现代软件开发的核心范式,能帮助我们构建更复杂的系统:

class Employee:
    """员工类"""
    
    # 类属性
    company_name = "ABC科技有限公司"
    
    def __init__(self, name, age, department, salary):
        """构造函数"""
        self.name = name
        self.age = age
        self.department = department
        self.salary = salary
    
    def calculate_bonus(self, rate=0.1):
        """计算奖金"""
        return self.salary * rate
    
    def promote(self, new_salary):
        """晋升"""
        self.salary = new_salary
        print(f"{self.name}晋升了,新薪资:{self.salary}")
    
    def __str__(self):
        """字符串表示"""
        return f"{self.name} - {self.department} - ¥{self.salary}"

# 创建对象
emp1 = Employee("张三", 25, "技术部", 8000)
emp2 = Employee("李四", 28, "市场部", 9000)

# 使用对象方法
print(emp1.calculate_bonus())  # 800.0
emp2.promote(12000)            # 李四晋升了,新薪资:12000
print(emp1)                    # 张三 - 技术部 - ¥8000

# 继承示例
class Manager(Employee):
    """经理类,继承自Employee"""
    
    def __init__(self, name, age, department, salary, team_size):
        super().__init__(name, age, department, salary)
        self.team_size = team_size
    
    def calculate_bonus(self, rate=0.15):
        """经理奖金更高"""
        base_bonus = super().calculate_bonus(rate)
        return base_bonus + 500  # 额外津贴
    
    def __str__(self):
        return f"{super().__str__()} - 团队规模:{self.team_size}"

# 使用继承
manager = Manager("王五", 35, "技术部", 15000, 10)
print(manager.calculate_bonus())  # 2750.0
print(manager)                    # 王五 - 技术部 - ¥15000 - 团队规模:10

核心概念

  • 封装:将数据和操作封装在类中
  • 继承:子类继承父类的属性和方法
  • 多态:不同对象对同一方法的不同实现

2.2 文件操作与异常处理

实际应用中,数据持久化和错误处理至关重要:

import json

# 1. 文件读写
def save_employee_data(employees, filename="employees.json"):
    """保存员工数据到文件"""
    try:
        with open(filename, 'w', encoding='utf-8') as f:
            json.dump(employees, f, ensure_ascii=False, indent=2)
        print(f"数据保存成功:{filename}")
    except IOError as e:
        print(f"文件操作失败:{e}")
    except Exception as e:
        print(f"未知错误:{e}")

def load_employee_data(filename="employees.json"):
    """从文件加载员工数据"""
    try:
        with open(filename, 'r', encoding='utf-8') as f:
            return json.load(f)
    except FileNotFoundError:
        print(f"文件不存在:{filename}")
        return []
    except json.JSONDecodeError:
        print("文件内容格式错误")
        return []

# 2. 异常处理实战
def process_salary_data(raw_data):
    """处理薪资数据,演示异常处理"""
    results = []
    for item in raw_data:
        try:
            # 尝试转换为数字
            salary = float(item)
            if salary < 0:
                raise ValueError("薪资不能为负数")
            results.append(salary)
        except ValueError as e:
            print(f"处理失败:{item} - {e}")
            continue
    return results

# 使用示例
employee_list = [
    {"name": "张三", "salary": 8000},
    {"name": "李四", "salary": 9000},
    {"name": "王五", "salary": 10000}
]

# 保存数据
save_employee_data(employee_list)

# 加载数据
loaded_data = load_employee_data()
print("加载的数据:", loaded_data)

# 处理异常数据
raw_salaries = ["7000", "8000", "invalid", "9000", "-100"]
processed = process_salary_data(raw_salaries)
print("处理后的薪资:", processed)  # [7000.0, 8000.0, 9000.0]

2.3 模块与包管理

# 1. 创建自定义模块
# 文件:employee_utils.py
"""
员工工具模块
提供员工信息处理的实用函数
"""

def format_salary(salary, currency="CNY"):
    """格式化薪资显示"""
    symbols = {"CNY": "¥", "USD": "$", "EUR": "€"}
    symbol = symbols.get(currency, "¥")
    return f"{symbol}{salary:,.2f}"

def calculate_age_group(age):
    """计算年龄分组"""
    if age < 25:
        return "青年"
    elif age < 35:
        return "中年"
    else:
        return "资深"

# 2. 使用第三方包
# 安装命令:pip install requests pandas openpyxl

import requests
import pandas as pd

def fetch_employee_from_api(url):
    """从API获取员工数据"""
    try:
        response = requests.get(url, timeout=10)
        response.raise_for_status()  # 检查HTTP错误
        return response.json()
    except requests.RequestException as e:
        print(f"API请求失败:{e}")
        return None

def analyze_salary_data(df):
    """使用Pandas分析薪资数据"""
    # 计算统计信息
    stats = {
        "平均薪资": df['salary'].mean(),
        "最高薪资": df['salary'].max(),
        "最低薪资": df['salary'].min(),
        "薪资中位数": df['salary'].median()
    }
    return stats

# 使用示例
from employee_utils import format_salary, calculate_age_group

print(format_salary(8000))  # ¥8,000.00
print(calculate_age_group(28))  # 中年

# Pandas数据分析示例
data = {
    'name': ['张三', '李四', '王五', '赵六'],
    'salary': [8000, 9000, 12000, 7500],
    'department': ['技术部', '市场部', '技术部', '人事部']
}
df = pd.DataFrame(data)
stats = analyze_salary_data(df)
print(stats)

第三阶段:实战项目(第9-12周)

3.1 项目一:员工信息管理系统(完整版)

这是一个综合性的实战项目,整合了前面学习的所有知识点:

import json
import os
from datetime import datetime

class EmployeeSystem:
    """员工信息管理系统"""
    
    def __init__(self, data_file="employee_db.json"):
        self.data_file = data_file
        self.employees = self.load_data()
    
    def load_data(self):
        """从文件加载数据"""
        if not os.path.exists(self.data_file):
            return []
        try:
            with open(self.data_file, 'r', encoding='utf-8') as f:
                return json.load(f)
        except (json.JSONDecodeError, IOError) as e:
            print(f"加载数据失败:{e}")
            return []
    
    def save_data(self):
        """保存数据到文件"""
        try:
            with open(self.data_file, 'w', encoding='utf-8') as f:
                json.dump(self.employees, f, ensure_ascii=False, indent=2)
            return True
        except IOError as e:
            print(f"保存数据失败:{e}")
            return False
    
    def add_employee(self, name, age, department, salary, position):
        """添加员工"""
        # 数据验证
        if not name or not department:
            print("错误:姓名和部门不能为空")
            return False
        
        try:
            age = int(age)
            salary = float(salary)
            if age < 18 or age > 70:
                print("错误:年龄必须在18-70岁之间")
                return False
            if salary < 0:
                print("错误:薪资不能为负数")
                return False
        except ValueError:
            print("错误:年龄和薪资必须是数字")
            return False
        
        employee = {
            "id": len(self.employees) + 1,
            "name": name,
            "age": age,
            "department": department,
            "salary": salary,
            "position": position,
            "created_at": datetime.now().isoformat()
        }
        
        self.employees.append(employee)
        if self.save_data():
            print(f"员工{name}添加成功")
            return True
        return False
    
    def find_employee(self, name=None, department=None):
        """查找员工"""
        results = self.employees
        
        if name:
            results = [e for e in results if name.lower() in e['name'].lower()]
        
        if department:
            results = [e for e in results if department.lower() in e['department'].lower()]
        
        return results
    
    def update_salary(self, employee_id, new_salary):
        """更新薪资"""
        try:
            new_salary = float(new_salary)
            if new_salary < 0:
                print("错误:薪资不能为负数")
                return False
        except ValueError:
            print("错误:薪资必须是数字")
            return False
        
        for emp in self.employees:
            if emp['id'] == employee_id:
                old_salary = emp['salary']
                emp['salary'] = new_salary
                if self.save_data():
                    print(f"员工{emp['name']}薪资已更新:{old_salary} → {new_salary}")
                    return True
        print(f"未找到ID为{employee_id}的员工")
        return False
    
    def delete_employee(self, employee_id):
        """删除员工"""
        for i, emp in enumerate(self.employees):
            if emp['id'] == employee_id:
                name = emp['name']
                del self.employees[i]
                if self.save_data():
                    print(f"员工{name}已删除")
                    return True
        print(f"未找到ID为{employee_id}的员工")
        return False
    
    def generate_report(self):
        """生成统计报告"""
        if not self.employees:
            print("暂无员工数据")
            return
        
        total_employees = len(self.employees)
        total_salary = sum(e['salary'] for e in self.employees)
        avg_salary = total_salary / total_employees
        
        # 按部门统计
        dept_stats = {}
        for emp in self.employees:
            dept = emp['department']
            if dept not in dept_stats:
                dept_stats[dept] = {'count': 0, 'total_salary': 0}
            dept_stats[dept]['count'] += 1
            dept_stats[dept]['total_salary'] += emp['salary']
        
        print("\n" + "="*50)
        print("员工信息统计报告")
        print("="*50)
        print(f"总员工数:{total_employees}")
        print(f"总薪资支出:¥{total_salary:,.2f}")
        print(f"平均薪资:¥{avg_salary:,.2f}")
        print("\n部门统计:")
        for dept, stats in dept_stats.items():
            dept_avg = stats['total_salary'] / stats['count']
            print(f"  {dept}:{stats['count']}人,平均薪资¥{dept_avg:,.2f}")
        print("="*50)
    
    def show_menu(self):
        """显示主菜单"""
        print("\n" + "="*40)
        print("员工信息管理系统")
        print("="*40)
        print("1. 添加员工")
        print("2. 查找员工")
        print("3. 更新薪资")
        print("4. 删除员工")
        print("5. 显示所有员工")
        print("6. 生成统计报告")
        print("0. 退出系统")
        print("="*40)
    
    def display_all(self):
        """显示所有员工"""
        if not self.employees:
            print("暂无员工数据")
            return
        
        print("\n员工列表:")
        print("-" * 80)
        print(f"{'ID':<4} {'姓名':<8} {'年龄':<4} {'部门':<10} {'职位':<10} {'薪资':<10}")
        print("-" * 80)
        for emp in self.employees:
            print(f"{emp['id']:<4} {emp['name']:<8} {emp['age']:<4} {emp['department']:<10} {emp['position']:<10} ¥{emp['salary']:<9}")
        print("-" * 80)

# 主程序
def main():
    system = EmployeeSystem()
    
    while True:
        system.show_menu()
        choice = input("请选择操作(0-6):").strip()
        
        if choice == '1':
            print("\n--- 添加员工 ---")
            name = input("姓名:")
            age = input("年龄:")
            department = input("部门:")
            salary = input("薪资:")
            position = input("职位:")
            system.add_employee(name, age, department, salary, position)
        
        elif choice == '2':
            print("\n--- 查找员工 ---")
            name = input("姓名(可空):") or None
            department = input("部门(可空):") or None
            results = system.find_employee(name, department)
            if results:
                print("\n查找结果:")
                for emp in results:
                    print(f"  {emp['name']} - {emp['department']} - ¥{emp['salary']}")
            else:
                print("未找到匹配的员工")
        
        elif choice == '3':
            print("\n--- 更新薪资 ---")
            emp_id = int(input("员工ID:"))
            new_salary = input("新薪资:")
            system.update_salary(emp_id, new_salary)
        
        elif choice == '4':
            print("\n--- 删除员工 ---")
            emp_id = int(input("员工ID:"))
            system.delete_employee(emp_id)
        
        elif choice == '5':
            system.display_all()
        
        elif choice == '6':
            system.generate_report()
        
        elif choice == '0':
            print("感谢使用,再见!")
            break
        
        else:
            print("无效选择,请重新输入")

if __name__ == "__main__":
    main()

项目要点

  • 完整的CRUD(增删改查)功能
  • 数据持久化到JSON文件
  • 输入验证和异常处理
  • 用户友好的交互界面
  • 统计报告功能

3.2 项目二:数据分析与可视化

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

# 设置中文字体(根据系统调整)
plt.rcParams['font.sans-serif'] = ['SimHei', 'Arial Unicode MS', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False

class SalaryAnalyzer:
    """薪资分析器"""
    
    def __init__(self, data_file="employee_db.json"):
        self.data_file = data_file
        self.df = self.load_and_preprocess()
    
    def load_and_preprocess(self):
        """加载并预处理数据"""
        try:
            with open(self.data_file, 'r', encoding='utf-8') as f:
                data = json.load(f)
            
            if not data:
                print("没有数据可分析")
                return None
            
            df = pd.DataFrame(data)
            
            # 数据清洗
            df['created_at'] = pd.to_datetime(df['created_at'])
            df['age_group'] = df['age'].apply(self.get_age_group)
            
            return df
        except Exception as e:
            print(f"数据加载失败:{e}")
            return None
    
    def get_age_group(self, age):
        """获取年龄分组"""
        if age < 25:
            return '青年(<25)'
        elif age < 35:
            return '中年(25-34)'
        elif age < 45:
            return '资深(35-44)'
        else:
            return '专家(45+)'
    
    def basic_statistics(self):
        """基础统计"""
        if self.df is None:
            return
        
        print("\n基础统计信息:")
        print(self.df.describe())
        
        # 按部门统计
        print("\n按部门统计:")
        dept_stats = self.df.groupby('department')['salary'].agg(['count', 'mean', 'std'])
        print(dept_stats)
    
    def plot_salary_distribution(self):
        """绘制薪资分布图"""
        if self.df is None:
            return
        
        fig, axes = plt.subplots(2, 2, figsize=(14, 10))
        
        # 1. 薪资直方图
        axes[0, 0].hist(self.df['salary'], bins=15, edgecolor='black', alpha=0.7)
        axes[0, 0].set_title('薪资分布直方图')
        axes[0, 0].set_xlabel('薪资')
        axes[0, 0].set_ylabel('人数')
        
        # 2. 部门薪资箱线图
        sns.boxplot(data=self.df, x='department', y='salary', ax=axes[0, 1])
        axes[0, 1].set_title('各部门薪资箱线图')
        axes[0, 1].tick_params(axis='x', rotation=45)
        
        # 3. 年龄与薪资散点图
        axes[1, 0].scatter(self.df['age'], self.df['salary'], alpha=0.6)
        axes[1, 0].set_title('年龄与薪资关系')
        axes[1, 0].set_xlabel('年龄')
        axes[1, 0].set_ylabel('薪资')
        
        # 4. 各部门平均薪资柱状图
        dept_avg = self.df.groupby('department')['salary'].mean()
        dept_avg.plot(kind='bar', ax=axes[1, 1], color='skyblue')
        axes[1, 1].set_title('各部门平均薪资')
        axes[1, 1].tick_params(axis='x', rotation=45)
        
        plt.tight_layout()
        plt.savefig('salary_analysis.png', dpi=300, bbox_inches='tight')
        print("\n图表已保存为:salary_analysis.png")
        plt.show()
    
    def correlation_analysis(self):
        """相关性分析"""
        if self.df is None:
            return
        
        # 计算相关系数
        correlation = self.df[['age', 'salary']].corr()
        print("\n年龄与薪资的相关系数:")
        print(correlation)
        
        # 按年龄组统计
        print("\n各年龄组平均薪资:")
        age_group_stats = self.df.groupby('age_group')['salary'].mean().sort_values(ascending=False)
        print(age_group_stats)
    
    def export_report(self, filename="salary_report.xlsx"):
        """导出分析报告到Excel"""
        if self.df is None:
            return
        
        try:
            with pd.ExcelWriter(filename, engine='openpyxl') as writer:
                # 基础数据
                self.df.to_excel(writer, sheet_name='员工数据', index=False)
                
                # 部门统计
                dept_stats = self.df.groupby('department').agg({
                    'salary': ['count', 'mean', 'min', 'max'],
                    'age': 'mean'
                })
                dept_stats.to_excel(writer, sheet_name='部门统计')
                
                # 年龄组统计
                age_stats = self.df.groupby('age_group').agg({
                    'salary': ['count', 'mean'],
                    'age': 'mean'
                })
                age_stats.to_excel(writer, sheet_name='年龄组统计')
            
            print(f"\n分析报告已导出:{filename}")
        except Exception as e:
            print(f"导出失败:{e}")

# 使用示例
if __name__ == "__main__":
    analyzer = SalaryAnalyzer()
    
    # 基础统计
    analyzer.basic_statistics()
    
    # 相关性分析
    analyzer.correlation_analysis()
    
    # 绘制图表
    analyzer.plot_salary_distribution()
    
    # 导出报告
    analyzer.export_report()

第四阶段:高级技巧与职场应用(第13-16周)

4.1 自动化办公:Excel与邮件处理

import openpyxl
from openpyxl.styles import Font, PatternFill, Alignment
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication

class OfficeAutomation:
    """办公自动化工具"""
    
    @staticmethod
    def create_salary_excel(data, filename="薪资表.xlsx"):
        """创建格式化的薪资表"""
        wb = openpyxl.Workbook()
        ws = wb.active
        ws.title = "员工薪资"
        
        # 表头
        headers = ["ID", "姓名", "部门", "职位", "薪资", "年龄", "入职日期"]
        for col, header in enumerate(headers, 1):
            cell = ws.cell(row=1, column=col, value=header)
            cell.font = Font(bold=True, size=12)
            cell.fill = PatternFill(start_color="4472C4", end_color="4472C4", fill_type="solid")
            cell.font.color = "FFFFFF"
            cell.alignment = Alignment(horizontal="center")
        
        # 数据
        for row, emp in enumerate(data, 2):
            ws.cell(row=row, column=1, value=emp['id'])
            ws.cell(row=row, column=2, value=emp['name'])
            ws.cell(row=row, column=3, value=emp['department'])
            ws.cell(row=row, column=4, value=emp['position'])
            ws.cell(row=row, column=5, value=emp['salary'])
            ws.cell(row=row, column=6, value=emp['age'])
            ws.cell(row=row, column=7, value=emp['created_at'][:10])
        
        # 设置列宽
        for col in range(1, 8):
            ws.column_dimensions[openpyxl.utils.get_column_letter(col)].width = 15
        
        # 添加公式(总计)
        ws.cell(row=len(data)+2, column=4, value="总计:")
        ws.cell(row=len(data)+2, column=5, value=f"=SUM(E2:E{len(data)+1})")
        
        wb.save(filename)
        print(f"Excel文件已创建:{filename}")
        return filename
    
    @staticmethod
    def send_email_with_attachment(to_email, subject, body, attachment_path, 
                                   smtp_server="smtp.qq.com", smtp_port=465,
                                   sender_email="your_email@qq.com", sender_password="your_password"):
        """发送带附件的邮件"""
        try:
            # 创建邮件
            msg = MIMEMultipart()
            msg['From'] = sender_email
            msg['To'] = to_email
            msg['Subject'] = subject
            
            # 邮件正文
            msg.attach(MIMEText(body, 'plain', 'utf-8'))
            
            # 添加附件
            with open(attachment_path, 'rb') as f:
                attachment = MIMEApplication(f.read())
                attachment.add_header('Content-Disposition', 'attachment', 
                                    filename=os.path.basename(attachment_path))
                msg.attach(attachment)
            
            # 发送邮件
            server = smtplib.SMTP_SSL(smtp_server, smtp_port)
            server.login(sender_email, sender_password)
            server.send_message(msg)
            server.quit()
            
            print(f"邮件已发送至:{to_email}")
            return True
            
        except Exception as e:
            print(f"邮件发送失败:{e}")
            return False
    
    @staticmethod
    def batch_process_excel_files(folder_path, output_file="汇总表.xlsx"):
        """批量处理文件夹内所有Excel文件"""
        import glob
        
        all_data = []
        files = glob.glob(os.path.join(folder_path, "*.xlsx"))
        
        for file in files:
            try:
                wb = openpyxl.load_workbook(file)
                ws = wb.active
                # 读取数据(假设第一行是标题)
                for row in ws.iter_rows(min_row=2, values_only=True):
                    if row[0] is not None:  # 跳过空行
                        all_data.append(row)
                wb.close()
                print(f"已读取:{file}")
            except Exception as e:
                print(f"读取失败 {file}:{e}")
        
        if all_data:
            # 汇总到新文件
            wb = openpyxl.Workbook()
            ws = wb.active
            for row_idx, row_data in enumerate(all_data, 1):
                for col_idx, value in enumerate(row_data, 1):
                    ws.cell(row=row_idx, column=col_idx, value=value)
            wb.save(output_file)
            print(f"汇总完成:{output_file},共{len(all_data)}行数据")
        else:
            print("没有数据可汇总")

# 使用示例
if __name__ == "__main__":
    # 模拟数据
    employees = [
        {"id": 1, "name": "张三", "department": "技术部", "position": "工程师", "salary": 8000, "age": 25, "created_at": "2024-01-15"},
        {"id": 2, "name": "李四", "department": "市场部", "position": "经理", "salary": 12000, "age": 32, "created_at": "2023-06-20"},
        {"id": 3, "name": "王五", "department": "技术部", "position": "架构师", "salary": 18000, "age": 38, "created_at": "2022-03-10"}
    ]
    
    # 创建Excel
    OfficeAutomation.create_salary_excel(employees)
    
    # 发送邮件(需要配置真实邮箱信息)
    # OfficeAutomation.send_email_with_attachment(
    #     to_email="manager@company.com",
    #     subject="员工薪资报表",
    #     body="请查收附件中的员工薪资报表。",
    #     attachment_path="薪资表.xlsx"
    # )

4.2 网络爬虫入门

import requests
from bs4 import BeautifulSoup
import time
import random

class SimpleScraper:
    """简单网络爬虫"""
    
    def __init__(self):
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
        }
    
    def fetch_page(self, url, max_retries=3):
        """获取网页内容"""
        for attempt in range(max_retries):
            try:
                response = requests.get(url, headers=self.headers, timeout=10)
                response.raise_for_status()
                response.encoding = response.apparent_encoding
                return response.text
            except requests.RequestException as e:
                print(f"请求失败(尝试{attempt+1}/{max_retries}):{e}")
                if attempt < max_retries - 1:
                    time.sleep(random.uniform(1, 3))  # 随机延迟
                else:
                    return None
    
    def parse_html(self, html, selectors):
        """解析HTML提取数据"""
        if not html:
            return []
        
        soup = BeautifulSoup(html, 'html.parser')
        results = []
        
        # 示例:提取文章标题和链接
        articles = soup.select(selectors.get('article', ''))
        for article in articles:
            title_elem = article.select_one(selectors.get('title', ''))
            link_elem = article.select_one(selectors.get('link', ''))
            
            if title_elem and link_elem:
                results.append({
                    'title': title_elem.get_text(strip=True),
                    'link': link_elem.get('href')
                })
        
        return results
    
    def scrape_job_info(self, keyword="Python"):
        """示例:爬取招聘网站信息(模拟)"""
        # 注意:实际爬取需要遵守网站robots.txt和相关法规
        # 这里仅作为演示
        
        print(f"正在搜索{keyword}相关职位...")
        
        # 模拟数据(实际使用时替换为真实URL)
        mock_html = f"""
        <html>
        <body>
            <div class="job-list">
                <div class="job-item">
                    <h3>{keyword}开发工程师</h3>
                    <span class="salary">15k-25k</span>
                    <span class="company">ABC科技</span>
                </div>
                <div class="job-item">
                    <h3>高级{keyword}工程师</h3>
                    <span class="salary">25k-40k</span>
                    <span class="company">XYZ公司</span>
                </div>
            </div>
        </body>
        </html>
        """
        
        selectors = {
            'article': '.job-item',
            'title': 'h3',
            'link': 'a'  # 这里没有链接,仅演示
        }
        
        # 实际使用时:
        # url = f"https://example.com/search?q={keyword}"
        # html = self.fetch_page(url)
        # results = self.parse_html(html, selectors)
        
        # 演示使用模拟数据
        results = self.parse_html(mock_html, selectors)
        
        # 补充模拟数据
        for i, item in enumerate(results):
            item['salary'] = ['15k-25k', '25k-40k'][i]
            item['company'] = ['ABC科技', 'XYZ公司'][i]
        
        return results
    
    def save_results(self, results, filename="jobs.json"):
        """保存结果"""
        try:
            with open(filename, 'w', encoding='utf-8') as f:
                json.dump(results, f, ensure_ascii=False, indent=2)
            print(f"结果已保存:{filename}")
        except IOError as e:
            print(f"保存失败:{e}")

# 使用示例
if __name__ == "__main__":
    scraper = SimpleScraper()
    
    # 爬取职位信息
    jobs = scraper.scrape_job_info("Python")
    
    print("\n爬取结果:")
    for job in jobs:
        print(f"职位:{job['title']}")
        print(f"公司:{job['company']}")
        print(f"薪资:{job['salary']}")
        print("-" * 40)
    
    # 保存结果
    scraper.save_results(jobs)

4.3 代码优化与最佳实践

# 1. 使用列表推导式(更简洁高效)
def get_senior_employees(employees):
    """获取资深员工(传统方式)"""
    result = []
    for emp in employees:
        if emp['age'] >= 35:
            result.append(emp)
    return result

# 优化方式
def get_senior_employees_optimized(employees):
    """获取资深员工(列表推导式)"""
    return [emp for emp in employees if emp['age'] >= 35]

# 2. 使用装饰器
def log_execution(func):
    """执行日志装饰器"""
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print(f"{func.__name__} 执行时间:{end-start:.4f}秒")
        return result
    return wrapper

@log_execution
def heavy_computation():
    """耗时操作"""
    time.sleep(1)
    return "完成"

# 3. 使用上下文管理器
class DatabaseConnection:
    """数据库连接上下文管理器"""
    def __init__(self, connection_string):
        self.connection_string = connection_string
        self.connection = None
    
    def __enter__(self):
        print(f"连接到:{self.connection_string}")
        self.connection = "模拟连接对象"
        return self.connection
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        print("关闭数据库连接")
        self.connection = None

# 使用
# with DatabaseConnection("mysql://localhost:3306/db") as conn:
#     # 执行数据库操作
#     pass

# 4. 类型提示(Python 3.5+)
from typing import List, Dict, Optional

def calculate_employee_bonus(salary: float, rate: float = 0.1) -> float:
    """计算奖金(带类型提示)"""
    return salary * rate

def find_employee_by_name(employees: List[Dict], name: str) -> Optional[Dict]:
    """查找员工(带类型提示)"""
    for emp in employees:
        if emp.get('name') == name:
            return emp
    return None

# 5. 使用生成器处理大数据
def read_large_file(filename):
    """读取大文件(生成器)"""
    with open(filename, 'r') as f:
        for line in f:
            yield line.strip()

# 使用生成器
# for line in read_large_file("big_data.txt"):
#     process_line(line)  # 逐行处理,节省内存

# 6. 使用f-string格式化
def format_employee_info(emp):
    """格式化员工信息"""
    # 旧方式
    # return "姓名:{},薪资:{}".format(emp['name'], emp['salary'])
    
    # 新方式(f-string)
    return f"姓名:{emp['name']},薪资:¥{emp['salary']:,.2f}"

# 7. 使用collections模块
from collections import defaultdict, Counter

def analyze_department_distribution(employees):
    """分析部门分布"""
    # 使用defaultdict
    dept_count = defaultdict(int)
    for emp in employees:
        dept_count[emp['department']] += 1
    
    # 使用Counter
    dept_list = [emp['department'] for emp in employees]
    dept_counter = Counter(dept_list)
    
    return dict(dept_count), dept_counter

# 8. 使用itertools
import itertools

def group_employees_by_age(employees):
    """按年龄分组"""
    sorted_employees = sorted(employees, key=lambda x: x['age'])
    
    # 使用itertools.groupby
    for age, group in itertools.groupby(sorted_employees, key=lambda x: x['age']):
        print(f"年龄{age}:{list(group)}")

# 9. 使用functools
from functools import lru_cache

@lru_cache(maxsize=128)
def fibonacci(n):
    """计算斐波那契数列(带缓存)"""
    if n < 2:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

# 10. 使用pathlib处理文件路径
from pathlib import Path

def process_files_in_directory(directory):
    """处理目录中的文件"""
    path = Path(directory)
    
    # 遍历所有txt文件
    for file_path in path.glob("*.txt"):
        print(f"处理文件:{file_path.name}")
        content = file_path.read_text(encoding='utf-8')
        # 处理内容...
        
    # 创建新文件
    new_file = path / "output" / "result.txt"
    new_file.parent.mkdir(exist_ok=True)
    new_file.write_text("处理结果", encoding='utf-8')

第五阶段:职场竞争力提升

5.1 简历与面试技巧

简历撰写要点

  1. 项目经验:使用STAR法则(情境、任务、行动、结果)

    • 示例:开发员工信息管理系统,使用Python和JSON实现数据持久化,提升管理效率50%
  2. 技能描述:具体化、量化

    • 不佳:熟悉Python
    • 优秀:熟练使用Python进行数据分析、自动化办公和Web开发,使用Pandas处理10万+数据集
  3. 技术栈展示

    • 编程语言:Python, SQL
    • 数据分析:Pandas, NumPy, Matplotlib
    • 自动化:Openpyxl, Smtplib
    • 版本控制:Git/GitHub

面试准备

  • 技术问题:准备白板编程,重点练习字符串处理、数据结构、算法
  • 项目深挖:能清晰讲解项目架构、遇到的问题及解决方案
  • 行为问题:准备”最困难的项目”、”团队冲突处理”等案例

5.2 持续学习路径

推荐学习资源

  1. 在线平台

    • Coursera:Python for Everybody(密歇根大学)
    • LeetCode:算法练习
    • Kaggle:数据科学实战
  2. 书籍

    • 《Python编程:从入门到实践》
    • 1《流畅的Python》
    • 《利用Python进行数据分析》
  3. 社区与博客

    • Stack Overflow:解决问题
    • GitHub:参与开源项目
    • Medium/Towards Data Science:跟踪前沿技术

学习建议

  • 每天至少1小时编码时间
  • 每周完成一个小项目
  • 每月学习一个新库或框架
  • 建立个人技术博客,记录学习心得

5.3 职场软技能

沟通能力

  • 学会用非技术人员能理解的方式解释技术问题
  • 编写清晰的代码注释和文档
  • 主动汇报项目进展

团队协作

  • 使用Git进行版本控制,遵循团队规范
  • 代码审查(Code Review)时保持开放态度
  • 乐于分享知识,帮助同事

问题解决能力

  • 遇到问题先分析再求助
  • 学会使用调试工具(pdb, PyCharm调试器)
  • 建立问题解决笔记,积累经验

课程总结与行动计划

学习路线图回顾

阶段 时间 核心技能 产出成果
入门 1-4周 Python基础语法、数据类型、控制结构 基础语法掌握,能编写简单脚本
进阶 5-8周 OOP、文件操作、异常处理、模块化 可维护的代码结构,错误处理能力
实战 9-12周 项目开发、数据分析、可视化 2个完整项目,作品集
高级 13-16周 自动化办公、网络爬虫、代码优化 效率工具,技术深度

行动计划(30天)

第1周:完成Python基础语法学习,每天练习2小时 第2周:掌握数据结构,完成100道基础练习题 第3周:学习OOP,重构之前的代码 第4周:完成第一个项目(员工管理系统) 第5周:学习Pandas,分析公开数据集 第6周:学习Matplotlib,制作数据图表 第7周:完成第二个项目(数据分析) 第8周:学习自动化办公,处理真实Excel文件

成功标准

  • 初级:能独立完成简单自动化任务(如批量处理Excel)
  • 中级:能开发完整应用(如Web应用、数据分析系统)
  • 高级:能优化现有系统,解决复杂问题

常见问题解答

Q1: 零基础真的能学会吗? A: 绝对可以。本课程从最基础的计算机操作开始,每一步都有详细说明和练习。关键是坚持每天练习。

Q2: 需要数学基础吗? A: 基础编程不需要高深数学。数据分析需要基础统计知识,但我们会从零开始讲解。

Q3: 学完能找到工作吗? A: 完成本课程+项目练习+简历优化,足以胜任初级Python开发、数据分析、自动化工程师等岗位。建议同时刷LeetCode和准备面试。

Q4: 工作很忙,没时间怎么办? A: 每天1小时足够。利用碎片时间(通勤、午休)学习理论,周末集中时间做项目。关键是持续性和规律性。

Q5: 如何保持学习动力? A: 1) 设定小目标并庆祝达成;2) 加入学习社群;3) 将所学应用到工作中;4) 关注薪资提升前景。


结语

SW技能不仅是技术能力,更是思维方式的升级。通过本课程的系统学习,您将获得:

  • 硬技能:Python编程、数据分析、自动化开发
  • 软技能:逻辑思维、问题解决、项目管理
  • 职场优势:更高的薪资、更多的机会、更强的竞争力

记住:最好的学习时间是昨天,其次是现在。立即开始您的编程之旅,让SW技能成为您职场腾飞的翅膀!

立即行动

  1. 安装Python和开发环境
  2. 完成第一个”Hello World”程序
  3. 加入学习社群,找到同行伙伴
  4. 制定个人学习计划

祝您学习顺利,早日成为SW技能专家!