Python3:函数和变量


1. 变量

1.1 全局变量

# 全局变量
"""
全局变量:
    global关键字添加
    只有不可变的类型才需要添加global
         int float str bool ()
    可变的类型不需要添加global
        list dist set()  列表、字典、集合
局部变量:
    仅限于函数内部

可变和不可变:
    可变:
        list dist set()  列表、字典、集合
    不可变:
        当改变变量的值,地址发生改变,就认为此类型不可变:
        int float str bool ()
"""
#  不可变 int float str bool ()
a = 1
print(id(a))
a = 2
print(id(a))
a = ''
print(id(a))
a = 'str'
print(id(a))
a = (1, 2, 3)
print(id(a))
a = (1, 2)
print(id(a))

#  可变


a = [1, 2, 3]
print(id(a))
a.remove(3)
print(id(a))

print('局部变量和全局变量'.center(30, '-'))

x = 100

# 局部
def pr():
    x = 8
    y = 10
    print(x)
    print(y)
# 全局
def pr2():
    print(x)

# 修改全局
def pr3():
    global x  # 必须声明了才可以动
    x = x - 80  # 不能轻易动全局变量
    print(x)

pr()
pr2()
pr3()
pr2()

1.2 局部变量,拆装包:*args 、**kwagrs

# 局部变量
"""

可变参数
    *args :默认装进一个元组();就是一个容器
    *kwargs
    argument

一颗星:*
    拆装包

        装包:
            def 函数(*arg): ---------->此时会出现装包操作
                pass
        拆包:list、tuple、set
            函数调用时:函数(*list)|函数(*tuple)|函数(*set)
                print(sm(1, *ram_lst))  # 调用加一个* 拆包
        拆包过程
两颗星:** #<class 'dict'>
    *kwargs:key word 关键字参数

    关键字参数赋值才可以;只要不是关键字参数会报错
    只有传递参数时key=value形式,才可以装包放进放到字典中

    只有** 才会装包

"""


# 多参数:求和
def sm(a, *args):
    print(type(args))  # args:是元组 <class 'tuple'>
    return a + sum(args)


print(sm(1, 2, 3, 4, 5))

x, *y, z = 1, 2, 3, 4, 5
print(x, y, z)  # 默认是放到列表中:1 [2, 3, 4] 5

# 拆包
x, y, z = (7, 8, 9)
print(x, y, z)
# 先拆包、后装包
x, *y, z = (7, 8, 9, 2, 3, 4, 5)  # 先拆包、后装包
print(x, y, z)

# 列表中元素的和
ram_lst = [12, 4, 6, 8, 345, 678, 24, 67, 1, 23]
print(sum(ram_lst))

print(sm(1, *ram_lst))  # 调用加一个* 拆包

print("两颗星:**".center(30, "—"))


def show_book(**kwargs):  # <class 'dict'> # 关键字参数赋值才可以;只要不是关键字参数会报错
    print(type(kwargs))
    print(kwargs)

    for k, v in kwargs.items():
        print(k, v, sep='->')


# 字典装包
show_book(name='张三', age=18, sex='男')  # 关键字参数赋值才可以;只要不是关键字参数会报错

# 字典拆包
book = {'name': '西游记', 'author': '曹雪芹', 'number': 5}
show_book(**book)  # 拆包

print("单星* 和两颗星:**都存在".center(50, "—"))


def show_all_book(*args, **kwargs):
    print(type(args))
    print(type(kwargs))
    print(args)  # ()
    print(kwargs)  # {}


book = {'name': '红楼梦', 'author': '曹雪芹'}
show_all_book('张三', '李四', **book)
show_all_book('张三', '李四', **{'name': '红楼梦', 'author': '曹雪芹'})  # 只有** 才会装包

print('{}{}{}'.format('AA', 'BB', 'CC'))
print('{name}->{age}'.format(**{'name': '张三', 'age': 18}))

result = '#'.join('A', 'B', 'C')
print(result)


2. 参数(有参、无参)

