5. 模块化编程

更新於 發佈於 閱讀時間約 33 分鐘

HI, 大家好。我是茶桁。

上一节中我们学习了Python基本的流程控制,并且预告了这一节的内容,就是将要学习「模块化编程」。那什么是模块化编程呢?按照维基百科的说法:

模块化编程(英语:modular programming),是强调将计算机程序的功能分离成独立的、可相互改变的“模块)”(module)的软件设计技术,它使得每个模块都包含着执行预期功能的一个唯一方面(aspect)所必需的所有东西。

说的简单一点,就是把程序进行封装(函数封装、面向对象、文件...)

OK,话不多说,让我们开始吧。

函数

什么是函数?

函数的英文单词为function, 我们将其翻译过来,就是“函数,功能”。

其实,函数就是一个具有特定功能的代码块。

函数的作用

函数的目的是封装,将特定功能的代码块进行封装,其目的是提高代码的重用性,从而提高开发效率,并且降低了后期的维护成本。

函数的定义和使用

函数的定义其实非常简单,我们用代码来写一下:

# 定义函数[基本结构]
def 函数名([参数列表]):
当前行数的具体功能的代码
当前行数的具体功能的代码
...

当然,函数在写完之后并不会自动执行,只是把函数定义了而已。如果想要使用定义完成的函数,需要用语法来进行函数的调用。

那么函数该如何调用呢?如下:

函数名()

示例:

# 函数的定义格式
def love():
print('i')
print('love')
print('u')

# 函数的调用
love()

当前程序运行输出结果:

i
love
u

以上代码可以得到函数的第一个特征:函数定义后,不调用不执行。还记得咱们上节课强调的流程控制吗?代码最基本流程顺序是自上而下的,所以,这个时候我们如果调用放在上方,例如:

# 函数的调用
love()

# 函数的定义格式
def love():
print('i')
print('love')
print('u')

此时因为love()调用的时候函数还未被定义,所以会执行报错:

NameError: name 'love' is not defined
raw-image

所以我们需要注意:不能在函数定义前调用函数。

另外,我们需要注意,函数的调用不受次数的影响,比如,我们定义好函数后,这个时候在后面调用三次:

love()
love()
love()

那执行后的结果应该是连着打印了三次结果。

和变量一样,函数的命名也是要遵守命名规范的:

  • 字母数字下划线,不能以数字开头
  • 严格区分大小写,且不能使用关键字
  • 命名最好有意义,且不要使用中文

现在我们想想,在love()函数被定义后,我们再来定义一个同名的函数会怎么样?

我们尝试一下,在刚才定义好的函数下方重复写一个同名的函数:

# 函数的定义格式
def love():
print('i')
print('love')
print('u')

def love():
print('u')
print("don't")
print('love')
print('me')

# 函数的调用
love()

直接结果:

u
don't
love
me

那,我们得到了实验结果:同样的函数名被再次定义之后,冲突的函数会被覆盖。

所以,最后我们总结一下函数的特征及注意事项:

1. 函数定义后,不调用不执行
2. 不能在函数定义前调用函数
3. 函数的调用不受次数影响
4. 函数的命名要遵守命名规范
- 字母数字下划线,不能以数字开头
- 严格区分大小写,不能使用关键字
- 命名最好有意义,且不要使用中文
5. 函数名不要冲突,冲突后会被覆盖

函数的参数

在定义函数的时候,我们需要注意给函数的参数。可以在参数列表的位置进行定义,这个称为形参。如果一个函数有形参,那么在调用的时候必须传递参数(实参)。实参将值传递给实参的过程,本质上就是变量赋值操作。

函数参数概念及分类

带有参数的函数,该如何定义?

在定义函数时,在小括号内可以定义形参(形式上的参数)

def love(w):
print(f'i love {w}')

# 调用带有形参的函数时,需要传递参数(实参)
love('马户')

执行结果为:

i love 马户

在这整个函数中,小括号内的w就是形参,在调用的时候的马户就是实参,在调用过程中将值传给了形参w

那么,如果我在调用的时候没有传递实参,就会直接报错:

love()

TypeError: love() missing 1 required positional argument: 'w'

形参可以是多个,这就是定义带有多个参数的函数:

def love(m, n):
print(f'{m} love {n}')

love('i', 'u')

执行结果:

1
i love u

