Python3入门学习二.md

时间:2022-07-28
本文章向大家介绍Python3入门学习二.md,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

[TOC]

5.数据类型转换

数据类型的转换你只需要将数据类型作为函数名即可,还有几个内置函数可以执行数据之间的转换,这些函数返回一个新的对象,表示转换的值;

数据类型转换函数列表: int(x [,base = 10]) #将x转换为一个整数类型,或者指定一个进制类型进行转换成为整形(返回整型数据) float(x) #函数用于将整数和字符串转换成浮点数 str(x) #将对象 x 转换为字符串 complex(real [ ,imag ]) #用于创建一个值为 real + imag * j 的复数或者转化一个字符串或数为复数(如果第一个参数为字符串,则不需要指定第二个参数。。) repr(x) #将对象 x 转换为表达式字符串,为供解释器读取的形式; tuple(s) #将序列 s 转换为一个元组 list(s) #将序列 s 转换为一个列表 set(s) #转换为可变集合 dict(d) #创建一个字典d必须是一个序列 (key,value)元组。 chr(x) #将一个整数转换为一个字符 hex(x) #将一个整数转换为一个十六进制字符串 oct(x) #将一个整数转换为一个八进制字符串 ord(x) #将一个字符转换为它的ASCII整数值 frozenset(s) #返回一个冻结的集合,冻结后集合不能再添加或删除任何元素,参数iterable-可迭代的对象,比如列表、字典、元组等等。

案例:数据类型转换函数使用

#!/usr/bin/python3
#coding:utf-8
#功能:数值类型转换内置函数

print("整形 : 0xa=",int('0xa',16)," 0x12=",int('12',16)," 010=",int('10',8)) 
                                        #以16进制转换为整形,和8进制转换成为整形
print("浮点 :",float('123'),float(1))  #浮点类型
print("复数 :",complex(1,2),complex("1+2j"))  #转化一个字符串或数为复数 
#注意:这个地方在"+"号两边不能有空格,也就是不能写成"1 + 2j",应该是"1+2j",否则会报错

cdict = dict(zip(['one', 'two', 'three'], [1, 2, 3]))   # 映射函数方式来构造字典

print(str(cdict))  # 将对象转化为字符串形式。
print(repr(cdict))  # 将对象转化为供解释器读取的形式。

print(eval(' 2 ** 2'),eval('pow(2,2)'))  # 执行一个字符串表达式,可以执行python的一些数学函数和计算

print(set('runoob'),set('google'))       # 集合中重复的值被删除 set
print(frozenset(range(10)))              # 生成一个新的不可变集合 set

print(chr(48),chr(65),chr(97))       #将ASCII码 ==> 字符
print(ord('0'),ord('A'),ord('a'))    #将字符  ==> ASCII
print(hex(255),hex(15))
print("255 oct =",oct(255),"10 oct =",oct(10))

Python数据类型转换函数使用

6.操作符以及优先级

Q: 什么是运算符? A:让变量进行加减乘除四则运算;

运算符及其优先级:

  • 算术运算符
  • 右移/左移运算符
  • 位运算符
  • 比较(关系)运算符
  • 等于运算符
  • 赋值运算符
  • 身份运算符
  • 成员运算符
  • 逻辑运算符

Python优先级

Python优先级详细

Python中的按位运算法: 按位运算符是把数字看作二进制来进行计算的。

& 按位与运算符:参与运算的两个值,如果两个相应位都为1,则该位的结果为1,否则为0。 | 按位或运算符:只要对应的二个二进位有一个为1时,结果位就为1。 ^ 按位异或运算符:当两对应的二进位相异时,结果为1 ~ 按位取反运算符:对数据的每个二进制位取反,即把1变为0,把0变为1。(~x 类似于 -x-1 ,在一个有符号二进制数的补码形式)。

<< 左移动运算符:运算数的各二进位全部左移若干位,由”<<”右边的数指定移动的位数,高位丢弃,低位补0。 >> 右移动运算符:把 “ >> “左边的运算数的各二进位全部右移若干位,”>>”右边的数指定移动的位数 。

Python语言支持逻辑运算符:(类似玉C语言短路求值 && )