# 参数:就是在调用函数时,就是向函数中传值的作用
"""
无参:
    def 函数名()
        pass
有参:
    def 函数名(参数1,参数2,参数3)
        函数体
        pass
带多个参数的函数:
    多个参数
    默认值、关键字参数
默认值参数:(属于缺省参数,)
    def 函数名(参数1,参数2,参数3=值)
        pass
    def 函数名(参数1,参数2,*args,参数3=值)
        pass
    调用可以不给默认值参数赋值:
        函数名(值1,值2)

    注意:
        定义函数:普通参数要位于默认参数之前
            正确:def 函数名(参数1,参数2,参数3=值)
            错误:def 函数名(参数1,参数3=值,参数2)
"""


# 最多登录三次:retry_num:重试次数,默认三次
def login(retry_num=3):
    error_num = 1
    while error_num <= retry_num:
        username = input('请输入用户名:')
        password = input('请输入密码:')
        if 'admin'.__eq__(username) and '1234'.__eq__(password):
            return '登录成功'
        else:
            if retry_num - error_num > 0:
                print('用户名或者密码错误允许错误{}次,还有{}次'.format(retry_num, retry_num - error_num))
                error_num += 1  # 每错一次加1
            else:
                break
    return '用户名或者密码错误次数过多,请稍后重试!'


rst = login(4)
print(rst)

'''
求 1-n之间和;但是n必须是参数
'''


def sm(n):
    return sum(i for i in range(n + 1))


# 两个数求和
def get_sm(a, b):
    if type(a) == type(b) and isinstance(a, int) and isinstance(b, int):  # isinstance:类型判断
        return a + b
    else:
        return "类型不一致!"


# 调用
print(sm(100))
print(get_sm(1, 2))

# 借书



3. 函数

1. 什么是函数

# 函数基本操作
import random

"""
函数:复用
    定义调用:
        def 函数名([参数,...]): # [] 代表可有可无
            代码
        函数名: get_name() 多个单词下划线分割
                search()    单词
        代码: 封装重复内容
    调用机制:(函数名)
        1、先加载导内存
        2、使用必须调用     
    注意:
        1. 参数传递:类型属于对象,对象有不同类型的区分,变量是没有类型的: 
        2. 默认参数的顺序都是固定的,在赋值如果顺序不固定,需要关键字参数:参数名=value 如 login(name, password='1234') 
    参数:
        单参数、多参数
        形参、实参
"""


#  函数也是一个变量
def create_verification_code():
    code = ''
    while len(code) < 4:
        result = random.randint(0, 127)
        if ord('a') <= result <= ord('z') or ord('A') <= result <= ord('Z'):
            code += chr(result)
        elif 0 <= result <= 9:
            code += str(result)
    print(code)


print(create_verification_code)  # <function create_verification_code at 0x00000218317180D8>:函数也是一个变量,分配内存空间
# 验证函数是否可用
create_verification_code()

'''
定义一个login函数
admin 1234
输入用户名密码验证正确
'''


# 定义一个登录函数
def login(username, password, is_remember=False):  # 默认值参数
    if 'admin'.__eq__(username) and '1234'.__eq__(password):
        return '登录成功'
    else:
        return '用户名或者密码错误,登录失败!'


name = input('请输入用户名:')
pwd = input('请输入密码:')
rst = login(name, pwd)
print(rst)

rst = login(name, password='1234')  # 默认参数赋值
print(rst)

# 形参、实参

library = ['西游记', '红楼梦', '三国演义', '水浒传']


# 添加书
def add_book(book_name):
    library.append(book_name)


# 打印书
def show_book(books):
    for book in books:
        print(book)


add_book('明清那些事') # 添加书
print(show_book(library))

2. 函数参数注释

# 函数参数说明
"""
函数参数说明:
    def 函数名(参数1、参数2、参数3...):
        基本注释    ”注释内容“
        高级注释:
            ”“”
                参数说明:
                :param username: 用户名
                :param password: 密码

                返回值说明:
                :return: 是否登录成功
            “”“
"""


def login(username, password):
    """
    用户名密码登录
    :param username: 用户名
    :param password: 密码
    :return: 返回成功、失败
    """
    if username == 'admin' and password == '1234':
        "返回成功后业务逻辑"
        print("登录成功!")
    else:
        "返回失败后业务逻辑"
        print("登录失败!")


login("admin", "1234")

