python基础(7)--深浅拷贝、函数

1.深浅拷贝

  在Python中将一个变量的值传递给另外一个变量通常有三种:赋值、浅拷贝、深拷贝

  Python数据类型可氛围基本数据类型包括整型、字符串、布尔及None等,还有一种由基本数据类型作为最基本的元素所组成的像列表、元组、字典等。

  在Python中基本数据类型的赋值、深浅拷贝没有任何意义,都是指向同一块内存地址,也不存在层次问题。

  下面看基本数据类型的深浅拷贝

import copy
n1 = ‘abc‘
n2 = n1
n3 = copy.copy(n1)
n4 = copy.deepcopy(n1)
print(id(n1))    #输出140350336680040
print(id(n2))    #输出140350336680040
print(id(n3))    #输出140350336680040
print(id(n4))    #输出140350336680040

  以上代码说明Python的copy模块的copy和deepcopy函数实现了浅拷贝和深拷贝,可以看到,赋值、浅拷贝和深拷贝最后的id(Python内存地址的表达方式)都是一样的

  接下来讨论其他的列表、元组、字典等非基本数据类型对象的赋值、深浅拷贝的区别

  假设字典n1 = {"k1": "abc", "k2": 123, "k3": ["abc", 123]}

  赋值是将变量的内存赋给另一个变量,让另一个变量指向那个内存地址

  浅拷贝

  浅拷贝就是在内存中将第一层额外开辟空间进行存放

n1 = {"k1": "abc", "k2": 123, "k3": ["abc", 123]}
print(id(n1))    #140350328984328
n3 = copy.copy(n1)
print(id(n3))    #140350328986504可以看n3的内存地址已经和n1不同了

print(id(n1[‘k3‘]))    #140350328603976
print(id(n3[‘k3‘]))    #140350328603976 字典里的列表还是指向同一个列表

  深拷贝

  深拷贝就是在内存中将数据重新创建一份,不仅仅是第一层,第二层、第三层...都会重新创建

n1 = {"k1": "abc", "k2": 123, "k3": ["abc", 123]}
print(id(n1))    #140350328984328
n3 = copy.deepcopy(n1)

print(id(n1[‘k3‘]))    #140350328603976
print(id(n3[‘k3‘]))    #140350328604296 #可以看到第二层的列表也拷贝了一份,内存地址已经完全不一样

#注意,这仅局限于非基本数据类型,基本数据类型还是同一个内存地址

2.函数

  函数的定义及调用

  定义一个函数要使用def关键字,依次写出函数名、括号、括号中的参数和冒号:,然后用缩进的代码块写函数体,函数体内可以调用return语句返回结果。

  函数名作为函数的名称,也可以像变量一样进行赋值操作、甚至作为参数进行传递。

  

  函数的参数

  1)位置参数

  这是最常见的定义方式,一个函数可以定义任意个参数,每个参数用逗号分隔,例如:

def Foo1(arg1, arg2):
    print(arg1, arg2)

  用这种方式定义的函数在调用的的时候也必须在函数名后的小括号里提供个数相等的值(实际参数),而且顺序必须相同,也就是说在这种调用中,形参和实参的个数必须一致,而且必须一一对应,也就是说第一个形参对应这第一个实参。例如:

Foo1(‘abc‘, 123)#输出结果 abc 123

  也可以通过如下方式传递参数,而不必考虑顺序问题,但数量无论如何必须一致。

foo3(arg2 = 123, arg1 = ‘abc‘)

  2)默认参数

  我们可以给某个参数指定一个默认值,当调用时,如果没有指定那个参数,那个参数就等于默认值

def Foo2(arg1, arg2 = 123):
     print(arg1, arg2)

  调用

Foo2(‘abc‘)
Foo2(‘abc‘, 345)

‘‘‘
执行结果
    abc 123
    abc 345
注意:定义的时候默认参数必须放到所有位置参数的后面进行定义,否则会报语法错误
‘‘‘

  

  3)可变参数

  可变参数就是传入的参数个数是可变的,也可以是0个,例如

def Foo3(*args):
     print(args)

  调用

Foo3(1, 2, ‘abc‘)

