函数

2.全局变量和局部变量

约定俗成:全局变量变量名大写,局部变量变量名小写

命名空间
存放变量名字的内存地址,其中绑定着对应值的映射关系,字典的方式,因为有个命名空间,所以才有了变量的作用域,比如一个函数就有自己独立的命名空间。

总的可分为有3类:

  • locals 函数内的名称空间,局部变量和形参
  • globals 全局变量的命名空间 比如函数定义所在模块的名字空间
  • builtins 内置模块的名字空间 比如len

作用域的查找顺序

LEGB

  • L:locals 当前
  • E:enclosing 相邻的上一级
  • G:globls
  • B:builtins
# 全局变量 ,顶头写,没有缩进,整个文件里面都生效,在最外面循环、条件等里面定义的也为全局
name='lhf'
li = '全局变量'

def change_name():
    global name
    # 声明name是全局变量,可读取和赋值。如果没有声明直接赋值,就默认为局部变量,
    # 如果没有申明就对变量内容追加、修改或者删除操作,会反复向上级寻找,直到找到在操作,
    # 全局变量global(上级变量nonlocal),申明必须写在对应赋值语句前面

    name='帅了'    # 全局变量
    li = ‘哈哈’       #局部变量,里面调用的时候屏蔽了全局变量
    print(name,li)

以下情况会报错

li = [1,2,3,4,5]

def printMyLi():
    print(li)
    li = ['a','b','c']
printMyLi()

# UnboundLocalError: local variable 'li' referenced before assignment
change_name()
print(name,li)
# 优先读取局部变量,能读取全局变量,
# 无法对全局变量重新赋值(除非之前声明为global),但是对于可变类型,可以对内部元素进行操作

name = "刚娘"
def weihou():
    name = "陈卓"
    def weiweihou():
        nonlocal name   # nonlocal,指定上一级变量,如果没有就继续往上直到找到为止
        name = "冷静"    #如果没有声明nonlocal,非定义的操作,往外层寻找变量
    weiweihou()
    print(name)

print(name)
weihou()
print(name)

# 刚娘
# 冷静
# 刚娘

3.函数及变量

egon老师的风湿理论

# 向前引用
def foo():
    print('from foo')
    bar()
foo()    # 报错
def bar():
    print('from bar')
-----------------------
def bar():
    print('from bar')
def foo():
    print('from foo')
    bar()
foo()   # 不报错
------------------------
def foo():
    print('from foo')
    bar()
def bar():
    print('from bar')
foo()  # 不报错
----------------------

4.递归函数

递归特性:
- 必须有一个明确的结束条件
- 每次进入更深一层的递归时,问题规模都应有所减小
- 递归效率不高,层次过多会导致栈溢出

示例:汉诺塔问题,将a上的盘子移动到c盘,可通过b盘,每次只移动一次,不管何时每个柱子上面小盘永远在上面

import time

count = 0
a = "A"
b = "B"
c = "C"

def towerOfHanoi(n,a,b,c):
    global count
    if n == 0:
        return
    else:
        towerOfHanoi(n - 1,a,c,b)   #之前的人想法将A上当前之上所有的盘子通过C转到B
        print("Move %s to %s" % (a, c))  #当前人移动A盘到C
        towerOfHanoi(n - 1,b,a,c)  #之后的人想法将B上所有的盘子通过A转到C
        count += 1

n = int(input("请输入需要移动的盘子个数\n>>>"))
towerOfHanoi(n,a,b,c)
print("总共移动步骤:",count)

res=time.sleep(10)   #休眠功能,默认按照秒计算
print('----------->')

递归练习

一、深度查询

    1. 打印所有的节点
    1. 输入一个节点名字,沙河, 你要遍历找,找到了,就打印它,并返回true

def print_point(location):
    if not location:
        return
    for i in location:
        print(i["text"])
        if i["children"]:
            print_point(i["children"])

def find_point(location,flag,text):
    if not location:
        return flag
    for i in location:
        if i["text"] == text:
            flag = True
            return flag

        if not flag and i["children"]:
            return find_point(i["children"],flag,text)

        if not i["children"]:
            return flag

menus = [
    {
        'text': '北京',
        'children': [
            {'text': '朝阳', 'children': []},
            {'text': '昌平', 'children': [
                {'text': '沙河', 'children': []},
                {'text': '回龙观', 'children': []},
            ]},
        ]
    },
    {
        'text': '上海',
        'children': [
            {'text': '宝山', 'children': []},
            {'text': '金山', 'children': []},
        ]
    }
]

print_point(menus)
print(find_point(menus,False,"123"))

二、二分法算法查找实现


