掉进悬崖的小白,学python时被拉进函数漩涡,参数类型灌入脑中,学会复用代码 DRY,局部变量和全局变量的冲突解决。猜数游戏,数字转换大写汉字,随机赋不重复值。

掉进悬崖的小白,学python时被拉进函数漩涡,参数类型灌入脑中,学会复用代码 DRY,局部变量和全局变量的冲突解决。猜数游戏,数字转换大写汉字,随机赋不重复值。

函数(function)

函数论:

广义:
为获得某种东西或达到某种目的而采取的手段与行为方式。

狭义:
函数是指由一系列的程序语句组成的代码块

特性:

1.带名字的代码段
2.函数是代码重复使用的重要手段,是重用的基本手段:
无论现实世界还是程序世界,都以函数来达到重用的目的

定义函数

定义语法:[]表示可选 <>表示必备
<函数名>([参数列表])<:>
# 待执行语句
# 如果有需要显式返回<return 标识符>或
用缩进块来表示函数体,是函数的管辖区块

函数可以出现的位置:
模块(moudle)、类(class)、函数(function)中

命名规范:
函数名、参数名全部小写,多语义用_连接,函数名、参数名要尽量有意义。

调用函数

函数的目的在于重用,所有的函数编写完成后,都处于等待调用状态,被调用后函数开始执行,直到函数返回(有无返回值均必须返回)

函数大多数会在其他函数内部或模块内被调用
注意:模块内调用时注意只能调用该行语句之前出现过的函数
原因:代码自上向下执行

调用的规则:

1.调用者和被调用者相互可见
采用直接调用的方式
示例:
def func1():
print(“函数1”)
pass

func1() # 调用函数func1

2.调用者和被调用者相互不可见
先import模块再调用:注意调用时带上模块.
示例:
be_call_functions.py:
def be_call():
return “test” # 此处返回
call_functions.py:
import be_call_functions

be_call_functions.be_call()

3.特殊的调用方式
析构函数等魔法函数需要用特殊的方案调用
例如:
析构函数由系统自行调用等等
后续会逐步学到

返回值类型:

所有函数都需要返回
只是没写return的会自动返回None
函数有无返回值取决于函数的调用者是否需要返回值
注意:
函数遇到return立即退出并返回 so也常作为控制方法结束的手段
思考:了解
若返回值数量超过1个怎么办?
默认多返回:return a, b, c, d…
或者使用列表等其他容器返回
一般这样接收结果:
ret1, ret2, ret3 = func_return()

参数

参数分为两种类型:

形式参数:由函数编写者在预定义时限定
实际参数:任意的数据类型(为形参赋值)在函数的调用者中定义赋值,在实际调用(使用)函数的时候 传入函数的参数

声明和传参:
形式参数:
def area(radius): # radius即为形式参数
return 3.14*radius**2

实际参数:
r = 5
print(area®) # r即为实际参数

// 传参的实质:用实际参数为形式参数赋值
radius = r

位置参数:固定位置的参数

def func_args(arg1, arg2, arg3):
print(arg1, arg2, arg3)
调用时传实参时按位置传递:
func_args(1, 2, 3)
结果:1 2 3
也可以:
func_args(arg3=3, arg1=1, arg2=2)

默认参数:可以为参数设定默认值 调用时可以选择使用默认值而不传实参

def func_args(arg1=1, arg2=2, arg3=3):
print(arg1, arg2, arg3)
调用时传实参:
func_args()
结果:1 2 3
也可以:
func_args(3, 2, 1)
func_args(arg3=6, arg1=6, arg2=6)

命名关键字参数:*

以后的参数全部为显式命名传参的参数
注意:命名关键字参数和可变参数不能同时出现
def func_args(
, arg1, arg2, arg3):
print(arg1, arg2, arg3)
调用时传实参:必须显式命名传参
func_args(arg3=6, arg1=6, arg2=6)

可变参数:*args

