4.1 函数:

4.1.1、  概念

4.1.2、  创建

4.1.3、  参数

4.1.4、  函数的reture

    4.1.5、  定义域

    4.1.6、  filter

    4.1.7、  map

    4.1.8、  reduce

    4.1.9、  迭代器

    4.1.10、 装饰器

    4.1.11、 内置函数

4.2:深浅拷贝

    4.2.1、  浅拷

    4.2.2、  深拷贝



all 判断是否有空元素   返回值为True或False

eval() 转换为字典 也能直接求出结果  eval('1+3+2')



4.1 函数:

4.1.1、概念

作用:

1、减少重复代码

2、方便修改,易扩展

3、保持代码一致性

命名规则

函数名必须是下划线或字母开头, 可以包含任意字母、数字或下划线的组合, 不能使用任何标点符号

函数名是不区分大小写的;

函数名不能是保留字。


4.1.2、创建

def f(): # def是define简称  f()表示函数名  ()可以用来传递参数

print (" hello world ")   # 函数体,下面所有代码都属于 f 这个函数


f()# 调用函数, 不加(), 直接用f那么它就表示成了一个变量


4.1.3、参数 

# 注意:1、形参有多少个,实参就得定义多少个

2、调用时候需要严格区分大小写

3、默写参数一定要跟在其它参数后面

4、不定长参数, 固定格式: (*args无命名参数放左边,**kwargs 有命名参数放右边),如果有默认参数放左边


# 必须参数(关键字参数): 必须参数以正确顺序传入函数,调用时的数量必须和声明时的一样

    def add(x,y):# add(x,y) 形参
    print (x+y)
    def(3,5)# 实参

    def test1(name,age):
        print("Name: %s" % name )
        print("Age: %d" % age )

    test1("xiong",123)

打印结果: Name: xiong

   Age: 123


# 默认参数:

    def test1(name,age,sex="man"):
        print("Name: %s" % name )
        print("Age: %d" % age )
        print("Sex: %s " % sex )

test1("xiong",123)
打印结果: Name: xiong
   Age: 123
   Sex: man

# 不定长参数:(*args)    # args可以自行命名   *表示不定长参数   

(*arges):   无命名参数   # 保存至args时为元组

(**kwargs): 有命名参数 # 保存至kwargs时为字典

*args 使用方法

    a=(1,2,3,4,5)

    a=(*[1,2,3,4,5])


**kwargs  把N个关键字参数,转换成字典的方式

    a=(name="xiong",sex='m')
    a=(**{'name':'xiong','sex':'m'})
    def test2(*args):
        print(args)

 

test2(1,2,3,4,5,6)          # 打印结果为: (1, 2, 3, 4, 5, 6)

##################### 示例2 #####################

def test3(**kwargs):

    print(kwargs)

 

test3(name="xiong",age=123,sex="man")    # 打印结果: {'name': 'xiong', 'age': 123, 'sex': 'man'}

##################### 示例3 #####################

def test3(**kwargs):
    for te in kwargs:
        print(te,":",kwargs[te])

         

test3(name="xiong",age=123,sex="man")  

# 打印结果: name : xiong

             age : 123

             sex : man


##################### 示例4 #####################

def test4(*args,**kwargs):

    print(args,kwargs)

 

test4(1,2,3,4,name="xiong",age=123,sex="man")  

# 打印结果: (1, 2, 3, 4) {'name': 'xiong', 'age': 123, 'sex': 'man'}


##################### 错误——示例5 #####################

def test4(name,sex="man",*args,**kwargs):
    print(name,sex,args,kwargs)
 
test4(name="xiong",sex="man",1,2,3,4,age=123)
# 打印结果: SyntaxError: positional argument follows keyword argument

# 优先级: def 函数名(关键参数,默认参数,无命名参数,有命名参数)

#示例  def test(te1,age='male',123,job='IT')


#########  当中间有一个默认值的时候,如果不指定它还是会打印出错,

def test4(name,sex="man",*args,**kwargs):

    print(name,sex,args,kwargs)

 

test4("xiong",1,2,3,4,age=123)


4.1.4、函数的reture

作用: 1、结束函数

   2、返回某个对象


注意点: 1、 函数里如果没有return,会默认返回一个None

2、 如果return有多个对象,那么python会帮我们把多个对象封装成一个元组返回


4.1.5、定义域

函数是有自己的定义域的,IF是没有的

作用域分四种情况: LEGB

L:local,局部作用域,即函数中定义的变量;

E:enclosing,嵌套的父级函数的局部作用域,即包含此函数的上级函数的局部作用域,但不是全局的;

G:globa,全局变量,就是模块级别定义的变量;

