5. 模块化编程

2023-11-07

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

image-20230802142829519

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

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

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')

执行结果:

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__)

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

image-20230803024715900

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

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

总结一下:

  • 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 

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

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

如果你想查看的话,本文的代码可以在文末点击阅读原文后找到Github的链接。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

5. 模块化编程 的相关文章

  • 如何传递架构以从现有数据帧创建新数据帧?

    要将 schema 传递到 json 文件 我们这样做 from pyspark sql types import StructField StringType StructType IntegerType data schema Stru
  • 计算另一个字符串中多个字符串的出现次数

    在 Python 2 7 中 给定以下字符串 Spot是一只棕色的狗 斑点有棕色的头发 斑点的头发是棕色的 查找字符串中 Spot brown 和 hair 总数的最佳方法是什么 在示例中 它将返回 8 我正在寻找类似的东西string c
  • Gunicorn 工作人员无论如何都会超时

    我正在尝试通过gunicorn运行一个简单的烧瓶应用程序 但是无论我做什么 我的工作人员都会超时 无论是否有针对应用程序的活动 工作人员在我设置任何内容后总是会超时timeout值到 是什么导致它们超时 当我发出请求时 请求成功通过 但工作
  • VSCode Settings.json 丢失

    我正在遵循教程 并尝试将 vscode 指向我为 Scrapy 设置的虚拟工作区 但是当我在 VSCode 中打开设置时 工作区设置 选项卡不在 用户设置 选项卡旁边 我还尝试通过以下方式手动转到文件 APPDATA Code User s
  • Django Rest Framework 是否有第三方应用程序来自动生成 swagger.yaml 文件?

    我有大量的 API 端点编写在django rest framework并且不断增加和更新 如何创建和维护最新的 API 文档 我当前的版本是 Create swagger yaml文件并以某种方式在每次端点更改时自动生成 然后使用此文件作
  • 嵌套列表的重叠会产生不必要的间隙

    我有一个包含三个列表的嵌套 这些列表由 for 循环填充 并且填充由 if 条件控制 第一次迭代后 它可能类似于以下示例 a 1 2 0 0 0 0 0 0 4 5 0 0 0 0 0 0 6 7 根据条件 它们不重叠 在第二次迭代之后 新
  • 如何从Python中的函数返回多个值? [复制]

    这个问题在这里已经有答案了 如何从Python中的函数返回多个变量 您可以用逗号分隔要返回的值 def get name you code return first name last name 逗号表示它是一个元组 因此您可以用括号将值括
  • python multiprocessing 设置生成进程等待

    是否可以生成一些进程并将生成进程设置为等待生成的进程完成 下面是我用过的一个例子 import multiprocessing import time import sys def daemon p multiprocessing curr
  • 打印数字时添加千位分隔符[重复]

    这个问题在这里已经有答案了 我真的不知道这个问题的 名称 所以它可能是一个不正确的标题 但问题很简单 如果我有一个数字 例如 number 23543 second 68471243 我想要它使print 像这样 23 54368 471
  • GUI(输入和输出矩阵)?

    我需要创建一个 GUI 将数据输入到矩阵或表格中并读取此表单数据 完美的解决方案是限制输入表单仅允许float 例如 A 1 02 0 25 0 30 0 515 0 41 1 13 0 15 1 555 0 25 0 14 1 21 2
  • 如何将特定范围内的标量添加到 numpy 数组?

    有没有一种更简单 更节省内存的方法可以单独在 numpy 中执行以下操作 import numpy as np ar np array a l r ar c a a 0 l ar tolist a r 它可能看起来很原始 但它涉及获取给定数
  • 为什么一旦我离开内置的运行服务器,Django 就无法找到我的管理媒体文件?

    当我使用内置的简单服务器时 一切正常 管理界面很漂亮 python manage py runserver 但是 当我尝试使用 wsgi 服务器为我的应用程序提供服务时django core handlers wsgi WSGIHandle
  • Python 3:将字符串转换为变量[重复]

    这个问题在这里已经有答案了 我正在从 txt 文件读取文本 并且需要使用我读取的数据之一作为类实例的变量 class Sports def init self players 0 location name self players pla
  • 使用 python/numpy 重塑数组

    我想重塑以下数组 gt gt gt test array 11 12 13 14 21 22 23 24 31 32 33 34 41 42 43 44 为了得到 gt gt gt test2 array 11 12 21 22 13 14
  • 使用 Python Oauthlib 通过服务帐户验证 Google API

    我不想使用适用于 Python 的 Google API 客户端库 但仍想使用 Python 访问 Google APIOauthlib https github com idan oauthlib 创建服务帐户后谷歌开发者控制台 http
  • 当字段是数字时怎么说...在 mongodb 中匹配?

    所以我的结果中有一个名为 城市 的字段 结果已损坏 有时它是一个实际名称 有时它是一个数字 以下代码显示所有记录 db zips aggregate project city substr city 0 1 sort city 1 我需要修
  • pandas - 包含时间序列数据的堆积条形图

    我正在尝试使用时间序列数据在 pandas 中创建堆积条形图 DATE TYPE VOL 0 2010 01 01 Heavy 932 612903 1 2010 01 01 Light 370 612903 2 2010 01 01 Me
  • 重新分配唯一值 - pandas DataFrame

    我在尝试着assign unique值在pandas df给特定的个人 For the df below Area and Place 会一起弥补unique不同的价值观jobs 这些值将分配给个人 总体目标是使用尽可能少的个人 诀窍在于这
  • 如何在 Flask 中的视图函数/会话之间传递复杂对象

    我正在编写一个 Web 应用程序 当 且仅当 用户登录时 该应用程序从第三方服务器接收大量数据 这些数据被解析为自定义对象并存储在list 现在 用户在应用程序中使用这些数据 调用不同的视图 例如发送不同的请求 我不确定什么是最好的模式在视
  • python 对浮点数进行不正确的舍入

    gt gt gt a 0 3135 gt gt gt print 3f a 0 314 gt gt gt a 0 3125 gt gt gt print 3f a 0 312 gt gt gt 我期待 0 313 而不是 0 312 有没有