如果形参是多个的话,那么有多少个形参就必须传递几个实参。并且参数都是按照顺序进行传递的。

如果少传一个参数,则同样会被错。

那,能不能多传呢?也不行,如果多传了参数,一样会报错。

至此,我们可以做如下总结:

  • 函数参数:调用时需要传递的数据
  • 函数参数的大类分为形参和实参
    • 形参意思:函数定义时的参数
    • 实参意思:函数调用时的参数
  • 形实关系:函数调用时,形参和实参个数需要一一对应

函数中的参数类型

在确定了什么是形参和实参之后,我们来看看,这两种参数都有哪些类型。

函数参数在类型上,包括:

  • 普通参数
  • 默认参数
  • 收集参数
  • 命名关键字参数
  • 关键字参数收集

普通参数

先来说说普通参数,其实就是位置参数,也叫顺序参数,也是必须传递的参数。

def love(m, n):
print(f'{m} love {n}')

love('i', 'u')

这段代码中,m, n就是普通参数,必须传递。

默认参数

有些函数在定义的时候,行参上就已经定义了默认值,那么这种就叫做默认参数。

在调用函数的时候,默认参数是可以不传值的。当传值之后,默认值就会被改变:

def func(x, y=20):
print(x, y)

func(2)

这段代码中的行参y就是默认参数,我们在调用函数func()只写了一个实参,也就是只传了一个值给函数。这个时候执行结果为:

2 20

我们修改一下,传两个值进去看看结果:

def func(x, y=20):
print(x, y)

func(2, 100)

执行结果:

2 100

可以看到,本来我们定义的行参y的默认值被改变了。

在定义默认参数的时候需要注意,函数中的默认参数只能全部定义在普通参数的后面,否则在调用函数的时候就会报错,比如以下这些情况:

# 第1种错误情况
def func(x=100, y=200, z):
print(x, y, z)

func(100,200,300)

# 第2种错误情况
def func(x=100, y, z=200):
print(x, y, z)

func(100, 200, 300)

# 第3种错误情况
def func(x, y=100, z):
print(x, y, z)

func(300,200,50)

收集参数

收集参数就是专门收集在函数调用时传递的多余的实参,或者我们可以理解为,不确定需要传递多少个实参,直接用一个行参来接收。

比如,我们现在有个需求就是需要计算用户输入的数字总和,我们按前面那个函数的定义方式为:

def func(x, y z=100):
print(x+y+z)

func(20,30)

这个函数中,我们输入2个值或者3个值都可以,但是当我们只输入一个值或者三个以上的时候,程序就会报错了。

那么有没有什么办法,不管用户输入多少个数字,我们都可以进行相加计算呢?

def func(x="+", *args):
if x == '+':
print('加法运算', args)
else:
print('减法运算', args)

func("-", 2, 3, 4, 5, 6, 7, 8)

这段代码执行结果为:

减法运算 (2, 3, 4, 5, 6, 7, 8)

虽然中间的运算代码我没有写,但是大家可以看到,已经可以接受不固定的多个参数了。

这个*args就是我们的收集参数。

在定义函数的时候,如果需要收集参数,那么这个形参前面需要加一个*号,例如*args。这里需要注意一点,*args并不是固定写法,你可以随意定义一个,只要前面有*号就可以了。比如下面这样:

def func(x="+", *y):
if x == '+':
print('加法运算', y)
else:
print('减法运算', y)

func("-", 2, 3, 4, 5, 6, 7, 8)

一样可以执行并得到一样的结果,这个时候,我们的*y就是收集参数。

收集参数也有两类,一种是普通的收集参数:专门用于收集多余的普通参数,形成一个新的元组。

语法: 参数前面加*, 例如:*args

还有一种是关键字收集参数:用于专门收集多余关键字实参,形成一个新的字典:

语法:参数前面加**, 例如:**kwargs

现在我们已经理解了普通的收集参数,那么在学习关键字收集参数之前,我们先来学习一下命名关键字参数

命名关键字参数

命名关键字是放在*号后面的参数,调用的时候强制必须传入制定参数名才能进行调用。

def func(a, b, c=3, *args, name):
print(a, b, c, "\n", *args, "\n", name)

func(1, 2, 3, 4, 5, 6, 7, 8, name='茶桁')

这段代码执行结果:

1 2 3 
4 5 6 7 8
茶桁