练习

# 练习 函数文档注释
"""

    局部变量:临时保存数据,函数调用完就回收
    全局变量:外侧,(global)
    注意:
        变量同名问题,局部变量>全局变量
"""
import datetime

lst = ['西游记', '红楼梦', '三国演义', '水浒传']


def show_book(books):
    return [book for book in books if book == '三国演义']  # 列表推导式


print(show_book(lst))

num_lst = [1, 4, 90, 35, 79, 34, 89, 12, 90, 34, 89, 26, 90, 99]


# 删除小于50
def remove_element():
    [num_lst.remove(n) for n in num_lst[::-1] if n < 50]  # 造成遗漏所以反向删除,那样即使下标变化不影响整体结果


print(num_lst)
remove_element()  # 删除小于50
print(num_lst)

print('函数使用练习'.center(50, '-'))

'''
需求:
验证时候登录:is_login
    自定义一个函数is_login:
        参数:username 、password
        函数体:
            判断用户输入的用户名和密码是否正确,如果正确则返回True,否则返回False
    借书:定义一个函数borrow_book
        参数:书名:book_name
        函数体:
            判断是否登录,如何登录则可以借书
            如果没有登录则提示:还未登录不能借书
'''

# 是否登录
is_rem = False


def is_login(username, password, is_remember=False):
    global is_rem  # 使用了全局变量名
    if username == 'admin' and password == '1234':
        is_rem = is_remember
        return True
    else:
        return False


# 借书
def borrow_book(book_name):
    if is_rem or login():
        print("登录成功,成功借阅%s!" % book_name)
    else:
        print("未登录不能借书,请登录!")
        n = 3
        while n > 0:
            if login():
                print("登录成功,您可以借书了!")
            else:
                n -= 1
                print("用户名/密码错误,您还有{}次重试机会!".format(n))


def login():
    name = input("请输入用户名:")
    pwd = input("请输入密码:")
    is_remember = bool(input("是否记住用户名密码(True/False):"))
    # 登录
    return is_login(name, pwd, is_remember)


# 借书
borrow_book('红楼梦!')  # 第一次需要登录,可以is_remember 不输入或者输入True
borrow_book('西游记!')  # 不需要再登录了

'''
全局变量:
    停车费:
        1小时4块钱、计算停车费
        15分钟一块钱
        {车牌:[进入时间,离开时间]}
    def enter():
        # 键盘输入车牌号
        pass
    def go_out():
        # 键盘输入车牌号
        pass
    def car_billing():
        # 计费
        pass
'''
start_time = datetime.datetime.now()
end_time = datetime.datetime.now()

# car_park = [{'陕A1234': [start_time, end_time]}]
car_park = []


def enter():
    """
    进入停车场:开始计费
    :return: NONE
    """
    print("欢迎进入xxx停车场".center(30, '-'))
    car_num = input('键盘输入车牌号:')
    global start_time
    start_time = datetime.datetime.now()
    print(start_time)
    car_info = {car_num: [start_time, end_time]}
    car_park.append(car_info)
    print("{}已经进入停车场".format(car_num))


def go_out():
    """
    出车计费
    :return: 返回计费信息
    """
    print("退出xxx停车场".center(30, '-'))
    car_num = input('键盘输入车牌号:')
    global end_time
    global car_park
    global end_time
    for car in car_park:
        if isinstance(car, dict):  # 可以替换(字典默认和key 比较): for car_num in car
            # 字典默认和key 比较
            for key in car.keys():
                if car_num == key:
                    end_time = datetime.datetime.now()
                    car.update({key: [start_time, end_time]})
    print(car_billing(car_num))


def car_billing(car_num):
    spend_time = 0
    for car in car_park:
        if isinstance(car, dict):
            car_time = car.get(car_num)
            print(car_time)
            if isinstance(car_time, list):
                print(car_time[1], car_time[0])
                spend_time = car_time[1] - (car_time[0])

                print("spend_time:", spend_time)
    return '停车时常{},总车费{}。'.format(spend_time, spend_time / 60 * 4)


enter()
go_out()

3.1 匿名函数