#执行结果  (1, 2, ‘abc‘)  可以看到我们传递了三个参数都被Python转化为元祖,保存到args中了,这样我们就可以通过索引对参数记性调用,或者通过for in进行遍历

  

  4)关键字参数

  可变参数在调用过程中会组装成元组,元组只能通过索引进行调用,有时不是很方便,故Python可以通过关键字索引将传入的参数组装成字典

  

def Foo4(**kwargs):
    print(kwargs, type(kwargs))

Foo4(k1 = ‘abc‘, k2 = 123)

#执行结果 {‘k2‘: 123, ‘k1‘: ‘abc‘} <class ‘dict‘>
#关键字参数允许传入0个或任意个参数名的参数,0个的话就是一个空字典

  参数组合

  在Python中定义函数,可以用必选参数(位置参数)、默认参数、可变参数、关键字参数这几种参数进行组合使用,但是顺序必须是,必选参数、默认参数、可变参数、关键字参数。

def Foo5(arg1, arg2=‘abc‘, *args, **kwargs):
    print(‘arg1:‘, arg1)
    print(‘arg2:‘, arg2)
    print(‘args‘, args)
    print(‘kwargs‘, kwargs)

Foo5(123, ‘abc‘, 456, ‘def‘, k1=123, k2=‘abc‘)

‘‘‘
执行结果
arg1: 123
arg2: abc
args (456, ‘def‘)
kwargs {‘k1‘: 123, ‘k2‘: ‘abc‘}

‘‘‘

  lambda匿名函数

  匿名函数就是功能非常简单只需要一行代码就可以实现的,例如,求圆形面积

f = lambda r: 3.14 * r * r
print(f(4)) # 输出 50.24

#r相当于匿名函数的参数,当然也可以有多个参数,不用在写return,表达式就是返回的结果。

  使用匿名函数有个好处,因为函数没有名字,不用担心函数名冲突,此外匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量,再利用变量调用该函数。

  

  关于函数的return语句

  1)函数可以没有return语句,没有就默认返回None

  2)return语句有点类似循环的break,当函数执行到return语句时候,直接跳出函数的执行

  3)return可以返回多个值,多个值可以用两个变量接收,也可以额一个变量接收

def Foo6():
    return 123, ‘abc‘

res1, res2 =Foo6()
print(‘res1:‘, res1)    #res1: 123
print(‘res2:‘, res2)    #res2: abc

res = Foo6()
print(‘res:‘, res)  #res: (123, ‘abc‘)

#返回多个值就是返回一个元组,使用两个变量接收的时候回将元组的元素与变量一一对应赋给多个变量

  关于可变参数和关键字参数的传递小技巧

  我们已经知道可变参数和关键字参数分别将传递的参数组装成元组和字典,那么我们同样可以直接将元组、列表和字典直接传递给函数作为参数,传递的时候列表和元组要在变量前面加一个*,字典要在前面加两个*,否则函数还是会把它们当成一个普通的参数传递进行处理

def Foo7(*args, **kwargs):
    print(args)
    print(kwargs)

li = [1, 2, 3]
dic = {‘k‘:1, ‘k2‘:2}
Foo7(li, dic)
Foo7(*li, **dic)

‘‘‘
执行结果
([1, 2, 3], {‘k‘: 1, ‘k2‘: 2})
{}    #可以看到两个参数都被可变参数接收了,关键字参数啥也没有
(1, 2, 3)
{‘k‘: 1, ‘k2‘: 2}

‘‘‘

  Python常用的内置函数

  只重点关注标记的内置函数

print(abs(-10))

#输出10

abs 返回绝对值

print(all([1, True, 1 == 1]))

#True

all 可迭代对象(列表、元祖等)中所有的元素都是True,则返回True,否则返回False。相当于and

print(any([None, "", [], (), {}, 0, False])) #False

print(any([None, "", [], (), {}, 0, True]) )#True

#通常情况下“空”(None,空字符串、空列表,0等等)都是表示False

any 相当于or

print(bin(10))

#‘0b1010‘

bin 整数转换二进制字符串

print(bool())  #False

print(bool(10))  #True

class bool 返回或者新建一个布尔值

print(chr(89999))    #‘\U00015f8f‘

print(chr(97))    #‘a‘

chr 整数转成unicode编码所对应的字节

print(dict())    #{}

