【全栈之路】10 天掌握 Python 开发(5)函数、模块和包

函数的定义和调用

函数用于对代码逻辑的封装和隔离,在 Python 和 JavaScript 中,函数都被视作一等公民。

任务

编写一个打招呼的函数,将传入的个人信息(姓名、年龄、性别)格式化后打印。

JavaScript 实现

javascript 复制代码
function greet(name, age, gender='保密') {
  console.log(`你好,我是${name},今年${age}岁,性别${gender}`)
}

console.log(greet('张三', 18));
console.log(greet('李四', 18, '男'));
console.log(greet(...['王五', 18, '女']));

Python 实现

python 复制代码
def greet(name, age, gender='保密'):
    print(f"你好,我是{name},今年{age}岁,性别{gender}")

print(greet('张三', 18)) # 传入位置参数
print(greet(age=18,name='张三')) # 传入关键字参数
print(greet('李四', 18, '男')) 
print(greet(*['王五', 18, '女'])) 

代码解读

  • Python 使用 def 关键字定义函数,JavaScript 使用 function 关键字定义函数。
  • Python 使用冒号 : 和缩进表示函数体,JavaScript 使用花括号表示函数体。
  • Python 中,除默认值参数之外(如上面的 gender 参数),函数的每个参数都是必传的,否则会出现语法错误。而在 JavaScript 中未传递的参数默认值为 undefined
  • 在 Python 中,按照顺序传入的参数叫做 位置参数 ,必须严格按照形参定义顺序传入。此外,还可以使用 key=value 的形式向函数传入关键字参数,关键字参数的顺序不必与形参顺序保持一致,位置参数和关键字参数可以一起使用,但 必须保证调用函数时提供了所有必要参数
  • Python 中,可以使用 my_fn(*[p1, p2, ...]) 的形式传入位置参数,与 JavaScript 中的 myFn(...[p1, p2, ...]) 类似。

差异速览

特性 JavaScript Python
函数定义 function myFn(params) { ... } def my_fn(params):
函数调用 myFn(params) my_fn(params)

:::tip 如何获取函数入参? 使用 *args 获取传入的全部位置参数,类型为元组。使用 **kwargs 获取传入的全部关键字参数,类型为字典。

css 复制代码
def some_fn(position_arg, *args, **kwargs):
    print(position_arg)
    print(args)
    print(kwargs)

some_fn('position_arg_value','add_to_args1','add_to_args2',a=1,b=2,c=3)
# 运行结果
# position_arg_value
# ('add_to_args1', 'add_to_args2')
# {'a': 1, 'b': 2, 'c': 3}

类似地,Python 也可以使用 ** 展开一个字典

python 复制代码
def some_fn(a, b, c):
    print(a, b, c) # 1 2 3

my_dict = {"c": 3, "b": 2, "a": 1} # Python 对字典中键的顺序没有要求
some_fn(**my_dict)

*args**kwargs 虽然方便,但如果函数只定义了这两个形参,IDE 将失去代码提示,同时函数的逻辑也将变得难以理解,需要谨慎使用。 :::

相关资源

匿名函数

当需要一个可以在不定义单独函数的情况下内联执行的小段代码时,可以使用匿名函数,在 Python 中,匿名函数称为 "lambda 表达式" 或 "lambda 函数"。

任务

使用匿名函数,将数字列表的每一项映射为它的平方并打印新列表。

JavaScript 实现

javascript 复制代码
const numbers = [1, 2, 3, 4, 5];

const squaredNumbers = numbers.map(number => number ** 2);
console.log(squaredNumbers);

Python 实现

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

squared_numbers = list(map(lambda number: number ** 2, numbers))
print(squared_numbers)

代码解读

  • Python 使用 lambda 关键字创建匿名函数,JavaScript 使用 function=> 创建匿名函数。
  • Python 的 lambda 函数不能包含函数体,表达式的值将作为返回值自动返回。而 JavaScript 中的匿名函数可以有函数体和 return 语句。

差异速览

特性 JavaScript Python
创建匿名函数 (params) => expression lambda params: expression

:::tip 当 Python 的 lambda 函数有多个参数时,使用 , 隔开每一个参数。 :::

相关资源

创建和导入模块

一个庞大的应用程序通常由许多模块构成,模块在软件开发中是代码组织的独立单元,每一个 .py 文件都是一个 Python 模块,每一个 .js 文件都是一个 JavaScript 模块。

任务

设计一个程序,定义一个计算器模块,提供加减乘除四则运算功能。在另一个模块中引入该模块,计算并打印 1234 * 4321 的结果。

JavaScript 实现

javascript 复制代码
export function add(a, b) {
  return a + b;
}

export function subtract(a, b) {
  return a - b;
}

export function multiply(a, b) {
  return a * b;
}