# 匿名函数 + 高级函数
"""
匿名函数定义:
    lambda 参数列表:运算表达式
    可以接受任何参数,但是只能返回一个表达式的值
使用场景:高阶函数(一个函数的参数是另一个函数,俗称高阶函数)
    1. 匿名函数作为参数使用
    2. 系统高阶函数:max  min sorted
    3. filter(匿名函数要求返回bool类型,且bool 类型为真才是过滤)
    4. map:提取、加工数据,组成迭代
    5. reduce
    6. zip
"""
from functools import reduce


def su(a):
    return a + 1


print(su)
print(su(5))

r = lambda b: b + 1

print(r)
print(r(5))

print("匿名函数:使用场景->高级函数".center(30, "-"))


def test(n):
    print("-------test----->", n)


def func(a, f):
    print("----func---->", a)
    f(a)


func(6, test)

print("--------------------------------------------------")

print("-------------匿名函数作为参数使用------------")


def func1(a, f):
    print("++++++++++", a)
    print("=========>", f(a))


func1(5, lambda x: x ** 2)  # 匿名函数作为参数传递

print("-------------系统高阶函数------------")

lst = [("tom", 20), ("Tony", 23), ("rose", 30), ("Lily", 10)]

result = max(lst, key=lambda x: x[1])
print(result)
result = min(lst, key=lambda x: x[1])
print(result)

result = sorted(lst, key=lambda x: x[1])

print(result)
result = sorted(lst, key=lambda x: x[1], reverse=True)  # 从达到小

print(result)

result = filter(lambda x: x[1] > 18, lst)  # filter过滤

print(list(result))

result = map(lambda x: x[1] + 1, lst)  # map  映射,提取出来
print(result)
print(list(result))

result = map(lambda x: x[0].title(), lst)  # map  映射,提取,加工出来
print(result)
print(list(result))

resu = reduce(lambda x, y: x + y, [1, 2, 3, 4, 5])  # 就是一种运算

print(resu)

result = zip(lst)

print(result)

3.2 带返回值函数

# 函数返回值

"""
参数:外界向里面传值
返回值:里面的内容向外界传值
    def  函数名(参数名):
        函数体
        return 返回值
    调用:
        通告return 向外返回值;只要返回就需要接受数据
    注意:Python独有的特性:
        返回多个值:会以元组形式返回(a,b)
        return:可以结束调用

"""


def get_sum(*args):
    return sum(args)


print(get_sum(*[1, 1, 2, 3, 4, 5]))  # 解包

lst = [1, 3, 2, 9, 4, 5, 13, 56, 34, 23, 67]


# 求最大最小值:返回两个值:元组()
def get_max_min(num_lst):
    return min(num_lst), max(num_lst)


print(get_max_min(lst))  # (1, 9)
a, b = get_max_min(lst)
print(a, b)  # (1, 9)

print('冒泡排序'.center(30,'-'))
# 冒泡排序

for i in range(len(lst) - 1):
    for j in range(len(lst) - i - 1):
        if lst[j] > lst[j + 1]:
            lst[j], lst[j + 1] = lst[j + 1], lst[j]
print("升序:", lst)

for i in range(len(lst) - 1):
    for j in range(len(lst) - i - 1):
        if lst[j] < lst[j + 1]:
            lst[j], lst[j + 1] = lst[j + 1], lst[j]
print("降序:", lst)

3.3 递归函数

# 递归函数

"""
文件遍历
"""


# 1-10 数字的累加

def count(n):
    if n > 0:
        n -= 1
    else:
        return n  # 考虑结束
    return n + count(n)


print(count(10 + 1))  # 通过递归求1-10 的和
print(count(100 + 1))  # 通过递归求1-100 的和

print("递归实现斐波那契数列".center(30, '-'))


# 递归实现斐波那契数列,并打印

def fibonacci(n):
    if 0 < n <= 2:
        return 1
    result = fibonacci(n - 1) + fibonacci(n - 2)
    return result


for i in range(1, 10):
    print("------------>", fibonacci(i))

3.4 闭包+嵌套

# 函数闭包+嵌套