B:built-in,系统固定模块里面的变量,比如int, bytearray等。 搜索变量的优先级顺序依次是:作用域局部>外层作用域>当前模块中的全局>python内置作用域,也就是LEGB


外层 built-in --> global 全局作用域 --> enclosing 局部作用域 --> local 局部作用域


局部变量不能修改全局变量

局部要想改变全局变量需要增加一个global 变量

如果是在enclosing那就需要增加一个nonlocal 变量名称 


4.1.6:filter (函数名字, 序列)过滤器对象


filter()函数是 Python 内置的另一个有用的高阶函数,filter()函数接收一个函数 f 和一个list,这个函数 f 的作用是对每个元素进行判断,返回 True或 False,filter()根据判断结果自动过滤掉不符合条件的元素,返回由符合条件元素组成的新list

# 过滤列表中名称是xiong的字符串

            name=["xiong","yuan"]
            def fi(n):
                if n!="xiong":
                    return n

            let=filter(fi,name)
            print(list(let))
                # 结果 ['yuan']

# 再比如过滤掉数字为奇数的行

            def number(n):
                if n %2 ==1:
                    return n
            jnum=filter(number,range(1,20))     # 过滤对象内存地址:<filter object at 0x000000000250F828>
            print(list(jnum))                   # 打印结果就是:[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]

4.1.7 map (函数名字, 序列)

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

map()函数是python内置的高阶函数,对传入的list的每一个元素进行映射,返回一个新的映射之后的list

            def x(f):
                return f*f      #从9开始每次相乘

            num=map(x,range(9))
            print(list(num))                   0  1  2  3   4   5  6    7  8  每个值都乖以自己

# 结果: 等于就是每个值的平方 [0, 1, 4, 9, 16, 25, 36, 49, 64]

  注意:map()函数不改变原有的 list,而是返回一个新的 list。


由于list包含的元素可以是任何类型,因此,map() 不仅仅可以处理只包含数值的 list,事实上它可以处理包含任意类型的 list,只要传入的函数f可以处理这种数据类型。

            x=["ali","jic","you"]
            def name(x):
                return "a" + x      
            na=map(name,x)              # 跟filter差不多,但如果将map改为filter那么它返回的结果就是ali,jic,you
            print(list(na))
                # 结果: ['aali', 'ajic', 'ayou']

# 扩展信息: http://www.cnblogs.com/superxuezhazha/p/5714970.html


4.1.8 reduce(函数,对象或序列)

reduce()   # 想用这个方法必须加上如下参数    reduce的结果就是一个值 

         from functools import reduce 


        lambda a,b: a + b


        ## 示例 先调用这个函数 

        from functools import reduce

        # add = lambda a,b: a+b
        # print(add(1,2))           # 结果3

        def add1(x,y):
            return x + y

        print(reduce(add1,range(10)))   # 结果45

4.1.9、迭代器 (函数名字, 序列)过滤器对象


# 什么是迭代器?  迭代器包含生成器

            # 满足两个条件:1、有iter方法, 2、有next方法

    # 自己理解

       # for 循环 先将(元组,字典,列表,集合,元组) 使用__iter__() 转换成迭代器对象,然后再使用__next__()方法从上往下取出结果

   # 专业解释

      # 调用它们内部的__iter__()方法,把它们变成可迭代对象,然后for循环调用可迭代对象的__next__方法去取值,而且for循环会捕捉stopiteration异常,以终止迭代


        # for  循环内部三件事:

            1、 调用可迭代对象的iter方法返回一个迭代器对象

            2、 不断调用迭代器的next方法

            3、 处理 StopIteration


        # 生成器都是迭代器,迭代器不一定是生成器 能使用iter的可迭代对象

            l=[1,2,4,5]

            d=iter(l)

            print(d)        # 结果 <list_iterator object at 0x000000000063B1D0>

        Iterator 可迭代对象  Iterable 迭代器

        isinstance 判断对象是啥类型 

        from collections import Iterator    # 需要先调用这个类型才能使用isinstance方法

        print(isinstance([1,2,3],list))

 迭代器用法:

people_list=['xiong','yuan','xyz']
print('土地拍卖现在开始啦')
def pow(people_list):
    if len(people_list) == 0:
        return '没人获取了'
    person=people_list.pop(0)
    if person == "xyz":
        return '恭喜%s成功拍下'%person
    print('%s 加500W 还有没有要加的?'%person)
    res=pow(people_list)
    print('%s 结果: %res' %(person,res))
    return res

res=pow(people_list)
print(res)