def find_number(data,object_data,first_flag,end_flag):
    mind_flag = int((first_flag + end_flag) / 2)
    if object_data == data[mind_flag]:
        return mind_flag

    if first_flag == end_flag or first_flag +1 == end_flag:
        return None
    if object_data < data[mind_flag]:
        return find_number(data,object_data,first_flag,mind_flag - 1)
    else:
        return find_number(data,object_data,mind_flag,end_flag)


data = [1,3,5,7,8,9,12,13,14,15,23,24,25,36,39]
print(find_number(data,23,0,len(data) - 1))


5.函数的作用域

函数的作用域只跟函数声明时定义的作用域有关,跟函数的调用位置无任何关系,考虑作用域的时候,结合风湿理论,将函数看做变量(局部作用与全局作用,但不能申明globle nunlocal),function() 表示执行函数,name = function表示将函数的地址赋值给name,执行name()也可以调用函数
def test1():
    print('in the test1')

def test():
    print('in the test')
    return test1   # 返回函数的内存地址(加括号是运行)

print(test)
res=test()
print(res()) # test1()

# ---------------------------
name = 'alex'
def foo():
    name='linhaifeng'
    def bar():
        # name='wupeiqi'
        print(name)
    return bar
a=foo()
print(a)
a() # bar()

# -----------------------------
name = 'alex'
def t1():
    name = t1
    print(name)
    def t2():
        name = t2
        print(name)
        def t3():
            name = t3
            print(name)
            return t1
        return t3
    return t2
s = t1
print(s()()())

6.匿名函数

lambda 形参:返回值
匿名函数语法(一般和其他函数一起使用,不会单独使用),只能返回一个值(def定义的函数会将多个返回值处理成一个元组)

t = lambda x:x + "_sb"
print(t("alex"))

name = "alex"
t = lambda :name + "_sb"
print(t())


7.函数式编程介绍

编程方法论
- 面向过程:
- 面向对象:
- 函数式:编程语言定义的函数+数学意义上的函数(特有的风格)
- 一、不可变数据
- 函数中不用变量保存状态,不修改变量
- 二、第一类对象
- 函数及变量
- 高阶函数 1:函数接收的参数是一个函数名 2:返回值中包含函数

def foo(n): # n=bar
    print(n)

def bar(name):
    print('my name is %s' %name)

foo(bar)   # 把函数当作参数传给另外一个函数

foo(bar())
foo(bar('alex'))
-------------------------------------------
def bar():
    print('from bar')
def foo():
    print('from foo')
    return bar  #返回值中包含函数
n=foo()
n()
------------------------------------------
def hanle():
    print('from handle')
    return hanle   #返回值中包含函数
h=hanle()
h()

三、尾调用优化(尾调用递归优化)
在函数的最后一步调用另外一个函数(不一定是最后一行)

def test():
    print("from test")

def test1():
    print('from test1')
    test() #当调用这个函数的时候(最后一步),接下来也没有操作,所以当前函数状态不保存

def test2():
    print('from handle')
    return test1()  #!!这种情况当前函数也会被释放

def test3():
    print(“”)
    return test1() + 1   # 不会释放

8.map函数

map函数是遍历操作,对每个元素进行操作!

格式:new_variable = map(函数名,可迭代对象) 函数名可以用匿名函数或者其他定义的函数名(py2中返回的是列表)

num_l=[1,2,10,5,3,7]   # 实现里面的元素的平方

ret=[]    # for循环实现
for i in num_l:
    ret.append(i**2)
print(ret)

# --------------------------------------------

def map_test(array):  # 用函数实现
    ret=[]
    for i in num_l:
        ret.append(i**2)
    return ret
ret=map_test(num_l)
print(ret)
# ----------------------------------------

#终极版本(相当于map函数的原理)
def map_test(func,array):  # func=lambda x:x+1   arrary=[1,2,10,5,3,7]
    ret=[]
    for i in array:
        res=func(i)      # add_one(i)
        ret.append(res)
    return ret

num_l=[1,2,10,5,3,7]
print(map_test(lambda x:x+1,num_l))

# -----------------------------------
# 最终用法!
res=map(lambda x:x+1,num_l)
print('内置函数map,处理结果',res)


num_l = [1,2,3,4,5,6]
def reduce_one(item):
    return item - 1
print('传的是有名函数',list(map(reduce_one,num_l)))


msg='linhaifeng'
print(list(map(lambda x:x.upper(),msg)))


l=[1,2,3,4,5]
print(list(map(str,l)))   #将列表里面的每个元素转换为字符串


8.filter函数

filter函数是过滤函数

#终极版本
movie_people=['alex_sb','wupeiqi_sb','linhaifeng','yuanhao_sb']
#def sb_show(n):
#    return n.endswith('sb')
#--->lambda n:n.endswith('sb')