x and y 布尔”与” - 如果 x 为 False,x and y 返回 False,否则它返回 y 的计算值。 x or y 布尔”或” - 如果 x 是 True,它返回 x 的值,否则它返回 y 的计算值。 not x 布尔”非” - 如果 x 为 True,返回 False 。如果 x 为 False,它返回 True。

Python成员运算符:

包含了一系列的成员,包括字符串,列表或元组。 in 如果在指定的序列中找到值返回 True,否则返回 False。 not in 如果在指定的序列中没有找到值返回 True,否则返回 False。

Python身份运算符:

is 是判断两个标识符是不是引用自一个对象 x is y, 类似 id(x) == id(y) , 如果引用的是同一个对象则返回 True,否则返回 False is not 是判断两个标识符是不是引用自不同对象 x is not y , 类似 id(a) != id(b)。如果引用的不是同一个对象则返回结果 True,否则返回 False。

案例:Python各种操作符

#!/usr/bin/python3
#coding:utf-8
#功能:特殊运算符号验证demo
#"""Python算术运算符"""
print("2 / 4 = ", 2 / 4)   #除法 , 得到浮点数
print("2 // 4 = ",2 // 4)  #除法 , 得到整数
print("2 ** 4 = ",2 ** 4)  #乘方 ,(优先级最高)
print("5 % 4 = ",5 % 4)   #取余 ,

#"""比较运算符###
a = 1
b = 2
if ( a == b ):
   print ("1 - a 等于 b")
else:
   print ("1 - a 不等于 b")

#"""赋值运算符###
c = a + b
c += 1
print("C值为:",c)
c **= c
print("C值为:",c)

#"""Python位运算"""
a = 1
b = 8
print("a&b = ", a&b)  #与
print("a|b = ", a|b)  #或
print("a^b = ", a^b)  #亦或
print("~a = ", ~a)    #取反
print("a<<2 = ", a<<2)   #左移动

#"""Python逻辑运算符"""
a = 1
b = 2
print((a and b))  #如果 x 为 False,x and y 返回 False,否则它返回 y 的计算值。
print((a or b))   #如果 x 是 True,它返回 x 的值,否则它返回 y 的计算值。
print(not(a or b)) # 如果 x 为 True,返回 False 。如果 x 为 False,它返回 True。


#"""Python成员运算符"""
a = 10
b = 5
list = [1, 2, 3, 4, 5 ]
if(a in list):
    print("a 在list列表里面")
else:
    print("a 不在list列表里面")

if(b not in list):
    print("a 不在list列表里面")
else:
    print("b 在list列表里面")

#"""Python成员运算符"""
a = 20
b = 20
if ( a is b ):
   print ("1 - a 和 b 有相同的标识")
else:
   print ("1 - a 和 b 没有相同的标识")
#注: id() 函数用于获取对象内存地址
if ( id(a) == id(b) ):
   print ("2 - a 和 b 有相同的标识")
else:
   print ("2 - a 和 b 没有相同的标识")


a,b,c,d,e = 20,10,15,5,0
#"""算术运算符优先级验证""" 
e = (a + b) * c / d       #( 30 * 15 ) / 5
print ("(a + b) * c / d 运算结果为:",  e)
 
e = ((a + b) * c) / d     # (30 * 15 ) / 5
print ("((a + b) * c) / d 运算结果为:",  e)
 
e = (a + b) * (c / d);    # (30) * (15/5)
print ("(a + b) * (c / d) 运算结果为:",  e)
 
e = a + b * c / d;      #  20 + (150/5)
print ("a + (b * c) / d 运算结果为:",  e)

Python各种操作符案例

注意事项: 1)数值的除法包含两个运算符:/ 返回一个浮点数,// 返回一个整数。 2)在混合计算时,Python会把整型转换成为浮点数。 3)is 与 == 区别,前者用于判断两个变量引用对象是否为同一个, 后者用于判断引用变量的值是否相等。 4)逻辑运算符是 not、and 、or优先级 5)幂指数 ** 比左侧的优先级高,比右侧的优先级低 6)使用 (x>y)-(x < y) 来判断x/y是否相同,如果 x < y 返回 -1, 如果 x == y 返回 0, 如果 x > y 返回 1