print(dict(k1 = ‘v1‘, k2 = ‘v2‘))    #{‘k1‘: ‘v1‘, ‘k2‘: ‘v2‘}

print(dict(([‘k1‘, ‘v1‘], [‘k2‘, ‘v2‘])))    #{‘k1‘: ‘v1‘, ‘k2‘: ‘v2‘}

print(dict({‘k1‘:‘v1‘, ‘k2‘:‘v2‘}))    #{‘k1‘: ‘v1‘, ‘k2‘: ‘v2‘}

dict 创建字典对象

print(dir(""))

#[‘__add__‘, ‘__class__‘, ‘__contains__‘, ‘__delattr__‘, ‘__dir__‘, ‘__doc__‘, ‘__eq__‘, ‘__format__‘, ‘__ge__‘, ‘__getattribute__‘, ‘__getitem__‘, ‘__getnewargs__‘, ‘__gt__‘, ‘__hash__‘, ‘__init__‘, ‘__iter__‘, ‘__le__‘, ‘__len__‘, ‘__lt__‘, ‘__mod__‘, ‘__mul__‘, ‘__ne__‘, ‘__new__‘, ‘__reduce__‘, ‘__reduce_ex__‘, ‘__repr__‘, ‘__rmod__‘, ‘__rmul__‘, ‘__setattr__‘, ‘__sizeof__‘, ‘__str__‘, ‘__subclasshook__‘, ‘capitalize‘, ‘casefold‘, ‘center‘, ‘count‘, ‘encode‘, ‘endswith‘, ‘expandtabs‘, ‘find‘, ‘format‘, ‘format_map‘, ‘index‘, ‘isalnum‘, ‘isalpha‘, ‘isdecimal‘, ‘isdigit‘, ‘isidentifier‘, ‘islower‘, ‘isnumeric‘, ‘isprintable‘, ‘isspace‘, ‘istitle‘, ‘isupper‘, ‘join‘, ‘ljust‘, ‘lower‘, ‘lstrip‘, ‘maketrans‘, ‘partition‘, ‘replace‘, ‘rfind‘, ‘rindex‘, ‘rjust‘, ‘rpartition‘, ‘rsplit‘, ‘rstrip‘, ‘split‘, ‘splitlines‘, ‘startswith‘, ‘strip‘, ‘swapcase‘, ‘title‘, ‘translate‘, ‘upper‘, ‘zfill‘]

dir 查看所有变量名和方法名

print(divmod(10, 3))

#(3, 1)    返回两个数的得商和余数组成的元组,相当于(a // b, a % b)

divmod返回两个数的得商和余数组成的元组

enu = enumerate([‘abc‘, ‘def‘, ‘ghi‘])
print(enu)
for i in enu
    print(i)

‘‘‘
返回一个迭代器,每次迭代返回一个元组包括一个计数器,和对iterable迭代取得的值,iterable可迭代对象,包括列表、元祖等。start表示计数器的开始值,默认是0
执行结果
<enumerate object at 0x0000000BE2D53510> # 可以看到返回的是一个enumerate对象
(0, ‘abc‘)
(1, ‘def‘)
(2, ‘ghi‘)
‘‘‘

#注意:返回的是是一个迭代器,迭代完了空了,如果需要重复使用,最好转化为一个列表对象保存到变量中,并且计数器是从0开始计数的
li = list(enumerate([‘abc‘, ‘def‘, ‘ghi‘]))
print(li)     #[(0, ‘abc‘), (1, ‘def‘), (2, ‘ghi‘)]

#还可以指定start的开始值
li = list(enumerate([‘abc‘, ‘def‘, ‘ghi‘], 2))
print(li)    #[(2, ‘abc‘), (3, ‘def‘), (4, ‘ghi‘)]

enumerate(iterable, start=0)

print(eval(‘3 + 4 * (1 - 3)‘))   #-5

#将的字符串形式的算数表达式进行计算,并返回结果

eval(expression, globals=None, locals=None)

def func(num):
    if num % 2 ==0:
        return True
    else:
        return False

nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

print(list(filter(func, nums)))

‘‘‘
接收一个函数和一个可迭代对象,将可迭代对象的每一个元素都作为参数执行函数,函数返回为真的放到一个新的可迭代对象中,并将新的可迭代对象返回