""""
嵌套:
    注意:
        1. 内部函数可以使用外部函数的变量
        2. 内部函数不能修改外部函数的变量,nonlocal a  可以修改外部函数变量需要再内部函数中,添加nolocal
闭包:(函数、变量都是如下顺序)
    内层函数-------> 全局函数--------->外层函数-------->系统函数(builtins)
    闭包三个特点:
        1. 嵌套函数
        2. 内部函数引用了外部函数的变量
        3. 返回值是内部函数
    使用场景:
        装饰器使用
"""


def outer():
    a = 100

    def inner():
        nonlocal a  # 引用外函数变量
        b = 200
        b += a
        a += b
        print("我是内函数!", b)

    result = locals()  # 局部变量查看,以字典形式返回:{'a': 100, 'inner': <function outer.<locals>.inner at 0x00000247463281F8>}
    print(result)
    print(a)
    print(inner)  # <function outer.<locals>.inner at 0x0000017531E381F8>
    inner()  # 调用
    print(a)  # a 被 nonlocal  局部函数修改

    return inner


r = outer()  # <function outer.<locals>.inner at 0x00000236F60381F8>

print(r)

print("闭包".center(30, '*'))

r()  # 调用内部函数

3.5 装饰器

# 装饰器
"""
装饰器:
    原则:遵循开放封闭原则,在不改变原函数的情况下,扩展了函数功能
    特点:
        1. 日志、权限校验、缓存
        2. 统计
    定义:
        def aaa(func):
            def xxx(参数,...):
                ....
                func()
                ...
            return xxx
    装饰:
        @aaa
        def 原函数():
            pass

    代参数装饰器:*arg,**kwargs
        原函数有参数,装饰器必须也有参数
        *arg:可变参数
        **kwargs:关键字参数
    装饰器修饰有返回值的函数:
        原函数有返回值,wrapper中必须有返回值

再入装饰器:



"""


def foo():
    print("foo")


def func():
    print("func")


foo = func  # 函数名仅仅是一个变量,相当于变量赋值,地址发生改变

foo()

print("装饰器".center(20, "#"))


def deco_house(fu):
    """
    1. 定义装饰器:装修房子
    :param fu : 被装饰着的引用
    :return wrapper : 返回被装饰后的对象 的地址  ;相当于house_a 装饰前后的地址发生变化
    相当于house_a = house-----地址指向发生改变----->house_a = wrapper
    """

    def wrapper():
        fu()
        print("安装家电----->")
        print("安装床沙发----->")
        print("精装修完成----->")

    return wrapper  # 返回内部函数


@deco_house  # 就会调用deco_house函数--->house_a = deco_house(house_a)
def house_a():
    print("毛坯房A")


@deco_house
def house_b():
    print("毛坯房B")


house_a()
house_b()

print("带参数的装饰器".center(30, '*'))


def de_house(fu):
    def wrapper(*args, **kwargs):  # wrapper() got an unexpected keyword argument 'name':(name="香格里拉大酒店")  修改添加**kwargs
        fu(*args, **kwargs)  # fu 就是house;元组拆包(带星拆元组):*args
        print("安装家电----->")
        print("安装床沙发----->")
        print("精装修完成----->")

    return wrapper  # 返回内部函数


@de_house
def house(address):
    print("房子的地址在:{},是一个毛坯房".format(address))


@de_house
def chang_fang(address, area):
    print("房子的地址在:{},是一个毛坯房。建筑面积是:{}平米".format(address, area))


@de_house
def hotel(name, address, area=40):
    print("{}的地址在:{},是一个毛坯房。单间建筑面积是:{}平米".format(name, address, area))


house("西安钟楼")

print("--------------------------")

chang_fang("西安雁塔区", 130)
print("------------默认参数--------------")
hotel("全季大酒店", "西安雁塔区")
print("------------指定默认参数--------------")
hotel("全季大酒店", "西安雁塔区", 80)
print("----------关键字参数----------------")
hotel(name="全季大酒店", address="西安雁塔区", area=80)
print("----------关键字参数:修改顺序----------------")
hotel(address="西安高新区", name="香格里拉大酒店", area=150)

print("装饰器修饰有返回值的函数".center(30, '*'))