7.Python流程控制语法

7.1 条件控制与循环

7.1.1 分支语句:if elif else

分支语法:

if 表达式:
    执行语句
elif 表达式:
    执行语句
else:
    执行语句
    
#三元操作符    
x if 条件 else y    //如果条件为真时候将x值赋给small,为假时候将y值赋给small


#else 语句
1) else 语句跟 if 语句搭,构成“要么怎样,要么不怎样”的语境
2) else 语句跟 for / while 语句搭,构成“干完了能怎样,干不完就别想怎样”的语境
2) else 语句跟 try 语句搭构成“没有问题,那就干吧”的语境

注意事项: 1) 由于Python中无{}包含代码块,而是采用缩进的方式来判别执行的代码块; 2) 与for/while语句搭配时候,只有在循环正常执行完成后才会执行 else 语句块的内容

7.1.2循环语句:while , for..else…

退出循环关键字:break,continue,及其循环语法:

while (表达式条件):
          为真则执行代码块
else:
        语句为 false 时执行该 else 的语句块: 
  
  
for 变量 in 表达式:
          循环体
else:
          它在穷尽列表(以for循环)或条件变为 false (以while循环)导致循环终止时被执行,但循环被break终止时不执行。

案例:条件控制于循环语句

#!/usr/bin/python3
#coding:utf-8
#功能:分支与循环
#-----------if 语句-----------------
guess = 8
temp = int(input("请输入一个1-10数值:"))
if guess == temp:
    print("恭喜您,输入的数值刚好")
elif guess > temp:
    print("太遗憾了,输入的数值小于它")
else:
    print("太遗憾了,输入的数值大于它")

x,y = 1,3
print("#三元运算符 :",end="")
print( x if x > 3 else y )


#------------while 语句---------------
# Fibonacci series: 斐波纳契数列 (两个元素的总和确定了下一个数)
a,b = 0,1
while b < 10:
    print(b,end=",")
    a,b = b, a+b
print("nn")   

while (1): print ('Python!')

#采用while ..else 进行素数的计算
count  = 11 / 2 
while count > 1:
       if num % count == 0:
             print("%d 最大约数是%d " %(11,count))
             break   #利用break跳出不执行else
             count -= 1
else:
             print("%d是素数" 11)   #循环穷尽(为假的时候,执行遇到break不会执行)



#------------for 语句---------------
for i in "python":
  print(i,end="|")  #依次打印字母并以 | 分割
print()   

sites = ["baidu","Google","Runoob","taobao"]
for i in sites:
    print(i,end=",")       #打印出列表的值
print()   

for i in range(len(sites)):  #或列表的长度 4 生成(0 - 3);
    print(i,sites[i],len(sites[i]))  #索引,列表中以索引下标的元素,元素的长度

