LF 第三章

三元运算

三元运算又称三目运算,是简单的条件语句的简写,如:

val = i if 条件成立 else 2

name = 'alex' if 3>5 else 'ben'
#ben  

 

Python文件处理

f = open("大.txt",mode = "r",encoding='utf-8')
data = f.read()
print(data)
f.close()

注意点:

1.注意编码格式,文件的编码,否则转换出错

2.如果不知道文件编码,则可以用rb 直接从硬盘以二进制模式读取存入内存

f = open("大.txt",mode = "rb")
data = f.read()
print(data)
f.close()

这种方式只有一种用处,给机器看

网络传输 rb模式

3.我再打开时,不知道编码,但我想看内容

有个模块 chardet

安装第三方工具包

pip3 install chardet

 

import chardet # 导入检测包
f = open('大.txt',mode='rb') # 以二进制rb读取文件
data = f.read()
print(chardet.detect(data)) # 分析文件,进行预测文件编码
print(data.decode('gbk'))# 分析后将文件以GBK格式解码读取

#{'encoding': 'ISO-8859-1', 'confidence': 0.73, 'language': ''}
大叫好哈哈哈

关于文件处理 另外文章讲解

函数

为什么使用函数

1.代码重复过多

2.如果日后需要修改,则全部需要改,维护性非常差

解决方法:只要将重复代码提取,放在公共地方,起个名字,以后谁要用这段代码,就通过名字调用就可以了

定义:

函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需要调用函数名即可

 

def sayhi():
    print("hello")
sayhi()

 

 特性:

减少代码重复

程序变得可扩展

程序变得易维护

 

 形参变量:

只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此形参只有在函数内部有效,函数调用结束返回主调用函数后则不在使用形参变量

实参:

可以是常亮,变量,表达式,函数等。无论实参是何种类型的量,在进行函数调用时,他们都必须有确定的值,以便把这些值传送给形参,因此应预先用赋值,输入等办法使参数获得确定值

 

def calc(x,y)#形参
    res = x**y
    return res
a,b = 3,4
c = calc(a,b)#实参
print("c")

 

 默认参数

def stu(name,age,course,country="cn"):#country 就是默认参数
    print(name,age,country,course)

stu("张三",22,linux)

默认参数位置要放在顺序参数之后

 

关键参数

正常情况下,给函数传参数要按顺序,不想按顺序就可以用关键参数,只需要制定参数名即可(制定了参数名的参数就叫关键参数),有一个要求就是:关键参数必须放在位置参数之后(以位置顺序确定对应关系的参数)

 

#函数声明:
def stu(name,age,course="PY",country="CN"):
    print("----注册学生信息----")
    print("姓名:",name)
    print("age:",age)
    print("国籍:",country)
    print("课程:",course)
#调用:
    stu("王尼玛",course='PY',age=22,country="jp")#第二个,第三个第四个就是关键参数

不可以这样

stu('jack',course="py",22,country='jp')

stu("ben",22,age=23,country='jp')

非固定参数 *args **kwargs

 1.以元组形式的非固定参数

#报警,给一个人发
def send_alert(msg,user):
    pass
#如果公司发展,给10个人发,那么需要调用多次
send_alert("Stop",'alex')
send_alert("Stop",'alex1')
send_alert("Stop",'alex2')

#如果这样需要修改大量代码,该怎么做呢
#user前面嫁个*
#第一个参数给了msg,后面所有参数都打包发给*user  原来user是个字符串,现在是个元组

所以以后可以这样写:

#报警发送
del send_alert(msg,*users):
    for u in users:
        print("send to ",u)
#报警给多人
send_alert('STOP!!!','alex','abc','ben','ken')

如果形参中出现了*,传递的参数就可以不在是固定个数,而是一个所有参数给打包成一个元组 

主流一般都是*args

传参的时候两种,

#方式1
sent_alert('STOP','alex','bben','cero')

#方式2
sent_alert('STOP',*['alex','bben','cero'])

#两种方式效果是一样的

几个注意点:

1.如果方式2,参数前面不加*直接传给*user,会出现一个问题,*会打包一次,则users接收到的是