4.1.10、 装饰器

    装饰器:为其它函数增加功能使用的


    原则:  1、不能修改被装饰的函数的源代码

            2、不能修改被装修的函数的调用方式


    装饰器

        1、函数即“变量”, 变量特性内存回收机制,只要变量存在,内存地址将不会被删除 

        2、高阶函数

            2.1、 满足函数名可以做为一个参数输入 (在不修改被装饰函数源代码的情况下为其添加功能)

            2.2、 函数名还可以做为返回值


        3、嵌套函数

            高阶函数+嵌套函数 ==> 装饰器


    定义:如果在一个内部函数里,对在外部作用域(但不是全局作用域)的变量进行引用,那么内部函数就被认为是闭包

    def xx():
        x=10:       
        def yy():           # 条件一 xx就是内部函数
            print(x)        # 条件二 外部环境的一个变量
        return yy           # 结论: 内部函数inner就是一个闭包
    # 装饰器
import time
def change(func):
    def wapper():
        start_time=time.time()      # 调用之后先来个时间
        func()              # 需要注意的是 func就是直接调用tests函数
        end_time=time.time()       # 调用之后的时间
        print('函数执行总时长: %s'%(end_time-start_time))
    return wapper       # 返回的是一个函数的内存指向地址


@change                  # 语法糖
def tests():
    time.sleep(2)
    print('_主体函数_')

# @change 完全等于 tests=change(tests)
tests()

 

   列表生成式:  生成器就是一个可迭代对象(Iterable)

        a=[x*x for x in range(10)]      直接计算出平方结果[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]


        a=(x*x for x in range(10))      打印出生成器对象,不会有结果

                                        <generator object <genexpr> at 0x00000000021669E8>

        a.__next__()   # 使用该内置方法可以将值打印出来,但是不建议使用

        建议使用 print(next(a)) 方法          py2中使用的是s.next()

                只能从0开始到最后


#  功能,设置一个函数时间,将其保存到测试文件中,将打印start funcation 到屏幕上

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
 
    def logger(n):
        import time
        time_format = "%Y-%m-%d %X"
        times = time.strftime(time_format)
 
        with open("测试文件",'a',encoding='utf-8') as f:
            f.write("%s funcation1 %s \n" %(times,n) )
 
    def fun1(n):
        print("start funcation 1 ")
        logger(n)
 
    fun1(1)

 

# 打印结果打开测试文件  2017-09-12 14:13:33 funcation1 1  

                    #   %s  times                      %s  n    函数形参的参数

# 实现不定长函数的加法

def test2(*args):
    number = 0
    for i in args:
        number += i
    print(number)

 

test2(1,2,3,4,5,6)      # 传递一堆整型给test2函数, 保存至args是元组格式,使用for循环叠加




4.1.11、 内置函数

b = 'abc1'
b.count('1')#统计元素个数结果 1
b.capitalize()#字符串首字母大写结果 Abc1
b.center(12,'-')#字符居中并两边打印- 结果 ----abc1----

print('abc'.ljust(50,'*'))向左对齐
print('abc'.rjust(50,'*'))向右对齐

print("   xiong   ".strip())去除所有空格,换行符也会自动取消  很重要的方法

print( 'xiong'.replace('x','X',1))替换 
#两个参数,(想更改的),(要更改成啥),如有多个字符,1表示只替换一次

b.encode#编码