print()   
#查询是否为质数 2 - 10 那些是质数
for x in range(2,10):
    for y in range(2,x):
        if x % y == 0:
            print(x,'等于',y , '*', x // y)
            break
    else:
        #循环中找到元素,它在穷尽列表(以for循环)或条件变为 false (以while循环)导致循环终止时被执行,但循环被break终止时不执行。 
        print(x,'是质数')

Python条件控制于循环案例

7.1.3 空语句:pass

Python pass是空语句,是为了保持程序结构的完整性,pass 不做任何事情,一般用做占位语句,如下实例:

while True:
    pass  # 等待键盘中断 (Ctrl+C)
    
#最小的类:
class MyEmptyClass:
   pass

8.迭代器与生成器

8.1 迭代器 iter

迭代是Python最强大的功能之一是访问集合元素的一种方式,迭代器是一个可以记住遍历的位置的对象;迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束,且只能往前不会后退。 迭代器参数:列表/字典

迭代器有两个基本的方法:iter() 和 next()。

创建一个迭代器,使用需要在类中实现两个方法 iter() 与 next() ;并且iter() 方法返回一个特殊的迭代器对象, 这个迭代器对象实现了 next() 方法并通过 StopIteration 异常标识迭代的完成,防止出现无限循环的情况。

案例:迭代器(魔术方法)

#!/usr/bin/python3
# coding:utf-8
# 功能:迭代器与生成器

import sys          #引入 sys 模块
list = [1, 2, 3, 4]
it = iter(list)

#** 方法1 for **#
## 其实 for 语句实现与iter迭代器差不多 ##
for x in it:
    print("值", x, end=", ")
else:
    print("n---------------------------")


#***方法2 next**#
it = iter(list)
while True:
    try:
        print(next(it), end=",")
    except StopIteration:     # StopIteration 异常用于标识迭代的完成,防止出现无限循环的情况;
        sys.exit()


#**方法3 迭代器 - 魔法方法 **#
# 创建一个返回数字的迭代器,初始值为 0,逐步递增 1:运行四次
#魔法方法案例(1)
class MyNumbers:
    def __iter__(self):  #魔法方法
        self.a = 0 
        return self

    def __next__(self):  #当
        try:
            if self.a <= 3:
                x = self.a
                self.a += 1
                return x
            else:
                raise StopIteration
        except StopIteration:
            return ('迭代结束')

myclass = MyNumbers()
myiter = iter(myclass)  # 实际触发了__iter__ 中 a = 0
print(next(myiter), end=" ")  #运行1次 next
print(next(myiter), end=" ")  #运行2次 next
print(next(myiter), end=" ")  #运行3次 next
print(next(myiter), end=" ")  #运行4次 next
print(next(myiter))  #第五次运行next由于条件(或抛出 StopIteration 退出迭代)

#案例二:采用魔法方法实现斐波那契数列
class Fibs:
    def __init__(self):
        self.a = 0
        self.b = 1

    def __iter__(self):
        return self   #返回它本身由于它自身就是迭代器

    def __next__(self):
        self.a, self.b = self.b,self.a + self.b
        return self.a   #a就是下一个斐波那契的值
    # def __next__(self):
    #     self.a, self.b = self.b,self.a + self.b
    #     if self.a > 10:
    #         raise StopIteration   #表示
    #     return self.a

fibs = Fibs()
for each in fibs:
    if each < 20: #返回
        print(each, end=" ")
    else:
        break


#######################
# $ python demo3.24.py
# 0 1 2 3 迭代结束
# 1 1 2 3 5 8 13

Python迭代器案例

8.2 生成器 yield

使用yield的函数被称为生成器(generator),跟普通函数不同的是,生成器是一个返回迭代器的函数;只能用于迭代操作,更简单点理解生成器就是一个迭代器。 不同之处:就是协同程序(可以运行的独立函数调用,函数可以暂停或者挂起,并在需要的地方从程序离开的地方继续或者重新开始)

重点:调用一个生成器函数,返回的是一个迭代器对象。 在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。

案例:生成器

#!/usr/bin/python3
#功能:生成器yield
import sys
 
#案例1:
def gener():
    print("生成器被执行!",end=" ")
    yield 1  #运行第一next 暂停在这里
    yield 2  #运行第二next 显示二

my = gener()
next(my)  # 成器被执行! 2
next(my)  # 2


#方法2:
def fibonacci(n): # 生成器函数 - 斐波那契
    a, b, counter = 0, 1, 0
    while True:
        #当 counter == 10 结束(即算出10次数)
        if (counter > n): 
            return
        yield a  #生成器进行返回
        a, b = b, a + b
        counter += 1
f = fibonacci(10) # f 是一个迭代器,由生成器返回生成
 
while True:
    try:
        print(next(f), end=" ") #一次返回一个斐波那契数列 0 1 1 2 3 5 8 13 21 34 55
    except StopIteration:
        sys.exit()


#方法3:for循环会自动解析Stopiteration异常并结束
def fbli():
    a = 0
    b = 1
    while True:
        a, b = b, a+b
        yield a

for each in fbli():  #each 及是 返回生成器 a的值
    if each <= 55:
        print(each,end=" ")
    else:
        break

########## 执行结果 ##########
# 1 2 3 5 8 13 21 34 55

9.Python 函数

9.1 函数定义语法

函数能提高应用的模块性,和代码的重复利用率可以进行自我调用,用户自己建立的函数叫用户自定义函数; 函数function,对象object,模块moudule。

函数与过程: 过程(procedure)是简单的,特殊并且没有返回值的,一般的编程语言都把函数和过程分开。 但Python事实上只有函数没有过程,函数是有返回值的,当函数中无return语句返回的时候,将返回None类型。但Python可以返回多个值、利用列表【多种类型共存】或者元组;

Q:如何定义一个函数? A:以下是简单的规则: 1.函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 (),函数内容以冒号起始,并且缩进。 2.任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。 3.函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。即 ‘’’函数说明’’’ 4.return [ 表达式 ] 结束函数,选择性地返回一个值给调用方,如果不带表达式的return相当于返回 None。

函数语法:

#.__doc__ (函数的默认属性,他是一个特殊的属性,特殊属性格式就是这样)
def 函数名(形参列表):
      '函数文档 :通过 函数名.__doc__调用' 
      函数体


#(形参) formal parameters
#(实参) actual parameters
def first(name="default"):
       '函数定义过程中name是形参' #因为ta只是一个形式,表示占据一个参数位置。
       print(name,"这时候name的值是实参,因为他是具体的参数值!")

>>> def hello():
    print("hello world")     #由于这里没有return 语句,将返回None
>>> temp = hello()     #将函数的值返回给temp
hello world    
>>> temp                    #但是temp并没有return返回值
>>> print(temp)   
None                             #Print-Temp时候返回了None类型
>>> type(temp)
<class 'NoneType'>


>>> def back():
    return ["Python","Flash", 3.1415926]
>>> back()
['Python', 'Flash', 3.1415926]     #返回列表
 
>> def back():
    return "Python","Flash", 3.1415926
>>> back()
('Python', 'Flash', 3.1415926)   #返回元组

默认情况下,参数值和参数名称是按函数声明中定义的顺序匹配起来的。

函数实例:

#!/usr/bin/python3
#功能:实现函数功能

def fun(num1,num2):
    '函数功能:求出两个数之和'  #通过 函数名.__doc__调用函数文档
    return num1 + num2        #用return返回参数或者程序运行的结果

def saypython(name='小甲鱼',words="改变时间"):  #设置默认参数,当未给函数赋值的时候显示
    '函数文档:我们的心声'
    print(name + ' 想 ->' + words)

print("1 + 2 =",fun(1,2))
print("函数说明:(",fun.__doc__,end=")n-------------")
print("我",saypython('weiyigeek','改变世界'))  #由于无return语句则返回none

saypython('weiyigeek','改变世界')
saypython()  #采用函数默认参数,便可以不带参数运行,因为有内置可选参数 name='小甲鱼',words="改变时间"

print("函数说明:(",fun.__doc__,end=")n")

Python函数定义案例

9.2 函数参数详述

python 函数的参数传递:

  • 不可变类型:类似 c++ 的值传递,整数、字符串、元组。如fun(a),传递的只是a的值,没有影响a对象本身。比如在 fun(a)内部修改 a 的值,只是修改另一个复制的对象,不会影响 a 本身。
  • 可变类型:类似 c++ 的引用传递,如列表,字典。如 fun(la),则是将 la 真正的传过去,修改后fun外部的la也会受影响

以下是调用函数时可使用的正式参数类型:

  • 必需参数, def printme(argv,argv1) = 关键字参数,函数调用使用关键字参数来确定传入的参数值(无需顺序输入,采用关键字即可) printme(argv1= 1024,argv = 1)
  • 默认参数,def printme(argv = 1024)
  • 不定长参数,需要一个函数能处理比当初声明时更多的参数 (重点)

可变参数运用在不确定有多个参数之间: (1)加了单个星号 形参名,如(params)会打包成为元组(tuple),如果在函数调用时没有指定参数,它就是一个空元组,我们也可以不向函数传递未命名的变量。 (2)加了两个星号 形参名,如(params)会以字典(dict)的形式导入

函数参数案例:

#!/usr/bin/python3
#功能:函数参数
#例如:其实PRINT()就自带收集参数*Objects
#print(*objects, sep=' ', end='n', file=sys.stdout, flush=False) 

#/*不可变对象**/
def ChangeInt(a):
    a = 10
    print("(不可变)函数内:",a) #结果是 10

b = 2
ChangeInt(b)
print("(不可变)函数外:",b,end="nn") #结果是 2

#/*可变对象**/
def changeme(mylist):
    mylist.append([1,2,3,4])  #这时候传入列表已经被改变了
    print("(可变)函数内取值 :",mylist)  
    return
mlist = [6,6,6]
changeme(mlist)
print("(可变)函数外取值 :",mlist)  #列表已改变

#!/*** 可变参数(*) 与 关键字参数 **/
def test(*params,exp="weiyi"):
    print("参数长度 :",len(params)," 第二个参数:",params[1],"Name :",exp)
    for var in params:
        print(var,end=",")
    return 0

test(1,"爱您",1024,1,exp='weiyigeek')

#!/*** 可变参数(**) **/
def printmm(arg1,**vardict):
    '函数文档:形式参数为字典类型'
    print("nn输出 arg1:",arg1)
    print("输出 vardict 字典 :",vardict)

printmm('test',a=1,b=2,c=3)

#!/*** 单个星号的使用  (注意)**/
def star(a,b,*,c):
    print("a :",a ," b:",b ,' c:', c)

star(1,2,c=1024)  #c必须进行指定关键字传入值,否则会报错

Python函数参数案例

注意事项: 1) Python一切皆对象,严格意义上我们不能说是值传递还是引用传递,我们应该说不可变对象和可变对象。 2) 声明函数时,参数中星号 * 可以单独出现,但是星号后的参数必须用关键字传入。