export function divide(a, b) {
  if (b === 0) {
    throw new Error("除数不能为0");
  }
  return a / b;
}
javascript 复制代码
import { multiply } from './calculator.js';
console.log(multiply(1234, 4321));

Python 实现

python 复制代码
def add(a, b):
    return a + b

def subtract(a, b):
    return a - b

def multiply(a, b):
    return a * b

def divide(a, b):
    if b == 0:
        raise ValueError("除数不能为0")
    return a / b
python 复制代码
import calculator
result = calculator.multiply(1234, 4321)
print(result)

代码解读

  • Python 和 JavaScript 都使用 import 关键字导入模块。
  • Python 模块成员不需要使用 export 关键字进行导出,模块中全部成员都将自动导出。

:::danger Python 模块中的私有成员 在 Python 中,所有在模块内可以访问的变量、函数、类等都是自动导出的,可以被其他模块任意引用,Python 没有提供保护模块私有成员的方法。若模块中的某些成员不希望被其他模块导入,可以按照约定,使用 ___ 开头对成员进行命名。同时,在使用第三方模块时,我们也要遵守这个约定,不要直接导入和使用以下划线开头的成员。 :::

差异速览

特性 JavaScript Python
导入模块 import foo from 'module' import foo
从模块导入特定成员 import { foo, bar } from 'module' from module import foo, bar
将模块导入为别名 import { foo as alias } from 'module' from module import foo as alias
将整个模块导入为别名 import * as alias from 'module' import module as alias
默认导出 export default module -
命名导出 export foo -

:::tip Python 中的模块名称由文件名决定,文件名称不能包含 - ,否则无法被其他模块引用。

Python 在文件名与模块名之间存在一些转换约定如下:

文件名 模块名 说明
my_module.py my_module 模块名与文件保持一致
myModule.py mymodule 大写字母自动转换为小写

:::

相关资源

创建和导入包

在 Python 中,包是一个包含多个 Python 模块的目录。Python 中的包和模块的概念类似于使用目录和文件在 JavaScript 中组织和结构化代码,但略有不同。

假设有一个名为 "my_package" 的文件夹(在 Python 中称之为包),它包含了许多文件和文件夹:

markdown 复制代码
my_package/
    __init__.py
    module1.py
    module2.py
    subpackage/
        __init__.py
        module3.py

横过来是这样:

markdown 复制代码
            my_package
           /          \
   module1.py   module2.py   subpackage
                            /           \
                        module3.py   (其他模块)

首先,"my_package" 是一个文件夹,它里面有一个名为 "init.py" 的文件,它是一个特殊的文件,用户编写一些初始化包的代码,该文件是可选的。

在 "my_package" 包中,还有 "module1.py" 和 "module2.py" 两个模块,它们是编写变量、函数、类的定义的地方。

此外,还有一个名为 "subpackage" 的文件夹,它是一个子包。和 "my_package" 一样。

在 "subpackage" 子包中,有一个名为 "module3.py" 的模块。这个模块同样包含了一些变量、函数、类的定义,但它是在 "subpackage" 这个特定的上下文中使用的。

现在,可以在应用程序的任一模块中,从包中导入想要的模块

python 复制代码
import my_package.subpackage # 当不指定模块名称时,默认导入 __init__.py 中的成员,与 JavaScript 项目中的 index.js 文件作用类似
from my_package.subpackage.module3 import my_function # 从 module3.py 中的导入 my_function

如上,由包和模块的搭配,让代码形成了 "命名空间" 。

:::tip 许多 JavaScript 工程师刚接触 Python 包相关的知识时,可能还会遇到代码中的包导入时报 搜索路径相关错误 的问题,可通过 官方文档 中的说明解决。 :::

相关资源


本书的内容完全免费,开源地址:github.com/luckrnx09/p...

相关推荐
爱写代码的派大星9 分钟前
el-table :span-method 合并单元格(2.0)
前端·javascript·vue.js
夫琅禾费米线23 分钟前
CSS 设置宽高的单位概览
前端·javascript·css
张雨zy1 小时前
Vue Form表单的使用,rules格式校验网络校验,键盘按键监听
javascript·vue.js
余生H1 小时前
transformer.js(四): 模型接口介绍
前端·javascript·深度学习·transformer
liangshanbo12152 小时前
创建可重用React组件的实用指南
前端·javascript·react.js
gma9993 小时前
JSONCPP 数据解析与序列化
开发语言·前端·javascript·c++
夫琅禾费米线5 小时前
JavaScript 中的 Generator 函数及其方法
开发语言·前端·javascript
世界和平�����5 小时前
vue3 命名式(函数式)弹窗
前端·javascript·vue.js
所遇所思5 小时前
vue项目中中怎么获取环境变量
前端·javascript·vue.js
ljklxlj6 小时前
webview4/edgewebbrower学习记录——执行js
前端·javascript·学习