(['alex','bben','cero'])这样一个元组。为了避免这样情况,需要在传参时前面加一个*,这样user接受到的是(‘alex','bben','cero')

2.带*的非固定参数一般放在最后 因为*user会接受所有

send_alert(msg,*users,age):
    pass

send_alert('abc','ben','alex',22)
#这样是错的,*users接受了后面三个,运行报错age没有值

send_alert('abc','ben','alex',age=22)
#这样是不报错的,运用关键参数指定赋值

 

2.以关键字形式的非固定参数:

def func(name,*args,**kwargs):
    print(name,ages,kwargs)
func ('alex',22,'tesla',addr='山东',num=123123)
#**kwargs接收的是关键字参数(未定义的关键字参数)

d={'nanjing':27149}
func('alex',d)
#>>会输出 nanjing ({'nanjing':27149}){} 想要传入字典 需要如下操作
 func('alex',**d)
#>>peiqi (){'nanjing':27149}

函数返回值

def stu_register(name,age,course):
    print(name,age,course)
    return name #函数执行到return 则下面的不执行
    print(1)
    #####
    #return name,age    返回一个元组('peiqi',29) 因为函数返回只能返回一个值
  #也可以直接返回一个列表 [name,age]

全局变量和局部变量

name = 'black'
def change_name():
    name = 'yellow'
    print(name)

print(name)

#输出   yellow    
#         black
#内部是局部变量,外部是全局变量 两个name名字一样但完全不是一个值
#通过id(name)就知道两个变量指向的内存地址不同
#注意函数内printname 如果有局部变量,则print打印的是函数内的name,否则调用外面的全局变量
#注意,里面可以调用外面,但外面不能调用里面

 

局部变量就是指定义在函数里的变量 只能在局部生效,函数一旦执行完毕 里面生成的所有局部变量全部销毁

定义在函数外部一级代码的变量,叫全局变量,全局能用

在函数内部,可以引用全局变量,如果全局和局部有一个同名变量,那函数查找顺序是由内而外的

如果在函数内修改全局变量 name = 'abc' 其实是声明了一个局部变量

如果执意要修改全局变量,则需要调用方法

name = 'girl'

def change_name():
    global name
    name = 'boy'
    pring("在函数中局部变量name的值:",name)
print("全局变量name的值:",name)

>>>在函数中局部变量name的值:boy
>>>全局变量name的值:boy

#两个内存地址是一样的,即global name 在函数里面修改局部变量
#如果函数中调换了global name和name会报错。所以想要引用全局就要把global放上面,即 先要声明要修改某全局变量,再去修改

在实际的开发过程中一般情况下不建议使用global

函数里修改列表数据

names = ['alex','blg','peiq']

def change_name():
    del names[2]
    print(names)
change_name()
print(names)

['alex', 'blg']
['alex', 'blg']

发现可以修改

原因很简单,列表是引用,元素占用单独的内存地址,列表的内存地址不能改,但是内部单独是可以修改的

字典,列表 集合 类 对象 内部是不能改的 元组内有列表 是可以改的

字符串 数字 true false 不能改

执意要改 就是global 

嵌套函数

def func1():
    print('alex')
    def func2():
        print('eric')
func1()
>>>>alex

func1()执行后,只打印alex

原因:函数如果定义完成之后,没有人通过他的名字调用它,那么他永远不会执行

def func1():
    print('alex')
    def func2():
        print('eric')
    func2()
func1()
>>>>alex
>>>>eric

-----

1.函数内部可以再次定义函数

2.只要函数定义了,不管在外还是内,要想执行,需要被调用

age = 19
def func1():
    age = 73
    print(age)
    def func2():
        age = 84
        print(age)
    func2()
func1()
>>>73
>>>84

函数内部自己找变量名,找不到再往外找

但是如果代码是这样

age = 19
def func1():
    age = 73
    print(age)
    def func2():
        print(age)
    func2()
func1()

这里注意,由内往外找,是一层一层往外找,func2()里面的age也是局部变量

接下来

age = 19
def func1():
    def func2():
        print(age)
    age = 73
    func2()
func1()
>>>73

这里比较简单,函数从上到下运行,碰到函数但是不执行,执行func2()时候,age = 73被赋值,所以func2中age=73

接下来

age = 19
def func1():
    def func2():
        print(age)
    func2()
    age = 73
func1()
#报错

报错是因为,printage时候,找不到是哪个age,自己体会,不放在func2下面

接下来刺激的  

age = 19  #极少用到
def func1():
    global age
    def func2():
        print(age)
    func2()
    age = 73
func1()
>>>19

执行为啥是19   因为在函数func1中,global了age,相当于在此处 age = 19,那么在下面调用func2时候,会往外找,即19

接下来age = 73 ,那样全局变量就变成了73,那么如果在外面加一个打印那就是73

作用域

在python中,函数就是一个作用域 局部变量放置在其作用域中

注意:在这段代码定义完成后,作用域已经生成,作用域链向上查找

但是在别的语言里,比如java c# 不同

age = 77
def func1():
    age = 18      
    money = 1999
    print('alex')
    def func2():
        age = 88
        print('eric')

接下来看

age = 18
def func1():
    age = 73
    def func2():
        print(age)
    return func2
val = func1()
val()

执行后 ,结果是73,这里就有作用域了,函数无论不论在哪被调用,都会回到原来的作用域中

总结 1.函数名可以当做返回值

  2.代码写完之后,作用域已经生成,不论函数名传递到哪里 ,只要执行,回到最开始的地方

  3.Pythion中函数就是一个作用域(与java c#不同)局部变量防止在其作用域中

   

匿名函数

 定义一个函数不用名字?

def calc(x,y):
    return x*y
lambda x,y:x*y # 声明一个匿名函数

#普通函数调用通过名字()
#匿名函数如何调用?
func = lambda x,y:x*y
print(func(3,4))
#lambda匿名函数是不支持ifelse等复杂的逻辑语句,只能简单的逻辑判断
#最多最多支持三元运算
func = lambda x,y:x*y if x<y else x/y
#匿名函数的主要作用:就是跟其他方法搭配使用
data = list(range(10))
print(data)
#自乘
#老办法是:
# for index,i in enumerate(data):
#     data[index]=i*i
# print(data)
#单独的方法 map
def f2(n):
    return n*n
print(list(map(f2,data)))
#或者
print(list(map(lambda x:x*x,data)))
#这里的lambda跟其他方法调用使用,即用完一次就不用了,为了简单方便
#1。节省代码量
#2,。看着高级

高阶函数

变量可以指定函数,

函数的参数能接受变量,那么一个函数就可以接受另一个函数作为参数,这种函数就称为高阶函数

def cala(x):
    return xxx

n = 10
cala(10)
#如果传一个函数当参数进去 只要传函数,就是高阶函数

def func(x,y):
    return x+y
def cala(x):
    return x()

n = func
cala(func)

返回

def func(x,y):
    return abs,x,y
res = func2(3,-10)
#返回一个元组
print(res[0](res[1]+res[2]))

#只要你返回值里面有另一个函数,那他也是一个高阶函数

总结:给一个函数传另一个函数作为参数,或者一个函数返回另一个参数作为返回值,那么这个函数就是高阶函数

递归 

递归就是函数执行过程中调用了自己

def recoursion(n):
    print(n)
    recoursion(n+1)
recoursion(1)
#会报错 超过了最大限制
#python有个最大递归层次限制 sys.getrecursionlimit() 默认是1000
#修改限制:sys.setrecursionlimit(9999)

Python为什么要限制递归次数?

简单地说:每次新的递归,前一个函数仍在执行之中,内存会约占约多,如果无限运行系统很快就会撑爆了

为了避免出现这种情况,所以进行了限制

专业的说:在计算机中,函数的调用时通过栈(手枪弹夹来理解,弹夹就是栈,子弹就是栈帧)来调用的,但是python中不存在这种数据结构。由于函数没有停止,栈内就会很快被填满,就会出现栈溢出,无法存入数据,程序会崩溃。

每执行一次,加一层栈帧,函数销毁则减一层。

递归的作用

需求 10/2 一直除到0为止

def func(x):
    v=int(x/2)
    print(v,end=' ')
    if v == 0:
        return "done"
    func(v)
func(10)

如果

def func(x):
    v=int(x/2)
    print(v)
    if v == 0:
        return "done"
    func(v)
    print(v)
func(10)

>>>5 2 1 0 1 2 5

递归特点

1.必须有结束条件

2.每一次进入更深一层递归时,问题规模相比上次递归都应有所减少

3.递归执行效率不高,递归层次够多会导致栈溢出

递归的作用

斐波那契数列之类

求阶乘

任何大于1的自然数n阶乘表示方法:

n!=1x2x3x4x5x6x..xn

或n!=nx(n-1)!

def func(n):
    if n == 1:
        return 1
    return n*func(n-1) 
print(func(10))
>>>3628800

尾递归优化

def cal(n):
    print(n)
    return cal(n+1)
cal(1)
#优化思路 每一层return 后,下一层是直接返回,不再用上一层。那为什么上一层还要在占用内存
#以上就是尾递归,但是python不支持 还是会生成多个栈 知道这回事

内置函数

abs() #取绝对值
dict() #把一个数据转为字典
help() #帮助
min() # 取出列表最小值 (int)
max() #取出最大值 (int)
all() #如果列表所有值都是True或者空列表[],那么all返回true
bool() #判断是不是True  (0是False 其他是True)
        #对于一个列表,直接判断都是False     
any() #列表里任意值是True,返回True
dir() #打印当前程序存在的所有变量
hex() #转成16进制
slice() #切片 slice(start,stop[,step]) 先规定切片规则方便后面用,没啥用
divmod() #(10,3)>>(3,1)得到两个数的结果,在返回余数  //
sorted() #排序 对于一个字典d,需要排序 一般需要排序的话,首先转成列表d.items() ,不按key排序,用sorted(d.items(),key=lambda x:x[1])排序,按照value从小到大排序
acsii() #没什么用转成unicode一堆二进制
bin()#转成二进制

 

eval() #按解释器规则字符串转代码  f = '1+3/2' eval(f)
          #eval('print('hello')) >>hello
          #eval()能处理的只能是单行代码
exec() #与eval()一样,但是他能执行多行代码
           #最大区别 eval有返回值,exce没有返回值 
ord() #输出acsii 对应位置 'a'>>97 
chr #输出acsii >>字符串 chr(97) >>'a'
sum() #列表值求和

 

bytearray()
#字符串不可修改 s=  'abcd' s[0]='x' 报错
#但是可以通过修改bytes
s.encode('utf-8')
s = bytearray(s)
s[0] = 65
s.decode()
>>Abcd
#这里是原内存地址修改,不是重新开辟新内存地址。
#大字节修改,先变成bytes类型,再修改

map(f,list)
#map()是 Python 内置的高阶函数,它接收一个函数 f 和一个 list,并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的 list 并返回。

filter(f,list)
#过滤的意思,把符合条件的值过滤出来
#filter(lambda x:x>3,[1,2,3,4,5,6])
>>[4,5,6]

map filter reduce 三剑客reduce 2.0有
在python3里
import functools
reduce(f,list,x)
#
functools.reduce(lambda x,y:x+y,[1,2,3,4,5,6],3)!????????????????

print() #1.end=''  以''断 默认是\n
    #2.sep = '-'   :print('abc','bcd',sep='-')>>abc-bcd
    #3.print可以直接把数据打印进文件里
    #msg = 'abcde'
    #f = open('lala.txt','w')
    #print(msg,'aaaaa',sep='`',end = '',file = f)

tuple() #变成元组
callable() #判断是否可以调用
    #def f():
         pass
    #callable(f)>>>True
    #判断一个变量是否是函数,可以用这个方法判断。
wars() #当前所有变量打印出来,跟dir有区别,dir只会打印变量名,wars打印变量名和值

locals() #一般在函数内运行,打印函数的局部变量。永远只打印 局部变量
globals() #不管在哪运行,打印所有全局变量

repr(集合) #打印显示字符串??????????????????????????
zip()    # a = [1,2,3,4]  b=['a','b','c'] 想把两个列表 一一对应整合成一个列表 对应成为元组,放在一个列表里???????
    # list(zip(a,b) >>> [(1,'a'),(2,'b'),(3,'c')] 一一对应没有就丢弃

reversed() #和sorted()类似,默认反转???????????????

complex(3,5) #(3+5j)???????
round() #round(1.234434)>>1 round(1.234434,2)>1.23 保留几个小数

复习下hash() 集合

set() #把一个列表变成一个集合 set([3,3,4])>>{3,3,4}

 几个小栗子:

1、现在有两个列表,list1 = ['key1','key2','key3']和list2 = ['1','2','3'],把他们转为这样的字典:{'key1':'1','key2':'2','key3':'3'}
>>>list1 = ['key1','key2','key3']
>>>list2 = ['1','2','3']
>>>dict(zip(list1,list2))
{'key1':'1','key2':'2','key3':'3'}

2、将嵌套列表转为字典,有两种方法,
>>>new_list= [['key1','value1'],['key2','value2'],['key3','value3']]
>>>dict(list)
{'key3': 'value3', 'key2': 'value2', 'key1': 'value1'}

或者这样:
>>>new_list= [['key1','value1'],['key2','value2'],['key3','value3']]
>>>new_dict = {}
>>> for i in new_list:
...   new_dict[i[0]] = i[1]                #字典赋值,左边为key,右边为value
...
>>> new_dict
{'key3': 'value3', 'key2': 'value2', 'key1': 'value1'}

 

posted @ 2018-07-02 21:52  Alexstraze  阅读(269)  评论(0编辑  收藏  举报