9.3 匿名函数

python 使用 lambda 来创建匿名函数,所谓匿名,意即不再使用 def 语句这样标准的形式定义一个函数。 lambda 表达式好处:使得代码更加精简,不需要考虑命名控制,简化代码可读性。

Q:如何建立一个匿名函数? A :lambda 只是一个表达式,函数体比 def 简单很多。 lambda 函数的语法只包含一个语句,如下: lambda [arg1 [ ,arg2,…..argn ]]:expression

案例:

#!/usr/bin/python3
#功能:使用匿名函数

#函数定义
sum = lambda arg1,arg2: arg1 + arg2
sum.__doc__ = '函数文档'

#调用匿名函数
print("1 + 99 相加后的值 :",sum(1,99))
print(sum.__doc__)


#进阶用法和BIF内置函数filter/map的使用
#匿名函数进阶 (设置过滤函数,返回可以不可以整除2的数值)
show = list(filter(lambda x: x % 2,range(10)))
print(show)

#进行map映射显示被%2整除后的结果。
show = list(map(lambda x:x % 2,range(10)))
print(show)

Python字典案例

注意事项: 1) lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。 2) lambda 函数拥有自己的命名空间,且不能访问自己参数列表之外或全局命名空间里的参数。 3) 虽然lambda函数看起来只能写一行,却不等同于C或C++的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率。

