三元运算

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

result = 1 if 条件 else 2 
# 如果条件成立,那么将 “值1” 赋值给result变量,否则,将“值2”赋值给result变量

深浅拷贝

一、数字和字符串

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

import copy
# ######### 数字、字符串 #########
n1 = 123        # n1 = "i am alex age 10"
print(id(n1))    # >>>1876955408
# ## 赋值 ##
n2 = n1
print(id(n2))    # >>>1876955408
# ## 浅拷贝 ##
n2 = copy.copy(n1)
print(id(n2))    # >>>1876955408  
# ## 深拷贝 ##
n3 = copy.deepcopy(n1)
print(id(n3))    # >>>1876955408    内存地址始终不变

python_day3函数及文件操作_python

二、其他基本数据类型

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

1、赋值

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

n1 = {"k1""wu""k2"123"k3": ["alex"678]}  
n2 = n1

  python_day3函数及文件操作_python_02

2、浅拷贝

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

import copy
n1 = {"k1""wu""k2"123"k3": ["alex"678]}
n3 = copy.copy(n1)

python_day3函数及文件操作_python_03

3、深拷贝

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

import copy
n1 = {"k1""wu""k2"123"k3": ["alex"678]}  
n4 = copy.deepcopy(n1)

python_day3函数及文件操作_python_04

函数(python是自上而下执行,先定义后引用)

  • 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可

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

  • 面向对象:对函数进行分类和封装,让开发“更快更好更强...”

一、定义和使用

def 函数名(参数):       
    ...
    函数体
    ...
    返回值

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

  • def:表示函数的关键字

  • 函数名:函数的名称,日后根据函数名调用函数

  • 函数体:函数中进行一系列的逻辑计算,如:发送邮件、计算出 [11,22,38,888,2]中的最大数等...

  • 参数:为函数体提供数据

  • 返回值:当函数执行完毕后,可以给调用者返回数据。

1、返回值

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

  • 一旦执行return,函数就结束了;

  • 函数的默认返回值为 None (就是没有写 return )。

2、参数

函数的有三中不同的参数:

  • 普通参数(严格按照顺序。将实际参数赋值给形式参数)

  • 默认参数(必须放置在参数列表的最后);指定参数(将实参赋值给形参)

  • 动态参数:* 与 **

*    #默认将传入的参数,全部放置在元组中

>>> def f1(*args):

...    print(args,type(args))

...

>>> li = [11, 22, 'nimei']#定义一个列表

>>> f1(li)

([11, 22, 'nimei'],) <class 'tuple'>#把列表当成一个参数

>>> f1(*li)               #参数前面又加一个*星号

(11, 22, 'nimei') <class 'tuple'>#列表里的每个元素都是一个参数

>>> str = "alex"

>>> f1(str)               #来看看字符串

('alex',) <class 'tuple'>

>>> f1(*str)               #把字符串也拆分了

('a', 'l', 'e', 'x') <class 'tuple'>  #加*,相当于里面加了一层for循环

>>>                        #也可以说是把每个元素直接赋值给变量

**   #默认将传入的参数,全部放置在字典中

>>> def f2(**args):

...    print(args,type(args))

...

>>> f2(k1="v1",k2="v2")     #参数输入必须是此种k,v类型

{'k2': 'v2', 'k1': 'v1'} <class 'dict'>

>>> dict1 = {"k1":"v1","k2":"v2"}

>>> f2(**dict1)          #又加俩**,相当于把整个字典给赋值了

{'k2': 'v2', 'k1': 'v1'} <class 'dict'>

>>>

万能参数:*args,**kwargs

>>> def f3(*args, **kwargs):#一星放前面,俩星放后面(规定)

...     print(args)

...     print(kwargs)

...

>>> f3(11,22,k1="v1",k2="v1")#k,v类型参数最后传入

(11, 22)

{'k2': 'v1', 'k1': 'v1'}

>>>


str.format()函数就是用的万能参数

def format(*args, **kwargs): # real signature unknown

    """

    Return value.__format__(format_spec)

    

    format_spec defaults to the empty string

    """

    pass

函数补充

1、同名函数,下面的会覆盖上面的

2、一个面试题:

函数的参数进行传递的时候,传的是引用,还是重新复制一份值呢??

