首页 > 其他分享 >参数,名称空间,作用域

参数,名称空间,作用域

时间:2024-04-14 22:02:32浏览次数:21  
标签:name 作用域 age list num 参数 名称 print

1 函数的调用方式

【1】直接调用

函数名()-->调用函数

def student(name, age):
    print(f"my name is {name} , my age is {age}")

# 函数名()-->调用函数
student(name="silence", age=16)
# my name is silence , my age is 16

【2】用表达式调用函数

用一个新变量存储函数的内存地址然后调用

def add(x, y):
    return x + y

result = add(2, 5)+ 9
print(result)  # 16

【3】函数作为返回值

def add(x, y):
    return x+y

def delete(a,b):
    return add(a, b)

print(delete(6,9)) # 15

【4】函数可以作为一个参数传递给另一个函数

def login(func):
    return func()
login(add())   # 相当于return中进入的是add()

2 函数的参数

【1】形参

  • 形参就是在函数定义阶段定义在函数名后面的()里的参数

  • 需要在函数调用的时候传递进去并且这个参数只在当前函数内部生效

【2】实参

  • 实参就是再调用函数的时候传递进去的那个真实的值
  • 可以按照位置和按照关键字传递参数
  • 实参可以是表达式,常量,变量
  • 表达式的意思就是表达式 1+1 1 x+y x/y

(1)按位置传参数

  • 有位置参数但是不传,参数不够,就会报错提示缺少必要的位置参数
  • 没有位置但是多传了,参数够了,但是给多了,提示只需要指定数量参数位置,但是给多了
  • 位置参数必须按照位置传递值,如果换位置就会导致函数内的参数错乱

(2)按照关键字传参数

  • 关键字传递参数的时候,要指定上函数定义时的位置参数名
  • 允许按照位置传递参数,并且指定上关键字
  • 允许不按照位置传递参数,指定上关键字

(3)位置参数和关键字参数连用

要传递的位置参数一定要在关键字参数之前否则会报错

def student(name, age, gender):
    print(f"my name is {name} and my age is {age} and my gender is {gender}")

student('silence',age=16,gender='male')  
# my name is silence and my age is 16 and my gender is male
student('silence',gender='male',age=16)
# my name is silence and my age is 16 and my gender is male

# 错误示例如下
#位置参数必须在关键字参数之前
student(age=18,'silence',gender='male')
# positional argument follows keyword argument

【3】默认参数

  • 在函数定义阶段的时候定义在函数名后面的 () 里面的参数可以给默认值
  • 位置参数给了默认值之后,在函数调用时,可以不指定默认参数的值,不给值默认就是默认值,给了新值就会被新值覆盖掉
def student(name, gender='male'):
    print(f' my name is {name} my gender is {gender}')

##给了name但是没给 gender , gender使用的就是默认的值 male
student('silence')   # my name is silence my gender is male
# 新值覆盖掉默认值
student('silence',gender='other')
my name is silence my gender is other

扩展内容:

# num_list 可变数据类型 ---> 定义一次下一次修改列表会影响到原来列表
def app_list(num, num_list=[]):
    num_list.append(num)
    print(num_list)
app_list(1)
app_list(2)
app_list(3)
# [1,2,3]  逐个进入循环后原来的会输出再将后续的也添加进来 所以最后是输出[1,2,3]


# num_list 每一次调用函数都是一个新的列表所以值只会是最后一个
def app_list(num):
    num_list = []
    num_list.append(num)
    print(num_list)
app_list(1)
app_list(2)
app_list(3) # [3] num_list 每一次调用函数都是一个新的列表,所以最后只有[3]


num_list = []
def app_list(num):
    num_list = []
    num_list.append(num)
app_list(1)
app_list(2)
app_list(3)
print(num_list)  # []  这个是输出外部的num_list  修改局部不会影响整体


#若要修改整体的
num_list = []
def app_list(num):
    global num_list
    num_list = []
    num_list.append(num)
app_list(1)
app_list(2)
app_list(3)
print(num_list)  # [3]

【4】可变长位置参数

可变长位置参数接收到多余的位置参数放到一个元组中

(1)什么是可变长位置参数

可变长位置参数 ,就是可以用一个变量来接收所有超出指定参数的位参数

在函数定义的时候在形参的位置增加 *args 用来接收多余的位置参数

args 默认的属性 但是是可以自己指定的

def student(name, age, gender='male', *pppp):
    print(name)
    print(age)
    print(gender)
    print(pppp)


student('silence', 18, 'male', 741, 159, 753)

