【全栈之路】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...

相关推荐
ew452182 小时前
ElementUI表格表头自定义添加checkbox,点击选中样式不生效
前端·javascript·elementui
画月的亮2 小时前
element-ui 使用过程中遇到的一些问题及解决方法
javascript·vue.js·ui
m0_526119402 小时前
点击el-dialog弹框跳到其他页面浏览器的滚动条消失了多了 el-popup-parent--hidden
javascript·vue.js·elementui
工业甲酰苯胺5 小时前
Vue3 基础概念与环境搭建
前端·javascript·vue.js
lyj1689975 小时前
el-tree选中数据重组成树
javascript·vue.js·elementui
lonelyhiker7 小时前
javascript的原型链
开发语言·javascript·原型模式
MarkHD9 小时前
第十六天 HarmonyOS WebView开发实战:从加载网页到与JavaScript交互
javascript·交互·harmonyos
柴柴的小记9 小时前
前端vue引入特殊字体不生效
前端·javascript·vue.js
bin915310 小时前
DeepSeek 助力 Vue 开发:打造丝滑的颜色选择器(Color Picker)
前端·javascript·vue.js·ecmascript·deepseek
程序员黄同学10 小时前
请解释设备像素、CSS 像素、设备独立像素、DPR、PPI 之间的区别 ?
开发语言·javascript