b.endswith('1')#以某个字符串结尾结果 True
b.startswith('1')#以某个字符串起始结果 False
b.expandtabs(tabsize=#)# 用得少

b.find('1')#查找第一个元素,并将索引值返回

print('xiong'.rfind('g'))#与find功能一样
print('xiong'.find('g'))

两个打印结果都是: 4

b.index('1')#与find功能一样,多了一个元素没有的时候会报错,find不会报错

b.format#格式化输出的另一种方式
b = 'abc1 {name} is {age}'
print(b.format(name='xiong',age='123'))

b.format_map({'name':'xiong','age':'123'})

print(str.isalnum()) # 判断所有字符都是数字或者字母
print(str.isalpha()) # 判断所有字符都是字母
print(str.isdigit()) # 判断所有字符都是数字 必须是一个整形
print(str.islower()) # 判断所有字符都是小写
print(str.isupper()) # 判断所有字符都是大写
print(str.istitle()) # 判断所有单词都是首字母大写,像标题
print(str.isspace()) # 判断所有字符都是空白字符、\t、\n、\r
# 返回结果不是True 就是 False

print('Abc',lower()) # 大写变小写结果abc
print('Abc',upper()) # 小写变大写结果ABC
print('Abc',swapcase()) # 小写变大写,大写变小写    结果 aBC

print ('My test xiong'.split(' '))将字符串变为一个列表  
# split(' ',1)   以什么为分隔符进行分割字符串 ['My', 'test xiong']

print ('My test xiong'.rsplit(' '))将字符串变为一个列表  
# rsplit(' ',1) 从右往左, 只分隔一次   ['My test', 'xiong']

print ('My test xiong'.title())    所有字符串 首字母都变成大写  My Test Xiong

join 连接方法   拼接   方法为 ''.join(字符串提供的方法)
a='123'
b='abc'
c=''.join([a,b])#结果 123abc
c='****'.join([a,b])#结果 123****abc

flush: 将数据从缓存区取出同步保存与磁盘中

import sys,time
sys.stdout.write("*")

# 截断是在写模式下操作的,必须使用write,append格式
truncate    # 清空文件内容

fileno# 文件描述符

isatty# 查看是不是终端设备
zip 拉链方法
    print(list(zip('a','b')))   #将两个字符串组成一个元组    结果: [('a', 'b')]
    print(zip(('b','c'),(1,2)))  # 直接打印就是一个内存对象地址 结果<zip object at 0x000000000250E508>  
# 需要将内存地址列出才能查看 ,左边一对应右边一
    print(list(zip(('b','c'),(1,2))))  # 结果[('b', 1), ('c', 2)]
# 当右边没有对应值时,就不会组成对应元组,
    print(list(zip(('b','c','d'),(1,2))))   #结果[('b', 1), ('c', 2)]

# 将字典也可以转成一一对应的元组
    dic={'name':'xiong','age':121}
    print(list(zip(dic.keys(),dic.values())))
    # 结果:[('name', 'xiong'), ('age', 121)]
    
max | min的用法, max最大,min最小

# max传递的参数必须是可迭代的,也就是可以用for进行循环的类型
print(list(max(zip(name.values(),name.keys()))))

# max比较的类型必须是同一种类型,比如现在是字符串,那么中间有整型比较一定会报错
name=['a11','b11','c11']  # 字符串比较是从第一位开始,第一位如果大那么这个字符串无论多长都是最大的
print(max(name))

name2=['A11','c11','a1']
print(max(name2))

print(bin(1))
print(hex(21))

# max的高级用法 ,比较数据的最大大小
    dit=[
        {'name':'xiong','age':123},
        {'name':'yy','age':312},
        {'name':'ss','age':4221},
        {'name':'za','age':1243},
    ]

    print(max(dit,key=lambda age:age['name']))
    # {'name': 'za', 'age': 1243}
    print(max(dit,key=lambda age:age['age']))
    # {'name': 'ss', 'age': 4221}
    
    # 相当于先return了一个age的最大数值,然后将数值进行比较
    it=[]
    for item in dit:
        it.append(item['age'])
    print(it)
    
# sorted从小到大排序

dic={
     'uu_age':50,
     'xx_age': 51,
}
# sorted 字典默认排序会直接使用key的方式
print(sorted(dic))
# 结果['uu_age', 'xx_age']

# 使用values进行比较,但打印出来的只是名称,不是数值
print(sorted(dic,key=lambda age:dic[age]))
# 结果['uu_age', 'xx_age']

# 以列表的方式打印出结果
print(sorted(zip(dic.values(),dic.keys())))
# 结果[(50, 'uu_age'), (51, 'xx_age')]

# reversed 倒序排列
li=[1,2,3,4,5]          
print(list(reversed(li)))


4.2 深浅拷贝


4.2.1 浅拷 = 相当于软链接

# 变量中列表就相当于文件,int与str就相当于是一个目录,

# (软链接可以将目录名称更称不会修改文件本身,但如果修改文件那么A跟B就会同时修改)。

a = [[1,2],3,4]
print(a)
打印: [[1, 2], 3, 4]
b = a.copy()
b[1]=321
print(b)
打印结果为: [[1, 2], 321, 4]# 软链接目录名称改了也不会影响原来的目录
print(a)
打印结果为: [[1, 2], 3, 4]# b修改a不修改也就正常了
# 但如果是修改变量中的列表时,它会修改内存中指的值,a跟b会同时修改
b[0][1] = 234
print(b)
print(id(b[0][1]))# 打印结果为: 1388964880   两个内存结果都一样

print(a)
打印结果为: [[1, 234], 321, 4]# 改了软链接中文件,那么2个文件都会同时更称
[[1, 234], 3, 4]
print(id(a[0][1])) # 打印结果为: 1388964880   
# 相当于一个链接的文件,修改b也相当于修改a了


4.2.2 深拷贝 = 完整克隆

变量 = copy.deepcopy(要复制的变量)    # 完整克隆一个数据