def make_house(fu):
    def wrapper(*args, **kwargs):  # wrapper() got an unexpected keyword argument 'name':(name="香格里拉大酒店")  修改添加**kwargs
        r = fu(*args, **kwargs)  # fu 就是house;元组拆包(带星拆元组):*args
        print("预计装修费用是:{}元".format(r))
        print("安装家电----->")
        print("安装床沙发----->")
        print("精装修完成----->")
        return r  # 原函数有返回值,wrapper中必须有返回值

    return wrapper


@make_house
def new_house():
    print("毛坯房....")
    return 50000


result = new_house()
print(result)

4. 复习

4.1 函数复习

# 函数复习
import sys

"""
函数返回值  :  return
    return 返回一个或者多个值,也可以单独使用return关键字
    return :表示函数结束调用 类似于break;是不过 break 中断当前循环还会执行循环后面的操作,而return 直接结束函数,后面不执行
    return a
    return a,b ------------>(a,b)

全局变量和局部变量
    全局变量
        1. 什么是全局变量、全局变量的位置
            全局变量可以直接用,但是不能再函数中修改
        2. 全局变量是不可变类型:
            不可再函数中修改,如果要修改必须加global 关键字声明
        3. 全局变量是可变类型
            函数中可以修改
        4. globals() 函数:可以查看全局变量
    局部变量(函数):
        1. 函数内部定义的便令
        2. 使用范围仅限函数内部;当函数调用结束就会回收变量(生命周期就在内部)
        3. 通络 locals 查看局部变量----> 字典
        4. 内部函数也可以看成局部变量
可变参数和不可变参数:
    当前的值和地址的关系:
        可变:值变了,地址没变; dict  list  set
        不可变:值变了 地址也变了; int str bool tuple  float

地址引用:传递一个地址
    1. 普通的赋值关系:
        调函数也会出现一次引用
    2. 函数参数
        函数参数类型是什么:可变还是不可变
函数嵌套:

闭包(装饰器):
    1. 必须是嵌套函数
    2. 内部函数引用外部函数变量
    3. 返回值是内部函数
"""

print(globals())  # 查看全局变量:返回格式字典:1.系统的全局变量 2. 自定义的全局变量

lst = [1, 2, 3]
lst1 = lst

print(sys.getrefcount(lst1))  # 因为调用会引用一次,所以结果是3

4.2 总结

# 总结

"""
函数:
作用域:LFGB
L: local 本地 局部变量
F:encloseing 嵌套
G:Global 全局
B:built-in 内置函数
嵌套函数:
闭包:
    1. 内层函数
    2. 内层函数引用外层函数的变量
    3. 返回内层函数
    4. 函数作为外层函数的参数
使用装饰器:
@ 装饰器名
def 函数名():
    pass

# 总结函数
普通函数
    1. 无参数:
    def func():
        pass
    2. 有参数
        一般参数:
            def func(a,b):
                pass
        可变参数:
            def func(*args,**kwargs):  args 单个元素; kwargs:关键字参数
                pass
            func() 、func(1) 、func(a=1)
        默认值:
            def func(a=1,b=2):
                pass
            func(a=100) #关键字参数
            func(900) #默认给a赋值
    3. 返回值
        没有返回值
            def func():
                pass

            x = func() ------->X=None
        有返回值:
            def func():
                return 'a','b' # 返回多个值

            x = func() ---------> x= ('a','b')
嵌套函数:------->闭包--------> 装饰器
    1.闭包:
        def  func():
            def wrapper():
                pass
            return wrapper()
    2. 装饰器:
        单层装饰器:
            def decorate(func):
                def wrapper(*args,**kwargs):  # 有参数和无参数都可以
                    pass
                return wrapper
            @decorate
            def house():
                pass
            @decorate()
            def new_house(a,b):
        多层装饰器:
            @deco2()
            @deco1()
            def func(a,b):
                pass
        装饰器带参数:
            def outer(a):
                def  decorate(func):
                    def wrapper(*args,**kwargs):
                        pass
                    return wrapper
                return decorate

            @outer(10)
            def house(10):
                pass
            @outer(100)
            def house(10):
                pass
匿名函数:lambada 函数:返回值
递归函数:自己调用自己

变量的作用域:
    global nonlocal
    globals locals
    LFGB



"""

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值