我们特意在中间加了换行字符来清晰的辨别*argsname

如果在这段代码中我稍微变一下,在执行函数的时候,实参里不标明name可以吗?

def func(a, b, c=3, *args, name):
print(a, b, c, "\n", *args, "\n", name)

func(1, 2, 3, 4, 5, 6, 7, 8, '茶桁')

执行之后我们收到了报错:

TypeError: func() missing 1 required keyword-only argument: 'name'

这段报错明显告诉我们,确实了一个必须的关键字参数name

那为什么会出现这种报错呢?这是因为在关键字参数之前,我们使用了*args来进行收集参数,那么无论你写多少,这些值都会被*args接收变成元组,那么后面的name自然就无法接受到值了。

让我们再来做一个实验,给命名关键字参数加上一个默认值,那么我们就能明显的看出问题:

def func(a, b, c=3, *args, name='_茶桁'):
print(a, b, c, "\n", *args, "\n", name)

func(1, 2, 3, 4, 5, 6, 7, 8, '茶桁')

这段代码执行结果:

1 2 3 
4 5 6 7 8 茶桁
_茶桁

可以看到,name给了默认值之后不再出现报错,而我们的实参也并未传到name里,而是全部被*args接收了。最后打印出了name的默认值_茶桁

利用命名参数的这种定义参数名称接收值的特点,我们就可以打乱之前普通参数传值的顺序性,比如:

def func(x, y):
print(x, "\t", y)

func(2, 3)
func(y = 2, x = 3)

执行结果为:

2 	 3
3 2

还是最开始的普通参数的写法,但是最后执行函数的时候,我们给实参指定了名称,这样传参顺序就没那么重要了。

所以,我们总结一下:

  • 关键字参数定义在收集参数后面
  • 关键字参数必须通过形参的名字来进行传递

关键字参数收集

前面我们在讲收集参数的结尾处提到了关键字参数收集,形式为**kwargs

def func(a, b, c=3, *args, name, age,  **kwargs):
print(a, b, c)
print(args) # 普通收集参数,会把多余的参数收集为元组
print(name, age)
print(kwargs) # 关键字参数收集,会把多余的关键字参数收集为字典

func(1, 2, 4, 112, 123, 321, 541, 231, name="茶桁", age=18, sex='male', height=185, x='x', y='y')

执行结果:

1 2 4
(112, 123, 321, 541, 231)
茶桁 18
{'sex': 'male', 'height': 185, 'x': 'x', 'y': 'y'}

从执行结果上我们可以看到,在nameage之后的所有参数都被传递到了**kwargs里,然后作为字典打印了出来。

在声明这个函数和执行函数的时候需要注意,这些参数都是有顺序的,如果在执行函数的时候再多传一个非关键字参数,这个时候程序就会报错,如果是关键字参数,则照样会被**kwargs接收。

在我们介绍完这些参数之后,我们最后再说明一下:

  • 形参声明的位置顺序:普通参数 -> 默认参数 -> 收集参数 -> 命名关键字参数 -> 关键字收集参数
  • def func(a, b, c=1, *args, d, **kw) 这段声明中,a,b为普通参数,c是默认参数,args是收集参数,d是命名关键字参数,kw是关键字收集参数
  • 极少情况下会同时出现上面五种形参,一般情况下为:普通参数,收集参数,关键字收集参数
  • 所有参数的摆放问题:
    • 实参:普通实参在前,关键字参数在后
    • 形参:关键字收集参数一定在最后出现,收集参数推荐在普通参数之后使用。
    • 推荐顺序:普通形参、收集参数、关键字收集参数

函数的返回值

一个函数除了可以完成一定功能之外,还可以用来安需要返回一些内容。在函数中,使用return关键字来制定返回数据,可以返回任意类型的数据。

函数的返回值会把数据返回到调用的地方,可以使用变量进行接收,或者作其他处理。

函数可以分为两类:

  1. 执行过程函数:函数体内完成一定的功能即可,没有返回值
  2. 具有返回值的函数:函数体内完成一定的功能,并且返回一个结果到函数调用处。

比如:

def func(a, b):
print(f'{a} love {b}')

以上函数就是一个没有返回值的函数,这个函数只是为了完成打印这句话的功能。

那么有返回值的函数是什么样子?

如果需要在函数中制定返回内容,我们需要使用return关键字。

