[Python笔记]第三篇:深浅拷贝、函数

本篇主要内容:深浅拷贝,自定义函数,三目运算,lambda表达式,

深浅拷贝

一、数字和字符串

对于 数字 和 字符串 而言,赋值、浅拷贝和深拷贝无意义,因为其永远指向同一个内存地址。

import copy
# ######### 数字、字符串 #########
n1 = 123
# n1 = "i am alex age 10"
print(id(n1))
# ## 赋值 ##
n2 = n1
print(id(n2))
# ## 浅拷贝 ##
n2 = copy.copy(n1)
print(id(n2)) # ## 深拷贝 ##
n3 = copy.deepcopy(n1)
print(id(n3))

  

[Python笔记]第三篇:深浅拷贝、函数

二、其他基本数据类型

对于字典、元祖、列表 而言,进行赋值、浅拷贝和深拷贝时,其内存地址的变化是不同的。

1、赋值

赋值,只是创建一个变量,该变量指向原来内存地址,如:

n1 = {"k1": "wu", "k2": 123, "k3": ["alex", 456]}

n2 = n1

  

[Python笔记]第三篇:深浅拷贝、函数

2、浅拷贝

浅拷贝,在内存中只额外创建第一层数据

import copy

n1 = {"k1": "wu", "k2": 123, "k3": ["alex", 456]}

n3 = copy.copy(n1)

  

[Python笔记]第三篇:深浅拷贝、函数

3、深拷贝

深拷贝,在内存中将所有的数据重新创建一份(排除最后一层,即:python内部对字符串和数字的优化)

import copy

n1 = {"k1": "wu", "k2": 123, "k3": ["alex", 456]}

n4 = copy.deepcopy(n1)

[Python笔记]第三篇:深浅拷贝、函数 

 

>>> import copy
>>> n1 = {"k1": "wu", "k2": 123, "k3": ["alex", "eric"]}
>>> n2 = n1
>>> n3 = copy.copy(n1)
>>> n4 = copy.deepcopy(n1)
>>> n1['k1'] = 'lee'
>>> n1['k3'][0] = "tim"
>>> print(n3)
{'k1': 'wu', 'k2': 123, 'k3': ['tim', 'eric']} # 浅拷贝
>>> print(n4)
{'k1': 'wu', 'k2': 123, 'k3': ['alex', 'eric']} # 深拷贝
>>>

三目运算

三目运算也叫三元运算,是对简单的条件语句的缩写。

1 # 书写格式
2
3 result = 值1 if 条件 else 值2
4
5 # 如果条件成立,那么将 “值1” 赋值给result变量,否则,将“值2”赋值给result变量

lambda表达式

学习条件运算时,对于简单的 if else 语句,可以使用三元运算来表示,即:

# 普通条件语句
if 1 == 1:
name = 'wupeiqi'
else:
name = 'alex' # 三元运算
name = 'wupeiqi' if 1 == 1 else 'alex'

对于简单的函数,也存在一种简便的表示方式,即:lambda表达式也叫匿名函数

# ###################### 普通函数 ######################
# 定义函数(普通方式)
def func(arg):
return arg + 1 # 执行函数
result = func(123) # ###################### lambda ###################### # 定义函数(lambda表达式)
my_lambda = lambda arg : arg + 1 # 执行函数
result = my_lambda(123)
# 不带参数的lambda表达式
ret1 = (lambda arg: arg + 3)(100)
# 带参数的lambda表达式
ret2 = (lambda arg: arg + 3 if arg % 2 == 0 else arg)(99)
print(ret1)
print(ret2)

带参数的lambda表达式

自定义函数

一、函数背景知识

在学习函数之前,我们一直遵循:面向过程编程。

即:根据业务逻辑从上到下实现功能,其往往用一长段代码来实现指定功能,

开发过程中最常见的操作就是粘贴复制,也就是将之前实现的代码块复制到现需功能处,如下:

while True:
if cpu利用率 > 90%:
#发送邮件提醒
连接邮箱服务器
发送邮件
关闭连接 if 硬盘使用空间 > 90%:
#发送邮件提醒
连接邮箱服务器
发送邮件
关闭连接 if 内存占用 > 80%:
#发送邮件提醒
连接邮箱服务器
发送邮件
关闭连接

  