执行结果
[2, 4, 6, 8, 10, 12, 14, 16, 18]
‘‘‘

filter(function, iterable)

print(‘0.5‘)    #0.5

print(0.5)    #0.5

#创建一个浮点类型的对象

class float([x])

#返回某个对象的帮助信息

help([object])

print(hex(23))    #‘0x17‘

#返回一个整数的16进制表达式

hex(x)

print(id(1))    #10455040
#返回对象的id(可以理解为Python为每个对象的编号,或者理解为是Python对象内存地址的表达形式)

id(object)

s = input(‘python>>‘)

print(s)

‘‘‘
输入123
输出‘123‘

接受用户从控制台的输入,并将用户输入的信息,以字符串的返回,prompt表示输入时前显示的字符串
‘‘‘

input([prompt])

print(int())    #0

print(int(‘1010‘, base=2))    #10

#创建一个整数类型的对象,默认如果创建的0,如果传递的是字符串类型的,可以把字符串表达式所表示的整数转化为整数类型,base表示的传递的字符串进制,默认是十进制

class int(x=0)

print(len(‘abc‘))    #3

#返回一个对象的长度(或者元素的个数)
#所谓的长度一般只字符串,像整数、浮点数等数据类型没有len方法

len(s)

print(list([1, 2, 3]))    #[1, 2, 3]
prnt(list({‘k1‘:‘v1‘, ‘k2‘:‘v2‘}))    #[‘k2‘, ‘k1‘]

#将一个可迭代对象转化为列表
#可以看到字典只是把key组成了列表,因为字典真正迭代的是key,value只是与key对应而已

class list([iterable])

s = map(lambda x: x**2, [1, 2, 3])
print(s)    #<map object at 0x0000000002D14CF8>

l = list(map(lambda x: x**2, [1, 2, 3]))
print(l)       #[1, 4, 9]

#接收一个函数和一个可迭代对象,将可迭代对象里的每一个元素都做作为参数传递到函数中,并把函数的返回结果保存到一个map对象中
#函数可以是匿名函数,另外函数必须有返回值,如果没有返回值,虽然不会报错,但没有任何意义,例如

map(function, iterable, ...)

print(max(1, 2, 3))    #3

‘‘‘
max(iterable, *[, key, default])
max(arg1, arg2, *args[, key])
返回可迭代对象中(或者2个以上参数中)最大的值

‘‘‘

max

print(min(1, 2, 3))    #1

‘‘‘
min(iterable, *[, key, default])
min(arg1, arg2, *args[, key])
返回可迭代对象中(或者2个以上参数中)最大的值
‘‘‘

min

print(oct(9))    #‘0o11‘

#将一个数转化为8进制的表达形式    Python中0o表示8进制

oct(x)

‘‘‘
    open(file, mode=‘r‘, buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)

  打开文件并返回文件文件对象,file表示文件名(可以是绝对路径,也可以是相对路径),mode表示打开方式,默认的是rt模式,表示只读的文本格式

‘‘‘

open

print(ord(‘a‘))    #97

#返回一个字符的Unicode编码

ord(c)

print(pow(2, 3)  )    #8

print(pow(2, 3, 3))    #2

#如果只传递两个参数x和y,就计算x的y次方,相当于x ** y
#参数z表示将x ** y的结果对z取模,相当于x ** y % z

pow(x,y[,z])

‘‘‘
    print(*objects, sep=‘ ‘, end=‘\n‘, file=sys.stdout, flush=False)

  打印函数,object表示要输出的对象,sep表示多个对象之间的分隔符,默认是空格,end表示末尾的字符,默认是回车符,file表示输出的文件,默认为sys.stdout也就是终端(标准输出)
‘‘‘

print

print(list(range(1, 10)))    #[1, 2, 3, 4, 5, 6, 7, 8, 9]

print(list(range(1, 10, 2)))    #[1, 3, 5, 7, 9]