def filter_test(func,array):
    ret=[]
    for p in array:
        if func(p):
               ret.append(p)
    return ret
res=filter_test(lambda n:n.endswith('sb'),movie_people)
print(res)

# ------------------------------------------------------

#filter函数使用方法

movie_people=['alex_sb','wupeiqi_sb','linhaifeng','yuanhao_sb']
res=filter(lambda n:n.endswith('sb'),movie_people)
print(list(res))
print(list(filter(lambda n: n.endswith('sb'),movie_people)))


8.reduce函数

原理:

num_l=[1,2,3,100]
def reduce_test(array):
res=array.pop(0)
    for num in array:
       res+=num
    return res
print(reduce_test(num_l))

# num_l=[1,2,3,100]
# def reduce_test(func,array):
#     res=array.pop(0)
#     for num in array:
#         res=func(res,num)
#     return res
#
# print(reduce_test(lambda x,y:x*y,num_l))

#最终版本
num_l=[1,2,3,100]
def reduce_test(func,array,init=None):
    if init is None:
        res=array.pop(0)
    else:
        res=init
    for num in array:
        res=func(res,num)
    return res
print(reduce_test(lambda x,y:x*y,num_l,100))

reduce函数使用方法

from functools import reduce  # 需要导入模块
num_l=[1,2,3,100]
print(reduce(lambda x,y:x+y,num_l,1))
print(reduce(lambda x,y:x+y,num_l))

9.map reduce filter函数总结

处理序列中的每个元素,得到的结果是一个‘列表’,该‘列表’元素个数及位置与原来一样

map(lambda n:n ** 2,(1,2,3,4,5))

filter遍历序列中的每个元素,判断每个元素得到布尔值,如果是True则留下来

people=[
    {'name':'alex','age':1000},
    {'name':'wupei','age':10000},
    {'name':'yuanhao','age':9000},
    {'name':'linhaifeng','age':18},
]
print(list(filter(lambda p:p['age']<=18,people)))

reduce:处理一个序列,然后把序列进行合并操作

from functools import reduce
print(reduce(lambda x,y:x+y,range(100),100))
print(reduce(lambda x,y:x+y,range(1,101)))

10. 常用的内置函数

a = [1,2,3,4,5]
b = 998

print(all(a)) # 判断可迭代对象,全为True结果为True
print(any((1,[])))  # 判断可迭代对象,只要一个True,结果都为True


print(dir())       # 打印当前程序所有变量
print(dir(dict))   # 打印一个对象中的所有属性名

print(hex(b))      # 10进制转换成16进制
print(oct(b))      # 十进制变八进制
print(bin(b))      # 二进制

print(chr(3))      # 找出数字相关的ascii符号
print(ord('a'))    # 显示ascii对应的数字

print(ascii("adfawefa三大"))  # Return an ASCII-only representation of an object.


print(divmod(2,3)) # Return the tuple (x//y, x%y)求除数的整数部分和小数部分

d = {}
for i in range(5):
    d[i] = -i
print(d.items())  # items将字典里面的键值对弄成一个元组
print(sorted(d.items())) # sorted() #排序
print(sorted(d.items(),key=lambda x:x[1])) # sorted() # 指定key进行排序
print(sorted(d.items(),key=lambda x:x[1],reverse=True)) # 指定key进行排序并反转


# enumerate(iterable,parm) 将可迭代对象进行编序,默认从0开始,
for i,k in enumerate(d.values(),1):
    print(i,k)

# eval
msg = '4 ** 5'
print(eval(msg)) # 将字符串转换 单行代码 计算式 元组 字典 列表 有返回值
a = '1.1'
print(eval(a))   #将字符串提取内容转换为int

b= '[1,2,3]'
print(eval(b))   #将字符串提取内容转换为list

c = '(1,2,3)'
print(eval(c))   #将字符串提取内容转换为tupe

d = '{1:1,2:2,3:3}'
print(eval(d))   #将字符串提取内容转换为dict

e = '{1,2,3}'
print(eval(e))   #将字符串提取内容转换为set

f = '1,2,3,4'
print(eval(f))   #将字符串提取内容自动转换为tupe

g = '1+2 * 3 -2 / (-1 -1)'
print(eval(g))   #将字符串提取内容转换为四则运算

"""交互器写多行代码的方法
code = '''
pass
'''
"""

# exec() # 能将多行字符串转换成代码,没有返回值
code = """
for i in range(5):
    print(i)
"""
exec(code)

# isinstance() 判断是否为相关的对象
print(isinstance(1,int))  #判断对象是否为类的实例
print(isinstance('abc',str))
print(isinstance([],list))
print(isinstance({},dict))
print(isinstance({1,2},set))

# sum() # 求和
d = [1,2,3,4,5]
print(sum(d))