这段代码if语句下面都是重复的内容,于是有了更简练的表达就有了:

def 发送邮件(内容)
#发送邮件提醒
连接邮箱服务器
发送邮件
关闭连接 while True: if cpu利用率 > 90%:
发送邮件('CPU报警') if 硬盘使用空间 > 90%:
发送邮件('硬盘报警') if 内存占用 > 80%:

  

没错,上面的代码就是函数了!

对于上述的两种实现方式,第二次必然比第一次的重用性和可读性要好,其实这就是函数式编程和面向过程编程的区别:

  • 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可
  • 面向对象:对函数进行分类和封装,让开发“更快更好更强...”

函数式编程最重要的是增强代码的重用性和可读性

二、函数的定义和使用

def 函数名(参数):

    ...
函数体
...
返回值

  

函数的定义主要有如下要点:

  • def:表示函数的关键字
  • 函数名:函数的名称,日后根据函数名调用函数
  • 函数体:函数中进行一系列的逻辑计算,如:发送邮件、计算出 [11,22,38,888,2]中的最大数等...
  • 参数:为函数体提供数据
  • 返回值:当函数执行完毕后,可以给调用者返回数据。

以上要点中,比较重要有参数和返回值:

1、返回值

函数是一个功能块,该功能到底执行成功与否,需要通过返回值来告知调用者。

以上要点中,比较重要有参数和返回值:

def 发送短信():

    发送短信的代码...

    if 发送成功:
return True
else:
return False while True: # 每次执行发送短信函数,都会将返回值自动赋值给result
# 之后,可以根据result来写日志,或重发等操作 result = 发送短信()
if result == False:
记录日志,短信发送失败...

  

2、参数

为什么要有参数?

参数是由函数封装者提供的功能定义。通过传入参数,函数使用者就无需只要函数内部工作细节就能完成一些复杂的运算操作

没有参数

def cpu_alrt():
#发送邮件提醒
# 连接邮箱服务器
# 发送邮件
# 关闭连接 def disk_alrt():
#发送邮件提醒
# 连接邮箱服务器
# 发送邮件
# 关闭连接 def ram_alrt():
#发送邮件提醒
# 连接邮箱服务器
# 发送邮件
# 关闭连接 while True: if cpu > 90%:
cpu_alrt() if disk > 90%:
disk_alrt() if ram > 80%:
ram_alrt()

有参数实现

def alrt(默认参数):
#发送内容 while True: if cpu > 90%:
alrt("cpu alrt") if disk > 90%:
alrt("disk alrt") if ram > 80%:
alrt("ram alrt")
3.三种参数

普通参数

普通参数的情况下,函数括号里面的叫做形式参数,调用函数而传入的叫实际参数.

普通参数的传递并没有个数和数据类型的限制,可以传递字符串,数字,列表和字典。

但参数必须按照函数定义时的顺序依次传入他们。

# 定义函数
def argtest(arg1,arg2,arg3):
print('hello everyone, %s' % arg1)
for k, v in arg2.items():
print('my %s is %s' % (k, v))
print("I like %s" % ' and '.join(arg3)) st = 'my name is john'
li = ['running', 'swimming', 'diving']
dic = {"age": 18, "gender": "male"} # 依次传入字符串;字典;列表
argtest(st, dic, li) """
hello everyone, my name is john
my age is 18
my gender is male
I like running and swimming and diving
"""

默认参数

默认参数是在定义函数的时候给参数赋一个默认值,默认参数需要定义在普通参数的后面,允许有多个默认参数

def func(name, age = 18):
print("%s:%s" %(name,age)) # 指定参数
func('eric', 28)
# 使用默认参数
func('john') # 执行结果
eric:28
john:18
# 注:默认参数需要放在参数列表最后

动态参数

def func(*args) 接受多个参数,内部自动构造元组,序列前加*,避免内部构造元组
def func(**kwargs) 接收多个参数,内部自动构造字典,序列前加**,直接传递字典
def func(*args,**kwargs):接受多个参数,既可以自动构造元组,又可以自动构造字典。

下面展示自动构造元组,自动构造字典及前两者综合的参数传递方式:

def func(*args):
print(args) a = [1, 2, 3]
func(a)
func(*a)
# 执行结果:
([1, 2, 3],)
(1, 2, 3) ################################# def func(**kwargs):
print(kwargs) func(name='john')
# 执行结果:
{'name': 'john'} func(name='john', aeg=18)
dic = {'name': 'alex', 'age': 88}
func(**dic)
# 执行结果:
{'name': 'alex', 'age': 88} ################################ def func(*args,**kwargs):
print(args)
print(kwargs) func(1, 2, 3, 4)
# 执行结果:
(1, 2, 3, 4)
{} func(k1=800, k2=900)
# 执行结果:
()
{'k1': 800, 'k2': 900} func(1, 2, 3, 4, k1=800, k2=900)
# 执行结果:
(1, 2, 3, 4)
{'k1': 800, 'k2': 900}
import smtplib
from email.mime.text import MIMEText
from email.utils import formataddr msg = MIMEText('邮件内容', 'plain', 'utf-8')
msg['From'] = formataddr(["发件人名字",'shuaige@126.com'])
msg['To'] = formataddr(["收件人名字",'shuainan@qq.com'])
msg['Subject'] = "主题" server = smtplib.SMTP("smtp.126.com", 25)
server.login("shuaige@126.com", "邮箱密码")
server.sendmail('shuaige@126.com', ['shuainan@qq.com',], msg.as_string())
server.quit()

发送邮件的代码

4.全局变量大写 局部变量小写

补充:全局变量和局部变量关系

# 全局变量
PERSON = "alex" def func1():
# 局部变量
a = 123
global PERSON
PERSON = "eric"
print(a) def func2():
# 局部变量
a = 456
print(PERSON)
print(a) func1()
func2()

函数补充内容

Filter函数的一种实现

def MyFilter(func, seq):
# func,函数名, 函数名() ====》 执行
# seq
result = []
for i in seq:
# func = f1()
# func(x) 执行f1 函数,并获取返回值,将其赋值ret
ret = func(i)
if ret:
result.append(i)
return result def f1(x):
if x > 22:
return True
else:
return False r = MyFilter(f1, [11,22,33,44,55])
print(r)

Map函数的一种实现

li = [11,22,33,44]
def x(arg):
return arg + 100 def MyMap(func, arg):
# func 函数
# arg 列表
result = []
for i in arg:
ret = func(i)
result.append(ret)
return result
r = MyMap(x, li)
print(r)

作业及答案:

利用函数写一个登录功能

实现用户登录 添加用户 修改用户 删除用户等功能

登录函数写法

def login(username, password):
"""
用于用户名密码的验证
:param username: 用户名
:param password: 密码
:return: True:用户名验证成功;False:用户验证失败。
"""
# f = open("db","r",encoding='utf-8')
with open("db", "r", encoding="utf-8") as f:
for line in f:
# 默认strip无参数:去除空格,换行符
# 有参数:移出两侧指定的值
line = line.strip()
line_list = line.split(":")
if username == line_list[0] and password == line_list[1]:
return True return False def user_exist(username):
"""
检查用户名是否存在
:param username: 要检测到用户名
:return: True,已存在;False,不存在
"""
# 一行一行查找,如果用户名存在,return True
with open("db", "r", encoding="utf-8") as f:
for line in f:
line = line.strip()
line_list = line.split(":")
if line_list[0] == username:
return True def register(username, password):
"""
注册用户
:param username: 用户名
:param password: 密码
:return: True,注册成功
"""
with open("db", "a", encoding="utf-8") as f:
temp = "\n" + username + ":" + password
f.write(temp)
return True def main():
print("Welcome to our sysrem !")
inp = input("1.登录;2.注册") user = input("请输入用户:")
pwd = input("请输入密码:") if inp == "":
is_login = login(user, pwd)
if is_login:
print("登录成功")
else:
print("登录失败") elif inp == "":
is_exist = user_exist(user)
if is_exist:
print("用户名已存在,无法注册 !")
else:
result = register(user,pwd)
if result:
print("注册成功")
else:
print("注册失败") if __name__ == '__main__':main()
上一篇:自动化运维工具-pssh工具安装配置及简单使用讲解


下一篇:【BZOJ4817】【SDOI2017】树点涂色 [LCT][线段树]