# silence
# 18
# male
# (741, 159, 753)   *args 用来接收多余的位置参数


num_list = [1,2,3,4,5,6,7,8,9,10]
print(*num_list) 
# 1 2 3 4 5 6 7 8 9 10 在列表里会解出来一个个元素

解包:* + 可迭代类型 就能将每一个元素单独解包出来

# 解包语法:只能用在元组,列表等可迭代对象
# * + 可迭代类型 就能将每一个元素单独解包出来
def student(name, age, gender='male', *pppp):
    print(name)
    print(age)
    print(gender)
    print(pppp)

num_list = [1,2,3,4,5,6,7,8,9,10]

student('silence', 18, 'male', num_list)
# ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10],)
student('silence', 18, 'male', *num_list)
# (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

【5】可变长关键字参数

语法:*** + kwargs*

可变长关键字参数接收到多余的关键字参数放到一个字典中

def student(name, age, gender, *args, **kwargs):
    print(name, age, gender)
    print(f'args :>>>> {args}')
    print(f'kwargs :>>>> {kwargs}')


student('silence', 16, 'male', 888, 666, class_id=2, addr='上海')

# silence 16 male
# args :>>>> (888, 666)
# kwargs :>>>> {'class_id': 2, 'addr': '上海'}

解包: 字典支持 * 解包 ,解包后得到的结果是 字典的每一个键

字典不支持 ** 解包

user_data = {'username': "silence", 'password': "741"}
print(*user_data) # username password
print(**user_data) 
# 报错'username' is an invalid keyword argument for print()

【6】命名关键字参数

def student(name, age, gender,*, class_id, addr):
    # * 前可以根据位置参数  后面必须根据关键字符给
    print(name, age, gender, class_id, addr)
# 调用上面的函数传递参数可以按照关键字传递参数
# 也可以按照位置传递参数
# *后面必须根据关键字符给
student('silence', 16, 'male',class_id= 2, addr='上海')
# silence 16 male 2 上海

# 在位置参数中间指定 * 隔开,
# * 之前的位置参数支持位置和关键字传参数
# * 后面的参数必须按照关键字传参数
# 在命名关键字参数中指定默认参数的时候,默认参数允许放在位置参数之前
# 但是普通的位置参数是不允许关键字参数放在位置参数之前的

def student(name, age, gender='male',*, class_id=2, addr):
    print(name, age, gender, class_id, addr)
student('silence', 16, 'male',class_id= 2, addr='上海')
#但是用来命名关键字参数 是允许上面存在的

【7】混合使用

  • 所有参数可任意组合使用,但定义顺序必须是:
    • 位置参数、默认参数、*args ,**kwargs
  • 所有位置参数、默认参数、*args ,**kwargs 混合使用的时候不允许使用关键字参数
  • 所有位置参数、默认参数、*args ,**kwargs
    • **kwargs 必须在 *args 之后

类型提示

【1】什么是注解

定义函数的位置参数的时候可以指定参数的类型

【2】基本数据类型的注解

(1)可变数据类型

  • 字典, 列表, 元组, 集合
from typing import Dict, List,Tuple,Set

def student(user_data: Dict[str, int], id_list: List[int],num_tuple:Tuple[str],num_set:Set[int]):
    print(user_data, type(user_data))
student({'age': 18}, [1],('1',),{2,3})

(2)不可变数据类型

  • 字符串, 整数,浮点数,布尔

弱类型约束:建议你按照我指定的传,但是你不按照我的传也可以

def student(name: str, age: int, score: float, is_male: bool):
    print(name, type(name)) # silence <class 'str'>
    print(age, type(age))    # 16 <class 'int'>
    print(score, type(score))   # 124.8 <class 'float'>
    print(is_male, type(is_male))   # True <class 'bool'>
student('silence', 16, 124.8, True)   

【3】约定函数的返回值类型

def add(x:int,y:int)->int:
    return x + y

print(add(1,2)) # 3


def add(x:str,y:str)->str:
    return x + y

print(add('1','2'))  # 12

【4】函数返回值既可以是字符串也可以是数字

  • union 既可以返回一个又可以返回另一个类型
def add(x: int, y: int) -> Union[str, int]:
    return x + y
    return str(x + y)

print(add(1, 2),type(add(1, 2))) # 3 <class 'int'>
print(add(1, 2),type(add(1, 2)))  # 3 <class 'str'>

【5】可以返回可选的参数类型

from typing import Optional
def add(x: int, y: int) ->Optional[None]:
    return 1
print(add(1,2))  # 1

名称空间