print(list(range(5))    #[0, 1, 2, 3, 4]

‘‘‘
range(stop)
range(start, stop[, step])
生成大于等于start,小于stop步长为step的数字序列,start默认是0
‘‘‘

range

print(reversed([0, 1, 2, 3, 4]))    #<list_reverseiterator object at 0x7fcc954acd68>

print(list(reversed([0, 1, 2, 3, 4])))    #[4, 3, 2, 1, 0]

#翻转一个序列,序列对象必须是有序的,也就是对象必须包含__reversed__()方法

reversed(seq)

print(round(1.236, 2))    #1.24

print(round(1.2, 2))    #1.2

#返回一个浮点数的后面保留ndigits位小数的结果,四舍五入,小数点位数不足,不补0

round(number[, ndigits])

print(set(1, 2, 4, 2))    #{1, 2, 4}

#根据序列对象创建集合对象

class set([iterable])

print(sorted([‘A‘, ‘b‘, ‘c‘]))    #[‘A‘, ‘b‘, ‘c‘]

print(sorted([‘A‘, ‘b‘, ‘C‘]))    #[‘A‘, ‘C‘, ‘b‘]

print(sorted([‘A‘, ‘b‘, ‘C‘], key = lambda x: x.lower()))#[‘A‘, ‘b‘, ‘C‘]

print(sorted([‘A‘, ‘b‘, ‘C‘], key = lambda x: x.lower(), reverse = True))
#[‘C‘, ‘b‘, ‘A‘]

#对一个序列对象进行排序,key接收一个函数,将序列的每一个函数处理返回的结果作为排序的依据,比如字符串都转换成小写排序或字典按照key或value排序等,reverse表示对排序的结果是否排序,默认字符串是先大写后小写的顺序排序的

sorted(iterable[, key][, reverse])

print(str(‘abc‘))    #‘abc‘

print(str(1234))    #‘1234‘

#创建一个字符串对象,或者将一个对象转化为字符串对象

class str(object=‘‘)

print(sum([1, 2, 4]))    #7

print(sum([1, 2, 4], 1))    #8

#返回一个序列对象的相加的总和在加上start,start默认是0,序列对象要么全是数字要么都是字符串,字符串就相当于把它们都拼接在一起

sum(iterable[, start])

print(tuple())    #()

print(tuple([1, 2, 4]))    #(1, 2, 4)

#创建一个元组对象,或将一个对象转化为元组

tuple([iterable])

print(type(1))    #<class ‘int‘>

‘‘‘
class type(object)
class type(name, bases, dict)
返回一个对象的类型
‘‘‘

type

import sys

vars(sys)
#{‘version_info‘: sys.version_info(major=3, minor=4, micro=0, releaselevel=‘final‘, serial=0), ‘getswitchinterval‘: <built-in function getswitchinterval>, ‘__name__‘: ‘sys‘, ‘path_hooks‘: [<class ‘zipimport.zipimporter‘>, <function FileFinder.path_hook.<locals>.path_hook_for_FileFinder at 0x7fcc97b51ae8>],后面省略n多行

#返回模块,类,实例或者任何其他有__dict__属性的对象的__dict__属性,默认是显示当前环境的

vars([object])

x = [1, 2, 3, 4]
y = [‘a‘, ‘b‘, ‘c‘]
print(zip(x, y))    #<zip object at 0x7fcc954aea08>
print(list(zip(x, y)))    #[(1, ‘a‘), (2, ‘b‘), (3, ‘c‘)]

#将多个元素组成一个新的zip对象,zip对象的元素个数取决于元素最少的参数

zip(*iterables)

时间: 2024-11-05 22:39:37

python基础(7)--深浅拷贝、函数的相关文章

python基础(深浅拷贝)

本文主要介绍:深浅拷贝                                                                       注意:在python中有一种自己的优化机制,通常来说字符串在内存中的地址是不相同的,但是在python中,不管是深拷贝还是浅拷贝,只要是通过拷贝的字符串,两个地址是相同的 一.创建 1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 # author by lh 4 5 import

Python基础:深浅拷贝

对于数字.字符串深浅拷贝: import copy num = 0 copy_num = copy.copy(num) print("These are normal copy").center(60,'*') print(num,id(num)) print(copy_num,id(copy_num)) print("These are deep copy").center(60,'*') deep_copy_num = copy.deepcopy(num) pr

python基础,深浅拷贝

赋值 1 直接赋值(字典同理) lst1 = [1,2,3] lst2 = [1,2,3] print(id(lst1),id(lst2)) 结果:2426068165192 2426069393800 2 引用赋值(字典同理) lst2 = [1,2,3] lst3 = lst2 print(id(lst2),id(lst3)) lst3.append(4) print(lst2) print(lst3) 结果:1857178919496 1857178919496[1, 2, 3, 4][1

Python中的深浅拷贝详解

要说明Python中的深浅拷贝,可能要涉及到下面的一系列概念需要简单说明下: 变量-引用-对象(可变对象,不可变对象)切片-拷贝-浅拷贝-深拷贝 [变量-对象-引用] 在Python中一切都是对象,比如说: 3, 3.14, 'Hello', [1,2,3,4],{'a':1}...... 甚至连type其本身都是对象,type对象 Python中变量与C/C++/Java中不同,它是指对象的引用 单独赋值: 比如说: >>> a = 3 在运行a=3后,变量a变成了对象3的一个引用.在

Python中的深浅拷贝

Python中的深浅拷贝 前言:我们在了解深浅拷贝之前首先需要明白的一点知识 不可变类型数据:不可变类型即指当改变其内元素时,内存空间将会发生变化,比如常见的不可变类型有:str,boolean, int,tuple. temp = "哈哈哈" ret = temp.replace("哈", "嘿", 2) print(temp) # 哈哈哈 print(ret) # 嘿嘿哈 # 我们可以看到temp的值并没有发生改变,这就是为什么对str数据改

python——赋值与深浅拷贝

初学编程的小伙伴都会对于深浅拷贝的用法有些疑问,今天我们就结合python变量存储的特性从内存的角度来谈一谈赋值和深浅拷贝~~~ 预备知识一--python的变量及其存储 在详细的了解python中赋值.copy和deepcopy之前,我们还是要花一点时间来了解一下python内存中变量的存储情况. 在高级语言中,变量是对内存及其地址的抽象.对于python而言,python的一切变量都是对象,变量的存储,采用了引用语义的方式,存储的只是一个变量的值所在的内存地址,而不是这个变量的只本身.  引

python小白-day3 深浅拷贝

一.深浅拷贝 对于 数字 和 字符串 而言,赋值.浅拷贝和深拷贝无意义,因为其永远指向同一个内存地址.下面是字符串例子,数字与其相同: 1 2 3 4 5 6 7 8 9 import copy n1 = 'abc' n2 = n1 n3 = copy.copy(n1) n4 = copy.deepcopy(n1) print(id(n1)) print(id(n2)) print(id(n3)) print(id(n4)) 对于字典.元祖.列表 而言,进行赋值.浅拷贝和深拷贝时,其内存地址的变

python之路-深浅拷贝

深浅拷贝用法来自copy模块. 导入模块:import copy 浅拷贝:copy.copy 深拷贝:deepcopy 字面理解:浅拷贝指仅仅拷贝数据集合的第一层数据,深拷贝指拷贝数据集合的所有层.所以对于只有一层的数据集合来说深浅拷贝的意义是一样的,比如字符串,数字,还有仅仅一层的字典.列表.元祖等 对于以下数据深浅拷贝的意义是一样的: name = 'beijing' age = 12 list1 = [1,2,3,4] dic1 = {'name':'beijing','age':20}

Python中的深浅拷贝,赋值及引用

简单来说,若对象a中存的是列表或字典等可变对象,b对a的浅拷贝只是对对象第一层的复制,修改b第二层的元素仍然会影响两个对象. 深拷贝则是不会影响原来的对象. import copy.copy() 浅拷贝 copy.deepcopy()  深拷贝 赋值操作更像是一个引用,新的赋值会创建一个新的内存地址,指向改变了,原来的内存地址还会存在. 参考文章地址: python基础(5):深入理解 python 中的赋值.引用.拷贝.作用域 http://my.oschina.net/leejun2005/

python基础学习-内置函数

#!/usr/bin/env python # -*- coding:utf-8 -*- 系统内置函数 n =abs(-1) #绝对值 print(n) #bytes()函数 s="离开" re= bytes(s,encoding="utf-8")  # bytes() 把字符串 转换成字节 print(re) res = str(re,encoding="utf-8") #转换回字符串 print(res) re= bytes(s,encodi