# 有返回值的函数
def func(a, b):
res = f'{a} love {b}'
# 可以在函数体内,使用return返回内容
return res

r = func('老鼠', '布丁')
print(r)

执行结果为:

老鼠 love 布丁

在这段代码中,我们在func()的函数体内最后利用关键字return返回了任意内容,并且使用变量r接收了这个返回值,最后讲r打印了出来。

在调用func()这个函数的时候,函数中的返回值会返回到函数调用处。

我们再来研究一下return这个关键字,我们在return的前后都加上一段打印代码,看看会发生什么。

def func(a, b):
res = f'{a} love {b}'
print('这是return前')
return res
print('这是return后')

r = func('老鼠','布丁')
print(r)

执行结果:

这是return
老鼠 love 布丁

看到结果我们可以清楚,return之后的的代码并未继续执行,也就是说,我们如果要在函数体内执行其他任务,必须放在return之前执行,否则根本不会执行。那么我们可以得出结论:return必须放在一个定义函数的最后面。

Tips: 其实,即便没有return关键字或者returen之后没有任何内容,也有返回值,只是返回的是None值。

None是一个特殊的数据,表示什么都没有。查询类型可以看到返回 <class ‘NoneType’>

变量的作用域

作用域就是当前起作用,可用的范围区域。也就是变量的有效范围。

变量按作用域可以分为:

  • 局部变量: 在函数内部可以使用的变量
  • 全局变量:在函数内外都可以使用的变量

局部变量

让我们尝试下,如果函数内定义的变量在函数外使用会如何:

def func():
a = 20

print(a)

执行结果:

NameError: name 'a' is not defined

被告知a并未被定义。

可以看到,函数内定义的变量,在函数外连获取都做不到。这种在函数内定义的这个变量a,就是局部变量,它在函数外不能使用。

再让我们来看看将变量定义在函数外会是怎样的一种情况:

num = 10
def func():
print(num)

func()

执行结果:

10

func函数内,我们获取到了变量num的值并打印。那说明,在函数内我们可以获取函数外部的变量。

我们继续在继续看:

num = 10
def func():
num += 20
print(num)

func()

执行后报错:

UnboundLocalError: local variable 'num' referenced before assignment

这样我们可以看到,变量num在函数内虽然可以使用,但是无法进行更改。

那在函数外定义的所有变量都是如此吗?再让我们试试看:

items = [1, 2, 3, 4, 5]
def func():
items[0] = 20
print(items)

func()

执行结果:

[20, 2, 3, 4, 5]

由此我们看出,并不是所有的变量都不可在函数内进行更改。

其实,变量是分为两种的:

  • 可变数据类型:在函数外定义的变量,在函数内可以使用并改变
  • 不可变数据类型:在函数外定义的变量,在函数内只可以访问而无法改变

可变数据类型有列表和字典,其他的都是不可变数据类型。

全局变量

之前我们介绍的都是局部变量,那怎样定义全局变量呢?

在函数内使用global直接定义的变量,就是全局变量,函数内外都可以直接使用。

在函数外定义的变量,在函数内使用global关键字进行声明,那么也是全局变量。

例如:

num = 20
def func():
global num
num += 10
print(num)

func()

这个时候我们可以得到执行结果:

30

那有小伙伴就问了,如果我在函数外直接使用global定义全局变量可以吗?让我们来试试看就知道了:

global num
num = 20
def func():
num += 10
print(num)

func()

执行之后得到报错:

UnboundLocalError: local variable 'num' referenced before assignment

这样我们就得到了结果:不可以。

在整个程序中,我们可以使用两个函数方法来获取数据:

globals()用来获取全局数据,locals()用来获取当前作用域的数据

讲到这里,我们再来多看一组代码:

# 函数的作用域
def outer():
print('this is outer func...')
def inner():
print('this is inner func...')

outer()
inner()

这段代码执行结果为:

this is outer func...

NameError: name 'inner' is not defined

正常执行了outer()内的打印,然后又报了一个错误,提示inner函数未定义。

说明,不只是变量有作用域,函数一样也有作用域。要想inner函数内的打印也起作用,我们需要在函数内就调用执行inner()

# 函数的作用域
def outer():
print('this is outer func...')
def inner():
print('this is inner func...')
inner() # 在函数内执行
outer()

这样,我们执行的结果就是:

this is outer func...
this is inner func...

如果我们在外层函数中定义一个局部变量,能在内层函数中使用吗?

# 函数的作用域
def outer():
a = 2
print('this is outer func...')
def inner():
a += 1
print('this is inner func...')
print(a)
inner()
outer()

执行之后得到报错:

UnboundLocalError: local variable 'a' referenced before assignment

说明并不可以。

nonlocal关键字

那么,到底有没有什么办法在内函数中使用上一层函数中的局部变量呢?答案是有办法。

在内函数中如果想要使用外层函数的变量,那么需要使用nonlocal关键字,可以引用上一层函数中定义的局部变量。

# 定义一个外层函数
def outer():
# 外函数的局部变量
num = 10
# 内函数, 局部函数, 在函数的内部定义的函数
def inner():
# nonlocal 关键字在局部函数中使用
nonlocal num # 可以引用上一层函数中定义的局部变量
num += 1
print(num)
inner()
outer()

执行后返回结果:

11

至此,我们通过使用nonlocal关键字,成功拿到了外层函数定义的变量num并使用。最后打印出使用的结果。

这里我们要注意,nonlocal虽然可以引用上一层函数中定义的局部变量,但是这并不代表提升为了全局变量。

既然我们有了global关键字可以提升变量为全局变量,为什么还需要一个nonlocal关键字呢?是不是有点多此一举?

这两者的功能上并不相同。global关键字修饰变量后标识该变量是全局变量,对该变量进行修改就是修改全局变量,而nonlocal关键字修饰变量后标识该变量是上一级函数中的局部变量,如果上一级函数中不存在该局部变量,nonlocal位置会发生错误(最上层的函数使用nonlocal修饰变量必定会报错)。

关于函数的文档

我们在一个未定义任何变量和函数的空白文档中打印一下全局数据:

print(globals())

执行结果:

{
'__name__': '__main__',
'__doc__': 'Automatically created module for IPython interactive environment',
'__package__': None,
'__loader__': None,
'__spec__': None,
'__builtin__': <module 'builtins' (built-in)>,
'__builtins__': <module 'builtins' (built-in)>,
'_ih': ['',
'print(globals())'],
'_oh': {},
'_dh': [PosixPath('/Users/xx/git/AI_Cheats/Python'),
PosixPath('/Users/xx/git/AI_Cheats/Python')],
'In': ['',
'print(globals())'],
'Out': {},
'get_ipython': <bound method InteractiveShell.get_ipython of <ipykernel.zmqshell.ZMQInteractiveShell object at 0x105be29e0>>,
'exit': <IPython.core.autocall.ZMQExitAutocall object at 0x105be3280>,
'quit': <IPython.core.autocall.ZMQExitAutocall object at 0x105be3280>,
'open': <function open at 0x10488e710>,
'_': '',
'__': '',
'___': '',
'__vsc_ipynb_file__': '/Users/xx/git/AI_Cheats/Python/globals.ipynb',
'_i': '',
'_ii': '',
'_iii': '',
'_i1': 'print(globals())'
}

我们来看这个打印出来的json

类似于__name__这种前后有__ __的数据,称之为“魔术变量”。我们并未定义,但是已经存在了。

如果脚本作为主程序,那么__name__值是__main__,如果是当作一个模块在另外一个脚本中引用去使用,那么值就是当前文件的命名。

__doc__当前脚本的文档说明,在当前脚本当中的第一个三引号注释就是当前脚本的说明文档。比如,我们在这个空白的文档中写一段三引号注释

"""
这里是整个文档的说明部分。
"""
def func():
pass

然后我们直接将doc打印出来查看:

print(__doc__)

可以看到输出内容:

这里是整个文档的说明部分。

这种文档其实不止适用于python文件,对于定义的函数依然适用。比如,我们执行定义了一个函数,并在函数内部用三引号进行注释:

def func():
"""
这里是让你写一写函数的文档说明的。
需要说明当前函数的作用,
如果当前函数还有形参,那么也需要对形参进行一一说明。
name: 这个是一个name参数,用于接收姓名
age: 这个参数是表示年龄
:return: 此处说明当前函数的返回值
"""
pass

这个时候,我们在下方执行:

print(func.__doc__)

可以看到我们在注释内定义的说明文档被打印出来了:

raw-image