9.4 函数变量作用域

Python 中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的,变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称,作用域一共有4种分别是:

  • 局部变量(Local Variable),只有在函数内部中进行访问使用。E (Enclosing) 闭包函数外的函数中
  • 全局变量(Global Varable), 在可以在整个程序范围内访问。B (Built-in) 内置作用域(内置函数所在模块的范围)

以的规则查找,即:在局部找不到,便会去局部外的局部找(例如闭包),再找不到就会去全局找,再者去内置中找。

g_count = 0  # 全局作用域
def outer():
    o_count = 1  # 闭包函数外的函数中
    def inner():
        i_count = 2  # 局部作用域
#内置作用域是通过一个名为 builtin 的标准模块来实现的,但是这个变量名自身并没有放入内置作用域内,所以必须导入这个文件才能够使用它。

如果在函数中修改全局变量便会出现,新建一个与全局变量相同名字的局部变量,并将全局变量的值赋给它,修改得其实是局部变量的值,而全局变量里面的值没有任何更改。

案例:函数作用域

#!/usr/bin/python3
#代码功能:全局与局部变量Variable

#msg 变量定义在 if 语句块中,但外部还是可以访问的
if True:
    msg = "I am from Weiyigeek"
print("nmsg 变量定义在 if 语句块中,但外部还是可以访问的:",msg)