可以选择传递0-n个参数
注意:可变参数无法和命名关键字参数同时出现
def func_args(*args):
for i in range(len(args)):
pri nt(args[i])
调用时传实参:
func_args()
func_args(1)
func_args(1, 2)
func_args(1, 2, 3…,n)

参数的传递

参数传递需要明白的要点:
形参的修正对实参的影响程度

参数传递的方式:
形式参数 = 实际参数

传参规则:
根据形式参数类型的不同 对实际参数的影响B程度也不相同
A:不可变类型:字符串、数字、布尔、元组
B:列表、类、对象、集合、字典

函数内部形参修正对函数外实参的影响程度:
A:不影响实际参数(同上述A:不可变类型)
B:影响实际参数(同上述B:可变类型)

不可变类型传参:形参的修改不会传递给实参 推荐

def swap(x,y):
x, y = y, x # 形参x,形参y交换数据

x = 666 # 实参x 都叫x,但意义不同
y = 888 # 实参y 都叫y,但意义不同
swap(x, y) #参数传递 形参x = 实参x 形参y = 实参y
print(“实参x =”, x, “实参y=”, y)
结果:实参x = 666 实参y= 888

可变类型传参:形参的修正会传递给实参

def change_list(arg_list):
arg_list[1] = 666

my_list = [1, 2, 3, 4]
change_list(my_list)
print(my_list)
结果:[1, 666, 3, 4]

局部变量:

在函数内部声明并使用的数据量,随函数的启动而出生,随函数的退出而消亡
作用域在函数内
def fun(x):
y= 2
print( “乘法的运行结果:” , x * y)
print( “y的值是:”, y)
报错的原因是因为试图访问局部变量,但是访问的地方不在该变量y的作用域中

全局变量

在模块中直接声明使用的数据量,整个模块中可以使用
作用域在模块内
g_num=“我属于模块 在模块内的任意地方都可使用”
def visitor_g1():
print(g_num)

def visitor_g2():
print(g_num)

visitor_g1()
visitor_g2()
print(g_num)

冲突场景

1.函数内修改全局变量会被解释器认为新声明了一个局部变量

例:
num = 10

def set_num(in_num):
num = in_num
pass

set_num(111)
print(num)
结果:10

解决办法:global关键字
num = 10

def set_num(in_num):
global num
num = in_num
pass

set_num(111)
print(num)
结果:111

2.在函数内新声明的局部变量和全局变量同名,但是又想使用全局变量
discount = 0.9 # 全场9折

def pay(money):
discount = 0.8 # 折上折
print(“请pay:”, money * discount * discount)
pass

pay(10000)
结果:请pay: 6400.0

解决办法:globals()函数
discount = 0.9 # 全场9折

def pay(money):
discount = 0.8 # 折上折
print(“请pay:”, money * globals()[“discount”] * discount)
pass

pay(10000)
结果:请pay: 7200.0

有趣练习题

##持续获取用户输入,直到用户输入的字符串中既有字母又有数字。

def task5():
    while 1:
        str1 = input("输入一个既有字母又有数字的消息:")
        # 做检测
        is_have_char = False
        is_have_num = False
        for i in range(len(str1)):
            if "0" <= str1[i] <= "9":
                is_have_num = True
            if "A" <= str1[i] <= "Z" or "a" <= str1[i] <= "z":
                is_have_char = True
            # 为了性能 提前中断
            if is_have_char and is_have_num:
                break
        else:
            continue
        break
    return str1


# print(task5())

有一个长度为62的字符列表,请为这个列表随机赋值(a-z A-Z 0-9)要求每个下标位置的字符都不重复。

def task6():
    chars = []
    while len(chars) != 62:
        # 随机出62个字符当中的一个
        # ord(字符)可以得到该字符的数字表示
        random_char_num = random.randint(ord("0"), ord("z"))
        # 48-57 65-90 97-122
        if ord("9") < random_char_num < ord("A") or ord("Z") < random_char_num < ord("a"):
            continue
        # chr(数字)->字符
        char = chr(random_char_num)
        if char not in chars:
            chars.append(char)
    return chars


