函数

函数:

1.函数返回return的作用有两点:

    1、把函数处理的结果返回

    2、结束函数,函数里面遇到return,函数立即结束

2.全局变量:

  python里分两种数据类型:可变类型和不可变类型

  如果改变了变量的值,相当于是新建了一个对象,而对于相同的值的对象,在内存中则只有一个对象,内部会有一个引用计数来记录有多少个变量引用这个对象变数据类型,允许变量的值发生变化,即如果对变量进行append、+=等这种操作后,只是改变了变量的值,而不会新建一个对象,变量引用的对象的地址也不会变化,不过对于相同的值的不同对象,在内存中则会存在不同的对象,即每个对象都有自己的地址,相当于内存中对于同值的对象保存了多份,这里不存在引用计数,是实实在在的对象。

  可变类型(值可以修改):

    列表list

    字典dict

  不可变类型(值不允许修改):

    数值类型int,long,bool,float

    字符串str

    元组tuple 

  可变类型表示修改值后id不会发生变化,都是一个标签,一改都改;不可变类型则修改值后id也变了,换了一个引用,是不同的标签不同的变量函数里如果对可变类型修改,则在函数外面这个变量值也会变化,不可变类型则在函数外面不会发生变化(类似内部变量不影响外部变量)
 

  全局变量
  #list、字典、集合,不需要声明global
  #字符串、数值类型、元组 需要声明global

 

def test():
    global a
    a = 5
    print(id(a))
    a = 6
    print(id(a))

def test1():
    c= a + 5
    return c
test()
res = test1()
print(res)

 运行结果:

1523215552
1523215584
11

  因为是不可变类型,所以定义了全局变量后,当a值重新赋值6的时候,id也发生了变化,不是对同一个id的变量进行修改

a=5
def test():
    global a
    print(id(a))
    a=a+5
    print(id(a))
    return a


res = test()
print(res)
print(a,id(a))

  运行结果:

1523215552
1523215712
10
10 1523215712

  

a是不可变类型的全局变量,当test声明引用全局时,之后a=a+5,右边的a是id 1523215552,左边由于不可变原因,所以新生成了一个全局的引用id 1523215712,值为11,此时有两个全局变量a(id不同),值也不同,一个为5,一个为11。注意的是gloable不声明的话,a会当成一个未定义的局部变量报错!

同理:

def test():
    global a
    a = 5
    print(id(a))
    a = 6
    print(id(a))

def test1():
    global a
    print(id(a))
    a= a + 5
    print(id(a))
    return a

test()
res = test1()
print(res)
print(a,id(a))

  运行结果:

1523215552
1523215584
1523215584
1523215744
11
11 1523215744

  

3.浅拷贝与深拷贝:

  浅拷贝:两个变量指向的是同一块内存地址(id)

  深拷贝:是会开辟一个新的内存,存放数据,就是两块不同内存(id)。

比较两段代码及结果:

import copy
     #0 1 2
num1 = [1,1,2,3,4,5,6,7,7,8]
num2 = num1 #浅拷贝
print(id(num1))
print(id(num2))
for i in num2:
    if i%2!=0:
        num1.remove(i)
print(num1)

  运行结果

2412905492616
2412905492616
[1, 2, 4, 6, 7, 8]

  

import copy
     #0 1 2
num1 = [1,1,2,3,4,5,6,7,7,8]
num2 = copy.deepcopy(num1)#深拷贝 num2=num1[:]也属于深拷贝
print(id(num1))
print(id(num2))
for i in num2:
    if i%2!=0:
        num1.remove(i)
print(num1)

  运行结果

1872643092616
1872643092744
[2, 4, 6, 8]

  

循环删除一个列表会有一个错位问题:因为在循环num1,并删除num1的元素时,列表的位置发生了移位,当删除“1”后,第二个元素“1”补位,这样第二个“1”就躲过了被删除的命运被留了下来,列表是通过下标循环,读过的下标就不会再读,轮到“2”了,“2”被删除之后,“3”来补位,以此类推!!

 

4.函数可变参数

当函数定义的时候有多个参数,则在函数调用的时候要注意传入参数的顺序

1 def mysql(host,user,password,port,charset,sql,db):
2     print('连接mysql')

  例如上述代码的参数有7个,则以下传入的顺序都是正确的

1 mysql('ip','user','sdfsdf',3306,'sdfsdf','select','db')
2 mysql(user='root',password='123456',host='192.168.1.3',port=3306,sql='sdfsdf',db='sdfsdf',charset='sdfsdf')
3 mysql('192.168.1.1','root',port=3306,password='sdfsdf')

  但是下述方式不正确,因为在函数定义的时候,参数的顺序是固定好的,如果传值得时候严格按照顺序传入而不带形参,python是可以识别的,如果打乱顺序指定形参传值,之后的形参就不能省略了

mysql(password='123456','root',...,) 

  

5.可变参数:*args  **args

如果一个函数定义时发现需要传入的参数的个数是不确定的,则应该使用可变参数*arg,在函数调动的时候,python会将入参打包成元组的形式传给被调函数

 

def mysql2(ip,*info):
    print(info)

  *info前可以带指定的参数,但是ip不能定义在*info后,因为如果是*info ip则python不知道传入的参数哪些是打包在*info内

1 def send_mail(*args):
2     print(args)
3 
4 send_mail('qqq@qq.com')
5 send_mail('qqq@qq.com','asaaa@163.com','ddd@sina.com')

  

 

('qqq@qq.com',)
('qqq@qq.com', 'asaaa@163.com', 'ddd@sina.com')

  除了以上的元组形式,python还支持dict形式的参数传入,需要用**args

def mysql(**mysql_info):
    print(mysql_info)

dic = {
    'host':'192.168.1.1',
    'user':'root',
    'password':123456,
    'port':3306,
    'charset':'utf-8',
    'sql':'sql',
    'db':'db'
}
mysql(**dic)

  

{'host': '192.168.1.1', 'user': 'root', 'password': 123456, 'port': 3306, 'charset': 'utf-8', 'sql': 'sql', 'db': 'db'}

  

posted on 2019-06-03 18:14  彬小彬  阅读(114)  评论(0编辑  收藏  举报

导航