def discount(price,rate):
    final_price = price * rate   #局部变量
   # print("这里试图打印全局变量old_price的值(回报错):",old_price)

    local_price = 100    #定义在函数中,则它就是局部变量,外部不能访问
    print("局部变量local_price :",local_price)   # 100

    old_price = 50
    print("函数内修改后old_price的值是1 :",old_price)
    return final_price

old_price = float(input('请输入原价:'))
rate = float(input('请输入则扣率: '))
new_price = discount(old_price,rate)
print('函数外修改后的old_price的值是2 :',old_price)
print('打折后的价格 :',new_price)

Python函数作用域案例

注意事项: 1) 尽量不要去在函数中更改全局变量,而且慎用全局变量。 2) Python 中只有模块(module),类(class)以及函数(def、lambda)才会引入新的作用域。 3) 其它的代码块(如 if/elif/else/、try/except、for/while等)是不会引入新的作用域的,也就是说这些语句内定义的变量,外部也可以访问。

9.4.1 函数变量作用域关键字

描述:Python为了保护全局变量引入了{ 屏蔽(Shadowing) },当内部作用域想修改外部作用域的变量时,就要用到global和nonlocal关键字了。

global 和 nonlocal关键字:

global关键字可以在定义的函数中更改全局变量(global variable),如果要修改嵌套作用域(enclosing 作用域,外层非全局作用域)中的变量则需要 nonlocal 关键字了

案例: 作用域关键字

#!/usr/bin/python3
#功能:全局变量作用域和非全局作用域

"""global"""
num = 1
def fun1():
    global num  # 需要使用 global 关键字声明
    print("global:",num,end=",") 
    num = 123
    print(num,end=",")
    num += 133
fun1()
print(num)  
#global: 1,123,256


"""nonlocal"""
def outer():
    num = 10
    def inner():
        nonlocal num   # nonlocal关键字声明
        num = 100
        print("nonlocal:",num,end=" | ")
        num *= 10.24
    inner()
    print(num,end=" | ")
outer()
print(num)  #这里的num没有变化由于outer函数中没有使用global关键字
#nonlocal: 100 | 1024.0 | 256

9.5 内嵌函数和闭包

Python中函数中可以内嵌函数定义与使用,还能在全局变量不适用的时候可以考虑使用闭包更稳定和安全。 容器(container),比如前面的所有数组(array)=列表(list),元组(tuple)

案例:

#!/usr/bin/python3
#功能:内嵌函数与闭包使用

#""" 内嵌函数 """
def fun1():
    print("Fun1 主函数被调用")
    def fun2():
        print("Fun2 内嵌函数正在被调用n")
    fun2()  #内部函数(内嵌函数),只能由fun1()调用

fun1()



#"""闭包"""
def funX(x):
    def funY(y):
        return x * y
    return funY

i = funX(8)
print("i的类型 :",type(i))
print("8 * 5 =",i(5)) #  40 由于前面已经赋值给x了,后面得就给了y=5.
"""
#类似于:
def funX(x):
    def funY(y):
        return x * y
    return funY(2)
>>> funX(3)
6
"""



#"""闭包进阶(采用类似于数数组的方式 -- 列表(传入的是地址))"""
def demo1(arg):
    x = [arg]
    def demo2():
        #采用 nonlocal 关键字也行
        x[0] **= x[0]  #采用这样的方式进行取值列表 (**幂运算) | 不引用局部变量(Local variable),采用数组的方式进行暗渡成仓.
        return x[0]
    return demo2()

print("2 ** 2 =",demo1(2),"  -  5 ** 5 =",demo1(5))

#"""一个闭包的典型案例"""
def funA():
    x = 5
    def funB():
        nonlocal x   #//把x强制表示不是局部变量local variable
        x += 13
        return x 
    return funB

a = funA()  #当 a 第一次被赋值后,只要没被重新赋值,funA()就没被释放,也就是说局部变量x就没有被重新初始化。
print("第一次调用:",a(),"第二次调用:",a(),"第三次调用:",a())

Python内嵌函数和闭包