这样,我们不仅可以在自己写函数的时候在上方清晰的写明当前函数的作用及参数,我们还可以使用此方法,查找其他人所写的函数的一些说明。

在我们平时写代码的时候,养成一个好习惯是非常有必要的。

总结一下:

  • print(__name__): 获取当前脚本的文件名
  • print(__doc__): 获取当前脚本的说明文档
  • print(func.__doc__): 获取当前函数的说明文档

练习:函数封装

我们上一讲中的练习中,我们打印了乘法表,矩形图形,还计算了12生肖。这里我们就将乘法表来封装成函数,实现我们上节课留的其中一道思考题:反向打印。

我们先将打印乘法表封装起来:

# 定义函数,打印九九乘法表
def multiply_table():
"""
当前函数的功能是打印出乘法表
"""
for x in range(1, 10):
for y in range(1, x+1):
print(f'{x}X{y}={x*y}', end=" ")
print()

这样,我们在其他地方执行multiply_table()函数的时候,就可以直接打印出乘法表。

现在让我们给这个函数多加一些功能:

# 定义函数,打印九九乘法表
def multiply_table(i=0):
"""
当前函数的功能是打印出乘法表
i=0; i 这个参数可以用来控制正向输出和方向输出,0的时候正向,1的时候反向,默认为0
"""
if i:
rs = range(9, 0, -1)
else:
rs = range(1, 10)

for x in rs:
for y in range(1, x+1):
print(f'{x}X{y}={x*y}', end=" ")
print()

我们执行函数的时候,输入1来试试看:

multiply_table(1)

输出结果:

9X1=9 9X2=18 9X3=27 9X4=36 9X5=45 9X6=54 9X7=63 9X8=72 9X9=81 
8X1=8 8X2=16 8X3=24 8X4=32 8X5=40 8X6=48 8X7=56 8X8=64
7X1=7 7X2=14 7X3=21 7X4=28 7X5=35 7X6=42 7X7=49
6X1=6 6X2=12 6X3=18 6X4=24 6X5=30 6X6=36
5X1=5 5X2=10 5X3=15 5X4=20 5X5=25
4X1=4 4X2=8 4X3=12 4X4=16
3X1=3 3X2=6 3X3=9
2X1=2 2X2=4
1X1=1

可以看到,我们的控制结果被成功打印出来。至此,这个有一些小功能的九九乘法表就封装完成了。

那么这一节课就不留思考题了,大家课后熟练掌握一下封装函数和变量的作用域,我们下节课来学习一些高阶函数, 好,下课。