随机推荐

  • Python中的len()函数

    函数 len 1 作用 返回字符串 列表 字典 元组等长度 2 语法 len str 3 参数 str 要计算的字符串 列表 字典 元组等 4 返回值 字符串 列表 字典 元组等元素的长度 5 实例 5 1 计算字符串的长度 gt gt g
  • python编程 报错解决:“AttributeError: ‘str‘ object has no attribute ‘decode‘”

    简介 在做django项目遇到了如题的报错 通过搜索分析是encode decode的问题 我的decode encode并没有出现在我编写的代码中 而是在D python Lib site packages django db backe
  • web项目打包到上线教程_web项目打包,发布以及部署

    如何将 web 工程打包 war 和解包 war 1 打包 war 进入 工程 应用的根目录 比如 webapps myjspweb 2 把整个 web 应用打包为 myjspwar war 文件 命令如下 jar cvfmyjspweb
  • jmeter常用线程组设置策略

    目录 一 前言 二 单场景基准测试 1 介绍 2 线程组设计 3 测试结果 三 单场景并发测试 1 介绍 2 线程组设计 3 测试结果 四 单场景容量 爬坡测试 1 介绍 2 线程组设计 3 测试结果 五 混合场景容量 并发测试 1 介绍
  • 踩坑了,BigDecimal 使用不当,造成 P0 事故!

    大家好 我是东哥 可能对于刚入门的新手不太理解P0的概念 下面简单解释一下 P0属于最高级别事故 比如崩溃 页面无法访问 主流程不通 主功能未实现 或者在影响面上影响很大 即使bug本身不严重 目录 背景 事故 分析 总结 工具分享 背景
  • 【Kubernetes系列】Kubernetes组件介绍

    概述 kubernetes中文文档 https kubernetes io zh docs home kubernetes中文社区 https www kubernetes org cn docs kubernetes的本质是一组服务器集群
  • PCL 网格投影曲面重建算法

    目录 一 算法原理 1 算法概述 二 代码实现 三 结果展示 一 算法原理 1 算法概述 类GridProjection实现了网格投影曲面重建算法 详细信息参考Polygonizingextremal surfaces with manif
  • Ubuntu16.04 64位系统下面安装JDK1.7

    1 去到官网下载jdk 点击打开链接 2 安装WinSCP工具连接到linux系统上面在 usr lib里面新建一个jvm文件夹 然后把下载的jdk 7u79 linux x64 tar gz上传到jvm里面 3 解压刚上传的jdk 7u7
  • 计算机视觉的定义,应用及整个系统

    定义 计算机视觉是使用计算机及相关设备对生物视觉的一种模拟 它的主要任务就是通过对采集的图片或视频进行处理以获得相应场景的三维信息 就像人类和许多其他类生物每天所做的那样 计算机视觉是一门关于如何运用照相机和计算机来获取我们所需的 被拍摄对
  • Linux查看当前目录下文件及文件夹的大小

    使用场景 查看服务器磁盘空间使用情况 快速定位当前目录下的大文件夹 快速找出大文件 推荐一个比较好用的命令 du h max depth 1 当前参数讲解 h 以可读性较好的方式显示尺寸 例如 1K 1M 1G max depth N 显示
  • objc学习笔记-基础

    1 xcode 4 3 3以后 NSAutoreleasePool 的用法发生改变 由 NSAutoreleasePool pool NSAutoreleasePool alloc init pool drain 变为 autoreleas
  • MySQL的分片(一)——分布式数据库概述

    系统分析 OLAP or OLTP 在互联网时代 海量数据的存储与访问成为系统设计与使用的瓶颈问题 对于海量数据处理 按照使用场景 主要分为两种类型 联机事务处理 OLTP 和联机分析处理 OLAP 联机事务处理 OLTP 也称为面向交易的
  • Typora+PicGo+GitHub搭建免费图床

    准备工作 Typora官网 PicGo官网 PicGo Core配置文件 Github 或Gitee Github准备图床仓库 新建一个仓库 仓库一定要设置为public公共仓库 生成私人令牌 Github主页右上角点击用户头像 gt Se
  • 课程2:《黑马程序员_Java基础视频-深入浅出精华版》-视频列表-

    day01 avi 01 01 计算机基础 计算机概述 avi day01 avi 01 02 计算机基础 计算机硬件和软件概述 avi day01 avi 01 03 计算机基础 软件开发和计算机语言概述 avi day01 avi 01
  • 用数学思想演绎的一些系统概念

    在这一部分要给出系统的数学定义 因为公式编辑器有时候不太好用 所以尽量简化 系统的定义 增长 竞争 整体 和 机械化 中心化 最终形态 最终形态的类型 学科中的同构 学科的联合 1 系统的定义 系统的数学定义如下 系统是由元素 元素之间相互
  • ip route 路由命令详解

    523条消息 ip route 命令详解 thj blog的博客 CSDN博客 ip route命令详解 Linux如何查看网关地址 study goup 博客园 cnblogs com 添加路由192 20 30 0 24网段走eth0网
  • python接口自动化测试视频教程百度云全集_python自动化运维测试框架实战视频教程百度云资源...

    python自动化运维测试框架实战视频教程百度云资源 web app 接口自动化 自动化框架 课程目录 开学典礼 上 开学典礼 下 python基础 Python入门 预习视频 python基础 对象与变量 预习视频 python基础 字符
  • Visio里Mathtype公式变形问题解决

    直接从word或者ppt复制MathType公式到Visio里可能会发生公式的变形 查找了一下解决办法 记录一下 建议不要只要从其他office软件直接复制过来 第一步 找到Visio工具栏的插入 然后选择对象 双击插入就可以了 后面的其他
  • QT5背景图片不显示的问题解决方法

    将qt creator左栏的项目 gt 概要 gt shadow build里的勾去除 使生成的debug文件放在源代码目录下 问题就解决了 更多绿色版本软件及机器视觉学习资料 请关注关注公众号 机器视觉智能解决方案
  • 5. 模块化编程

    HI 大家好 我是茶桁 上一节中我们学习了Python基本的流程控制 并且预告了这一节的内容 就是将要学习 模块化编程 那什么是模块化编程呢 按照维基百科的说法 模块化编程 英语 modular programming 是强调将计算机程序的