# print(task6())

写一个函数将整型数字(int 不含0)转换为汉字大写格式。例:111=>壹佰壹拾壹

说明:

# 167891111
# 使用列表:
# 汉字列表:["零","壹","贰","叁","肆","伍","陆","柒","捌","玖"]
#            0    1    2    3    。。。。                 9
# "167891111"=>"1"->汉字[int("1")]
# 单位:["圆", "拾", "佰", "仟", "万", "拾", "佰", "仟", "亿", "拾", "佰", "仟", "万"]
#        0    1    2     3   4    5    6    7.....
# "167891111"
#  012345678
#  876543210:len-1-i:单位[len-1-i]

解题:

def task7(num):
    # 做数字位数的限定
    if len(str(num)) > 13:
        print("暂时不支持13位以上的转换!")
        return
    # 准备汉字和单位列表
    zhs = ["零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"]
    units = ["圆", "拾", "佰", "仟", "万", "拾", "佰", "仟", "亿", "拾", "佰", "仟", "万"]
    # 设定转换后的字符串
    ret = ""
    num_str = str(num)
    for i in range(len(num_str)):
        ch = num_str[i]
        ret += zhs[int(ch)] + units[len(num_str) - 1 - i]
    return ret


# print(task7(123456789))

随机赋值,不重复操作

# 14.使用Random类给一个列表的所有元素赋随机初值(不重复)。
def task14():
    # 为10个位置的列表找到10个各不相同的随机数(1-10)
    # 为每一个位置找不重复的随机数
    # 定义一个列表
    # nums = [0] * 10
    # for i in range(len(nums)):
    #     while 1:
    #         # 为i位置找到和之前位置不同的随机数
    #         random_num = random.randint(1,10)
    #         if random_num not in nums:
    #             nums[i] = random_num
    #             break
    # nums = []
    # while len(nums) != 10:
    #     random_num = random.randint(1, 10)
    #     if random_num not in nums:
    #         nums.append(random_num)
    # return nums

    # 为数字找随机位置:洗牌算法
    # nums = [0] * 10
    # for i in range(1, 11):
    #     while 1:
    #         # i:1-10
    #         # 随机位置
    #         random_index = random.randint(0, len(nums) - 1)
    #         # 找到了一个随机位置
    #         # 判断该位置是否已经有数字了
    #         if nums[random_index] == 0:
    #             nums[random_index] = i
    #             break

    # 使用随机打乱方式获取不重复数据
    nums = list(range(1, 11))
    random.shuffle(nums)
    return nums


# print(task14())

猜数游戏

# 23.猜数游戏
# 1.随机出现一个数(范围自定义) 作为答案
# 2.提示用户输入并根据答案和用户输入的大小关系输出大了? 小了?
# 3.5次机会
# 4.可以重复玩
# 5.根据猜对的次数进行评价
# 6.无论对错 请告知答案
#
def repeat_play():  # 定义重复玩函数
    while True:
        guess_nums()
        an = input("是否退出游戏?(y/n)")
        if an == "y":
            return False


def guess_nums():  # 猜数游戏
    i = 0
    game_answer = random.randint(0, 100)
    while i < 5:
        user_answer = in_int()
        # print(game_answer)
        i += 1
        if user_answer == game_answer:
            break
        print(f"第{i}次你猜{user_answer}大了") if user_answer > game_answer else print(f"第{i}次你猜{user_answer}小了")
    print(f"本轮随机答案为:{game_answer}")
    print(f"{i}次猜对,欧皇附体!") if i == 0 else print(f"{i}次猜对,运气真好!") \
        if i == 1 else print(f"{i}次猜对,猜的不错!") if 4 > i > 1 else print(f"{i}次猜对,太及时了!") \
        if i == 4 else print("本次游戏未猜中,继续努力!")


# guess_nums()
# repeat_play()

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章