>>> def f1(a1):

...     a1.append(999)

...

>>> li = [11,22,33,44]

>>> ----------华丽分割线----------

>>> f1(li)

>>> print(li)      #查看 li 是否被修改

[11, 22, 33, 44, 999]#说明python参数传递的是引用(就是内存地址)

>>>如果将分割线下面f1(li)赋值给li,会是什么效果呢:

>>> li = f1(li)

>>> print(li) 就是None,因为函数的默认返回值是None!!

3、变量:优先使用自己作用域内(也就是局部变量),没有再去其父类查找

 全局变量(全部大写):在所有的作用域都可读

  修改全局变量:变量前加 global

对于列表、字典等特殊变量:可以修改(如append()),但不可以重新赋值

内置函数

python_day3函数及文件操作_python_05

注:查看详细猛击这里

open函数,该函数用于文件处理

操作文件时,一般需要经历如下步骤:

  • 打开文件

  • 操作文件

一、打开文件

文件句柄 = open('文件路径', '模式')

打开文件时,需要指定文件路径和打开方式,打开后,即可获取该文件句柄,日后通过此文件句柄对该文件操作。

打开文件的模式有:

  • r ,只读模式【默认】

  • w,只写模式【不可读;不存在则创建;存在则清空内容】

  • x, 只写模式【不可读;不存在则创建,存在则报错】

  • a, 追加模式【可读;   不存在则创建;存在则只追加内容】

"+" 表示可以同时读写某个文件;"b"表示以字节的方式操作

  • r+ | rb :   可以调整位置修改,最常用

  • w+ | wb : 先清空才能读,不好

  • a+ | ab :  seek()无法调节位置,始终是在最后追加

   注:以b方式打开时,读取到的内容是字节类型,写入时也需要提供字节类型

 #硬盘保存的是二进制文件,而python读取的却是str字符串类型文件,所以说,这中间存在一个二进制转换字符串的过程,是python自动转换的;除非显式的告诉python需要手动转换,即加个b:

f = open('db', 'ab')

f.write(bytes("你妹", encoding="utf-8"))

# 有b,需要将字符串转换成二进制,然后标明其编码格式;编码是在bytes()里面标注的

f.close()

f.seek(index)

#修改指针位置,然后写文件的时候就是从修改之后的index(字节的位置)的位置向后覆盖写文件

f.tell()    #获取当前指针的位置(字节

所以,一般修改指针的位置的时候,都是先获取位置,然后修改,即:

f.seek(f.tell()) #当然,获取位置之前的操作,可以是设置位置,一段代码如下:

f = open("db", "r+", encodong="utf-8")  #打开模式无b,则read,按照字符读取

data = f.read(1)  #读取第一个字符的位置

print(f.tell())   # 3,因为一个字符是三个字节

f.seek(f.tell())  #调整当前指针位置

f.write("888")   #当前指针位置开始向后覆盖

f.close()

二、操作文件

read()#无参数,读全部,有参数(b,按字节;无b,按字符)

tell()#获取当前指针位置(字节)

seek()#指针跳转到指定位置(字节)

write()#写数据:有b,按字节;无b,按字符

close()#文件关闭

fileno()#文件描述符,socket时会用

flush()#强制刷新,将缓冲区的信息写到文件里

readline()#仅读取一行

truncate()#截断,把当前指针位置后面的字符清空

for循环文件对象 

f = open(xxx)

for line in f:

    print(line)

三、管理上下文

为了避免打开文件后忘记关闭,可以通过管理上下文,即:

with open('log','r') as f:        
    ...

如此方式,当with代码块执行完毕时,内部会自动关闭并释放文件资源。

在Python 2.7 及以后,with又支持同时对多个文件的上下文进行管理,即:

with open('log1', 'r') as obj1, open('log2', 'w') as obj2:
    pass        #可以将第一个文件的内容写到第二个文件里

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 ###################### 
my_lambda = lambda arg: arg+1
result = my_lambda(123)

递归

利用函数编写如下数列:

斐波那契数列指的是这样一个数列 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368...

def func(arg1,arg2):
    if arg1 == 0:
        print(arg1, arg2)
    arg3 = arg1 + arg2
    print(arg3)
    func(arg2, arg3)
func(0,1)