【1】什么是名称空间

  • 名称空间就是存放函数名与函数值对应关系的地方

  • 变量名 = 变量值

  • 内存空间:开辟一块内存空间,把函数值扔到内存空间

  • 名称空间:变量名和变量值进行绑定

【2】名称空间的分类

(1)内建名称空间

python解释器自带的名称空间,打开时第一个加载的名称空间,随着代码启动生成,结束而关闭

  • 例如: if else def

(2)全局名称空间

随着内建名称空间加载完成,走到了你自己写的代码里面

  • 例如:自己创建的变量名 / 函数名 / 类名
# 这个列表是全局的列表
# 列表是可变数据类型 ---> 列表被修改后id不变
num_list = []
print(id(num_list)) # 2865103328448
def add_list(num):
    num_list.append(num)
    print(id(num_list)) # 2865103328448
add_list(1)
add_list(2)
add_list(3)
print(num_list) # [1, 2, 3]
print(id(num_list)) # 2865103328448

(3)局部名称空间

在函数内部或者是类内部定义的变量,随着函数启动而创建,随着函数结束而消失

num_list = []  # 这个列表是全局的列表
def add_list(num):
    num_list.append(num)
    print(num_list)
    print(id(num_list))
    # 1695055893696  列表是可变数据类型 ---> 列表被修改后id不变
add_list(1)  # [1]
add_list(2)  # [1,2]
add_list(3)  # [1,2,3]


def add_list(num): #这个列表是局部的列表
    # 垃圾回收机制 ---> 节省内存开销
    num_list = []  # 每次进来就是一个空列表
    num_list.append(num)
    print(num_list)
    print(id(num_list)) # 1586648339648
add_list(1) # [1]
add_list(2) # [2]
add_list(3) # [3]

【3】名称空间的加载顺序

  • 先加载内建名称空间
    • 其次是全局名称空间
      • 最后就是局部名称空间

【4】变量的查找顺序

所有的变量 尤其是 可变数据类型 字典 列表,尽量写在文件开头 , 如果放在函数下面可能会导致检索不到变量

全局查

  • 先全局后内建 --> 在 py 文件中执行代码

局部查

  • 先局部再全局再内建 ---> 在函数内部执行代码

作用域

【1】什么是作用域

变量的作用域

Python是静态作用域,也就是说Python中,变量的作用域源于它在代码中的位置

在不同的位置,可能有不同的命名空间。命名空间是变量作用域的体现形式

【2】默认知识

名称空间 ---> 分为内建 局部 全局

存放变量名和变量值关系的地方 ---> 内存中 / 硬盘中

【3】四种作用域

(1)内置作用域

python解释器自带的作用域

(2)全局作用域

全局名称空间

(3)局部作用域

在函数内部或者是类似内部的名称空间

a = 1
def func():
    b = 2
   
print(a) # a
print(b) # 报错   原因:全局作用域没办法使用局部变量

(4)嵌套作用域

在函数内部的函数的名称空间

# 局部能用全局 , 全局用不了局部
a = 1
def func():
    b = 2
    def inner():
        c = 3
        print(c) # 3
        print(b) # 2
        print(a) # 1
    print(c) # 报错

print(a) # 1
print(b) # 报错
print(c) # 报错

【4】局部修改全局变量

# 错误示例
name = 'silence'
def func():
    name = 'happy'
    print(name)   # happy
func()
print(name) # silence

# 在局部修改全局的变量
name = 'silence'
def func():
    # 在局部修改全局的变量
    # 使用关键字 global 在局部将局部变量的等级提升为全局
    #一般都是用在不可变数据类型身上
    global name
    name = 'happy'
    print(name)  # happy
func()
print(name)  # happy


【5】在内嵌函数中修改外部函数的变量

 # 错误示例
    age = 18
    def inner():
        global age
        age = 19
        print(age)# 19
    inner()
    print(age)  # 18
func()

#在内嵌函数中修改外部函数的变量值不能使用 global,要用nonlocal
    age = 18
    #在内嵌函数中修改外部函数的变量值不能使用 global
    # 要使用nonlocal 来提升内嵌函数的变量的等级到外部
    def inner():
        nonlocal age
        age = 19
        print(age)

    inner()
    print(age)
func()

【6】LEGB规则

(1)作用域的加载顺序

作用域加载顺序是由外而内

  • B : built in : 内置变量
  • G : global : 全局变量
  • L : locals() 局部变量
  • E : enclose function locals : 内嵌变量

(2)作用域的查找顺序

作用域查找顺序是由内而外

  • E : enclose function locals : 内嵌变量
  • L : locals() 局部变量
  • G : global : 全局变量
  • B : built in : 内置变量