留言
avatar-img
留言分享你的想法!
avatar-img
茶桁的沙龍
9會員
62內容數
从基础开始,再到Python,然后是CV、BI、NLP等相关技术。从头到尾详细的教授一边人工智能。
茶桁的沙龍的其他內容
2023/10/08
Hi,你好。我是茶桁。 我们在机器学习入门已经学习了两节课,分别接触了动态规划,机器学习的背景,特征向量以及梯度下降。 本节课,我们在深入的学习一点其他的知识,我们来看看K-means. 当然,在本节课我们也只是浅尝即止,关于这些内容,后面我们还有更详细的内容等着我们去深入学习。
Thumbnail
2023/10/08
Hi,你好。我是茶桁。 我们在机器学习入门已经学习了两节课,分别接触了动态规划,机器学习的背景,特征向量以及梯度下降。 本节课,我们在深入的学习一点其他的知识,我们来看看K-means. 当然,在本节课我们也只是浅尝即止,关于这些内容,后面我们还有更详细的内容等着我们去深入学习。
Thumbnail
2023/10/07
Hi, 你好。我是茶桁。 上一节课,咱们用一个案例引入了机器学习的话题,并跟大家讲了一下「动态规划」。 那这节课,我们要真正进入机器学习。 机器学习初探 在正式开始之前,我们来想这样一个问题:我为什么要先讲解「动态规划」,然后再引入机器学习呢? 原因其实是这样:曾经有一度时间,差不多一
Thumbnail
2023/10/07
Hi, 你好。我是茶桁。 上一节课,咱们用一个案例引入了机器学习的话题,并跟大家讲了一下「动态规划」。 那这节课,我们要真正进入机器学习。 机器学习初探 在正式开始之前,我们来想这样一个问题:我为什么要先讲解「动态规划」,然后再引入机器学习呢? 原因其实是这样:曾经有一度时间,差不多一
Thumbnail
2023/10/02
从一个案例开始 动态规划 Hi, 你好。我是茶桁。 咱们之前的课程就给大家讲了什么是人工智能,也说了每个人的定义都不太一样。关于人工智能的不同观点和方法,其实是一个很复杂的领域,我们无法用一个或者两个概念确定什么是人工智能,无法具体化。 我也是要给大家讲两个重要的概念,要成为一个良好
Thumbnail
2023/10/02
从一个案例开始 动态规划 Hi, 你好。我是茶桁。 咱们之前的课程就给大家讲了什么是人工智能,也说了每个人的定义都不太一样。关于人工智能的不同观点和方法,其实是一个很复杂的领域,我们无法用一个或者两个概念确定什么是人工智能,无法具体化。 我也是要给大家讲两个重要的概念,要成为一个良好
Thumbnail
看更多
你可能也想看
Thumbnail
沙龍一直是創作與交流的重要空間,這次 vocus 全面改版了沙龍介面,就是為了讓好內容被好好看見! 你可以自由編排你的沙龍首頁版位,新版手機介面也讓每位訪客都能更快找到感興趣的內容、成為你的支持者。 改版完成後可以在社群媒體分享新版面,並標記 @vocus.official⁠ ♥️ ⁠
Thumbnail
沙龍一直是創作與交流的重要空間,這次 vocus 全面改版了沙龍介面,就是為了讓好內容被好好看見! 你可以自由編排你的沙龍首頁版位,新版手機介面也讓每位訪客都能更快找到感興趣的內容、成為你的支持者。 改版完成後可以在社群媒體分享新版面,並標記 @vocus.official⁠ ♥️ ⁠
Thumbnail
每年4月、5月都是最多稅要繳的月份,當然大部份的人都是有機會繳到「綜合所得稅」,只是相當相當多人還不知道,原來繳給政府的稅!可以透過一些有活動的銀行信用卡或電子支付來繳,從繳費中賺一點點小確幸!就是賺個1%~2%大家也是很開心的,因為你們把沒回饋變成有回饋,就是用卡的最高境界 所得稅線上申報
Thumbnail
每年4月、5月都是最多稅要繳的月份,當然大部份的人都是有機會繳到「綜合所得稅」,只是相當相當多人還不知道,原來繳給政府的稅!可以透過一些有活動的銀行信用卡或電子支付來繳,從繳費中賺一點點小確幸!就是賺個1%~2%大家也是很開心的,因為你們把沒回饋變成有回饋,就是用卡的最高境界 所得稅線上申報
Thumbnail
全球科技產業的焦點,AKA 全村的希望 NVIDIA,於五月底正式發布了他們在今年 2025 第一季的財報 (輝達內部財務年度為 2026 Q1,實際日曆期間為今年二到四月),交出了打敗了市場預期的成績單。然而,在銷售持續高速成長的同時,川普政府加大對於中國的晶片管制......
Thumbnail
全球科技產業的焦點,AKA 全村的希望 NVIDIA,於五月底正式發布了他們在今年 2025 第一季的財報 (輝達內部財務年度為 2026 Q1,實際日曆期間為今年二到四月),交出了打敗了市場預期的成績單。然而,在銷售持續高速成長的同時,川普政府加大對於中國的晶片管制......
Thumbnail
在第十二課中,我們將學習 Python 中的模塊和包的概念。 模塊和包是 Python 中組織程式碼的主要方式,它們讓你能夠以邏輯和易於管理的方式組織你的程式碼。
Thumbnail
在第十二課中,我們將學習 Python 中的模塊和包的概念。 模塊和包是 Python 中組織程式碼的主要方式,它們讓你能夠以邏輯和易於管理的方式組織你的程式碼。
Thumbnail
在第七課,我們將談論 Python 中的模組 (Modules) 和套件 (Packages)。 模組和套件允許我們將 Python 程式碼組織成可重用的單元,有助於程式碼的模組化和重用。
Thumbnail
在第七課,我們將談論 Python 中的模組 (Modules) 和套件 (Packages)。 模組和套件允許我們將 Python 程式碼組織成可重用的單元,有助於程式碼的模組化和重用。
Thumbnail
Hi, 大家好。我是茶桁。 这一段Python之旅怎么样?还算顺利吧? 之前我们都学习了些什么?有基本常识,流程,函数,不同类型的数据以及一些模块对吧?并且还做了一些练习来巩固所学过的内容。 那么今天,我们接着来学习模块。不过今天要学的模块和以往不太一样了,以前我们学习的都是Python内
Thumbnail
Hi, 大家好。我是茶桁。 这一段Python之旅怎么样?还算顺利吧? 之前我们都学习了些什么?有基本常识,流程,函数,不同类型的数据以及一些模块对吧?并且还做了一些练习来巩固所学过的内容。 那么今天,我们接着来学习模块。不过今天要学的模块和以往不太一样了,以前我们学习的都是Python内
Thumbnail
Hi,大家好。我是茶桁。 系统内置模块就是安装完Python解释器之后,系统本身所提供的模块。我知道,咱们之前的课程里有学习系统的内置函数,这个模块和函数不是一个东西。模块这种东西,是需要导入后才可以使用的,比如:json, re, os等等。
Thumbnail
Hi,大家好。我是茶桁。 系统内置模块就是安装完Python解释器之后,系统本身所提供的模块。我知道,咱们之前的课程里有学习系统的内置函数,这个模块和函数不是一个东西。模块这种东西,是需要导入后才可以使用的,比如:json, re, os等等。
Thumbnail
在第五堂課中,我們將探討 Python 中的函式(functions)。 函式是一種讓我們可以將程式碼塊組織成一個獨立、可重複使用的單元的方式。 函式可以接受參數 (arguments) 並返回一個結果。 讓我們在新的文件 functions.py 中學習如何定義和使用函式。
Thumbnail
在第五堂課中,我們將探討 Python 中的函式(functions)。 函式是一種讓我們可以將程式碼塊組織成一個獨立、可重複使用的單元的方式。 函式可以接受參數 (arguments) 並返回一個結果。 讓我們在新的文件 functions.py 中學習如何定義和使用函式。
Thumbnail
在第五課中,我們將探討 Python 中的函式(functions)。 函式是一種讓我們可以將程式碼塊組織成一個獨立、可重複使用的單元的方式。函式可以接受參數 (arguments) 並返回一個結果。
Thumbnail
在第五課中,我們將探討 Python 中的函式(functions)。 函式是一種讓我們可以將程式碼塊組織成一個獨立、可重複使用的單元的方式。函式可以接受參數 (arguments) 並返回一個結果。
Thumbnail
HI, 大家好。我是茶桁。 上一节中我们学习了Python基本的流程控制,并且预告了这一节的内容,就是将要学习「模块化编程」。那什么是模块化编程呢?按照维基百科的说法: 模块化编程(英语:modular programming),是强调将计算机程序的功能分离成独立的、可相互改变的“模块)”(mo
Thumbnail
HI, 大家好。我是茶桁。 上一节中我们学习了Python基本的流程控制,并且预告了这一节的内容,就是将要学习「模块化编程」。那什么是模块化编程呢?按照维基百科的说法: 模块化编程(英语:modular programming),是强调将计算机程序的功能分离成独立的、可相互改变的“模块)”(mo
Thumbnail
Python的系列课程是写给零基础的小白看的,如果基础比较好的小伙伴可以暂时先不关注,等待后续课程。 Hi, 大家好,我是茶桁。 之前的课程已经给大家讲解了Python相关特性和基本语法。那么这节课呢,我们尝试着从最简单的脚本来开始认识Python。 在开始这节课之前呢,我是默认大家已经安装好
Thumbnail
Python的系列课程是写给零基础的小白看的,如果基础比较好的小伙伴可以暂时先不关注,等待后续课程。 Hi, 大家好,我是茶桁。 之前的课程已经给大家讲解了Python相关特性和基本语法。那么这节课呢,我们尝试着从最简单的脚本来开始认识Python。 在开始这节课之前呢,我是默认大家已经安装好
Thumbnail
我們將探索函式的定義和調用,這是程式設計中非常重要且強大的概念,它可以將大型程式切割成小的、可重複使用的函式。讓我們一起來了解吧!函式的定義、呼叫和返回值是學習函式的核心。
Thumbnail
我們將探索函式的定義和調用,這是程式設計中非常重要且強大的概念,它可以將大型程式切割成小的、可重複使用的函式。讓我們一起來了解吧!函式的定義、呼叫和返回值是學習函式的核心。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News