# bytearray() 高级玩儿法,可以原内存修改地址,
s = "ABC哈哈大圣"
s = s.encode("utf8")
s = bytearray(s)
s[0] = 97
print(s[5])
s[5] = 137
s = s.decode("utf8")
print(s)

# map filter reduce函数
map_ = list(map(lambda x:x**2,[1,2,3,4,5,6,7,8]))
filter_ = list(filter(lambda x:x % 2 == 0,[1,2,3,4,5,6,7,8]))
import functools
reduce_ = functools.reduce(lambda x,y:x + y,[1,2,3,4,5,6,7,8],2) # 最后一个参数2为初始值

print(map_)
print(filter_)
print(reduce_)


print("海峰","杠娘",sep="->") # sep指定分割的符号
print("海峰","杠娘",end="->") # end指定以什么结束
with open("print.txt","w",encoding="utf8") as f:
    print("海峰", "杠娘", sep="->",end="|",file=f) # 边打印边写入文件


# callable(a) 判断是否可调用,是否是函数
def a():
    pass
print(callable(a))


f = frozenset(s) # 不可变集合


locals()  # 函数的局部变量
globals() # 全局变量
repr(a)   # 返回规范化的字符串表示该对象的方法 ??

# zip将两个可迭代对象打包成一个对应元素的元组列表
print(list(zip([0,1,2,3],["a","b","c","d"])))


# compile('print.txt') # Compile source into a code object that can be executed by exec() or eval()
complex(3,5) # 复数
round(2.35434,3) # 保留几位小数
print(abs(-1))  # 取绝对值


name='你好'
print(bytes(name,encoding='utf-8'))  # 转换为字节,py3把除非Unique编码的汉字全部以16进制表示
print(bytes(name,encoding='utf-8').decode('utf-8'))  # 先编码,再解码

# hash() 哈希
# 可hash的数据类型即不可变数据类型,不可hash的数据类型即可变数据类型哈希运算(预防篡改)
print(hash('12sdfdsaf31231asdfasdfsadfsadfasdfasdf23'))

name='alex'
print(hash(name))


print(help(dict)) # 查看帮助信息

# 打印字典的key,value
p = {'name':'alex','age':16}
print(list(p.keys()),list(p.values()))
print(p.items())


print(pow(3,3))   # 3**3
print(pow(3,3,2))  # 3**3%2   #3的3次方然后取余


l=[1,2,3,4]
h = reversed(l) # 返回一个反转的列表迭代器
print(next(h))
print(l)


# slice() # 自定义切片功能
l='hello'
s1=slice(3,5)      # 定义切片(不收尾)
s2=slice(1,4,2)    # 定义切片(不收尾)指定步长为2
print(l[3:5])      # 直接切片
print(l[s1])       # 使用定义的切片取值
print(l[s2])       # 使用定义的切片取值,步长为2
print(s2.start)    # 查看定义的参数  开始位置
print(s2.stop)     # 查看定义的参数  结束位置(不收尾)
print(s2.step)     # 查看定义的参数  步长


# max min方法 注意!比较的值必须是同一个类型,否则报错
l=[1,3,100,-1,2]
print(max(l))   # 取最大值,从前到后一个一个比较(类型必须一样)(print(min(l))
# 取最小值min,用法一样)

age_dic={'alex_age':18,'wupei_age':20,'zsc_age':100,'lhf_age':30}
print(max(age_dic)) # #默认比较的是字典的key
print(max(age_dic.values()))
print('=======>',list(max(zip(age_dic.values(),age_dic.keys()))))  # 默认比较第一个参数



people=[
    {'name':'alex','age':1000},
    {'name':'wupei','age':10000},
    {'name':'yuanhao','age':9000},
    {'name':'linhaifeng','age':18},
]
# 终极玩儿法,指定每个元素中比较的内容,从而返回整个满足要求的元素
print(max(people,key=lambda dic:dic['age']))


print(set('hello'))  #变成一个集合的方式 鸭子类型转换
print(type("ss")) # 查看数据类型


print(vars()) # 打印当前作用域所有的变量值或者类型,是一个字典。



11.函数闭包

def bibao():
    name = "go"
    def baobao():
        print(name)
    return baobao   #闭包的效果,这种情况当return了,当前函数bibao没有被释放.

func = bigao()
func()

闭包面试题

补充:import导入方式 :import---调--->sys---调-->import()

import test   #test.py 这个写的模块,import不能导入字符串
test.say_hi()

import 'test'   #报错
module_name='test'
m=__import__(module_name)  #这种方式为导入字符串方式导入模块
m.say_hi()
posted @ 2018-07-20 23:09  哈哈大圣  阅读(178)  评论(0编辑  收藏  举报