【6】locals()和globals() 区别

locals 打印的是局部名称空间,globals 打印的是全局的名称空间

a = 1
def outer():
    b = 2
    # locals 打印的是局部名称空间
    print('outer', locals())
    print('outer', locals().get('b'))
    print('outer', locals().get('a'))
    # globals 打印的是全局的名称空间
    print('outer', globals())
    print('outer', globals().get('a'))

    def inner():
        c = 3
        print('inner', locals())
        print('inner', globals())
    inner()
print(locals())
print(globals())
outer()

标签:name,作用域,age,list,num,参数,名称,print
From: https://www.cnblogs.com/zyb123/p/18134766

相关文章

  • 13-axios 传递参数的方式(data 与 params 的区别)
    Axios官方网址:起步|Axios中文文档|Axios中文网(axios-http.cn)参考文章:axios传递参数的方式(data与params的区别)-知乎(zhihu.com) Axiosa大家都非常的清楚,一个既可以用于客户端或者 服务端发送http请求的库。但是在前后端联调的时候有的时候会很难受,所以这里我......
  • 实现自定义注解校验方法参数(AOP+自定义注解+自定义异常+全局异常捕获)
    一、实现目的在编写接口的时候,通常会先对参数进行一次校验,这样业务逻辑代码就略显冗杂,如果可以把校验参数的代码进行统一管理,在方法或者属性上直接添加注解就可以实现参数的校验,就可以提升代码编写的效率。二、实现原理通过自定义注解,注解在入参VO的属性上,设定需要满足的条件,然......
  • 项目中统一处理请求中的字符串参数的空格
    测试controller@RestController@RequestMapping("/test")@Slf4jpublicclassTestController{@GetMapping("/testStringParamTrim")publicTestObjectInfotestStringParamTrim(@RequestParamStringgoodsId,StringgoodsName){......
  • 在Linux中,如何编写脚本处理命令行参数?
    在Linux中,编写脚本处理命令行参数是编写shell脚本的基本功之一。命令行参数是用户在执行脚本时附加在命令行上的额外信息,这对于增加脚本的灵活性和复用性至关重要。以下是如何在bashshell脚本中处理命令行参数的几种常见方法:1.位置参数bash提供了一系列特殊变量$0至$9用于......
  • 关于C++作用域符的一种用法
    当作用域符号::前不带类名,或者namespace名的时候,表示是全局作用域的意思,也就是表示所调用的函数是全局函数,或者是某个动态库的函数,这对与代码的可阅读性有很大的帮助,因为它与类型成员函数的调用做了区分,表明该函数不是类成员函数如下图的send()函数,其前面的::表明send()函数不是......
  • LTE网优多频网互操作参数汇聚(中兴)
    欢迎不吝资助和交流--coding:utf-8--importosimportopenpyxlimporttimedefmeasGroup(g):measGrou={}forlineinrange(6,ws.max_row+1):c_value=ws.cell(row=line,column=2).valued_value=ws.cell(row=line,column=3).valuee_value=ws.cell(row=......
  • Jmeter模拟用户并发token参数化
    场景:项目需求,模拟用户并发签到,要求签到数据能记录到数据库。分析:签到接口需要tocken,单个tocken只能签到一次,需要多个tocken一起并发。脚本如下:        解决返回的乱码问题。  ......
  • python基础-函数(函数参数、返回值、执行、传参、作用域、函数名)
    前言!!!注意:本系列所写的文章全部是学习笔记,来自于观看视频的笔记记录,防止丢失。观看的视频笔记来自于:哔哩哔哩武沛齐老师的视频:2022Python的web开发(完整版)入门全套教程,零基础入门到项目实战1.初识函数函数就是一大堆代码的集合,这一堆的代码再起个名字。#定义函数def函数名......
  • java中字符串替换的4种方法 replaceAll() 带正则表达式参数 str.replaceAll("[0-9]+
    java中字符串替换的4种方法replaceAll()带正则表达式参数str.replaceAll("[0-9]+","");目录前言一、String的replace()方法二、String的replaceAll()方法三、StringBuffer/StringBuilder的replace()方法四、Matcher的replaceAll()方法总结前言在日常开发中,我们对......
  • Robocopy是Windows操作系统中的一个命令行实用工具,用于在文件和目录之间进行复制。它
    robocopy/?-------------------------------------------------------------------------------  ROBOCOPY  ::  Windows的可靠文件复制------------------------------------------------------------------------------- 开始时间:2024年4月11日16:33:......