一:变量的范围(Scope) 与 作用域 (Lifetime)
1)变量的范围(Scope) 是指变量在程序中的可访问区域或范围。
范围决定了一个变量是否可以被访问、修改或删除。
· 1.1 局部变量(Local Variable)
· 1.2 全局变量(Global Variable)
· 1.3 嵌套作用域(Enclosing Scope)
· 1.4 内建作用域(Built-in Scope)
# 4) 内建作用域- 练习(Built-in Scope)
from math import e
def function_one():
print(e )
function_one()
2)变量的作用域(Lifetime)
作用域(Lifetime) 是指变量在内存中存活的时间。也就是说,变量存在的时间长度及其值是否可用。
作用域规则:L E G B ·L - Local(局部作用域):查找当前函数或代码块内的变量。 ·E - Enclosing(外层作用域):查找外层函数中的变量,适用于嵌套函数。 ·G - Global(全局作用域):查找当前模块(文件)中的全局变量。 ·B - Built-in(内建作用域):查找 Python 内建的名称,如 print() 和 len() 等。
二:异常处理(Exception Handling)
异常处理(Exception Handling)是指在程序运行过程中,遇到错误或异常情况时,程序能够优雅地捕获并处理这些错误,而不是直接崩溃或中断。
1. 常见的异常类型
Python 中有多种内置异常类型,常见的有:
ZeroDivisionError:除以零错误。
ValueError:传入函数的值类型错误。
IndexError:索引超出序列范围。
TypeError:不支持的操作类型错误。
FileNotFoundError:文件未找到错误。
# try:
try:
x = int(input('请输入一个整数:'))
y = int(input('请输入另一个整数:'))
print(x/y)
except ValueError : #处理输入不是整数的情况
print('请输入整数')
except ZeroDivisionError : #处理除数为零的情况
print('除数不能为零')
# 输出:请输入一个整数:1
# 输出:请输入另一个整数:1.2
# 输出:请输入整数
2. 基本的异常处理结构
2.1 try / except
最基本的异常处理结构包括 try 和 except 块,try 块用于包含可能会发生错误的代码,except 块用于捕获并处理异常。
2.2 else 块
else 块可以选择性地使用,它在 try 块中的代码没有发生异常时执行。
# else 块可以选择性地使用,它在 try 块中的代码没有发生异常时执行。
try:
x = int(input('请输入一个整数:'))
y = int(input('请输入另一个整数:'))
print(x/y)
except (ValueError,ZeroDivisionError): #出现不是整数和除数为零的情况
print('出现错误,请重新输入!')
else: #其余别的情况,比较难以触发
print('else')
# 输出:请输入一个整数:8
# 输出:请输入另一个整数:5
# 输出:1.6
# 输出:else
2.3 finally 块
finally 块中的代码无论是否发生异常都会执行。通常用于清理资源或执行最终步骤,如关闭文件、释放连接等。
# finally 块中的代码无论是否发生异常都会执行。通常用于清理资源或执行最终步骤,如关闭文件、释放连接等。
try:
x = int(input('请输入一个整数:'))
y = int(input('请输入另一个整数:'))
print(x/y)
except (ValueError,ZeroDivisionError): #出现不是整数和除数为零的情况
print('出现错误,请重新输入!')
finally:
print('无论是否出现异常,都会执行')
# 输出:请输入一个整数:8
# 输出:请输入另一个整数:5
# 输出:1.6
# 输出:无论是否出现异常,都会执行
三:档案侦测
·import os 模块
os.path.exists(path):检查指定路径是否存在。
# 1) os.path.exists( ):检查指定路径是否存在。
import os #os 模块提供了一组与操作系统交互的功能。这些功能主要用于处理文件和目录的操作、执行系统命令、获取系统信息等。
str = r"E:\00_python\Python\22_\TEXT" #"r" 是读取模式(如果文件不存在,会抛出异常)。
# str = "E:\\00_python\\Python\\22_\\TEXT" #不用r,用双\表达也可以
print(str)
if os.path.exists(str): # os.path.exists():检查指定路径是否存在。
print('路径存在!')
else:
print('路径不存在!')
# 输出:E:\00_python\Python\22_\TEXT
# 输出:路径存在!
os.path.isdir(path):检查路径是否是目录。
# 2)档案(文件)和目录(文件夹)
# os.path.isfile( ):检查路径是否是档案(文件)。
# os.path.isdir( ):检查路径是否是目录(文件夹)。
if os.path.isfile(str):
print('该路径为档案!')
elif os.path.isdir(str):
print('该路径为目录!')
else:
print('other')
# 输出:该路径为目录!
os.path.isfile(path):检查路径是否是文件。
# r: 只读模式,文件必须存在。如果文件不存在,会抛出 FileNotFoundError。 # w: 只写模式。如果文件已存在,它会覆盖原文件;如果文件不存在,会创建新文件。 # a: 追加模式。如果文件已存在,新内容将追加到文件末尾;如果文件不存在,Python 会创建一个新文件。 # \n 是换行符
2.读取档案(文件)
with open() #使用 open() 打开文件。
# 使用 with 语句打开文件是一种推荐的做法,因为它可以确保文件在读取完毕后自动关闭,避免手动调用 close()。
# 使用 read()、readline() 或 readlines() 来读取文件内容。
import os
str = r'E:\00_python\Python\22_\TEXT\text.txt' #需要输入文件名,而不是文件夹名
with open(str) as file:
print(file.read()) #使用 read()来读取文件内容。
# 输出:Leif Ava #在文件夹里输入的内容
3.写入档案(文件) 'w'=write \n 是换行符
· r: 只读模式,文件必须存在。如果文件不存在,会抛出 FileNotFoundError。
· w: 只写模式。如果文件已存在,它会覆盖原文件;如果文件不存在,会创建新文件。
· a: 追加模式。如果文件已存在,新内容将追加到文件末尾;如果文件不存在,Python 会创建一个新文件。
# 练习一
str = r'E:\00_python\Python\22_\TEXT\text2.txt'
text2 = '哈喽!\nLeif Ava 祝你一切顺利!' #\n 是自动换行
with open(str,'w') as file: #'w'=write
file.write(text2)
# 输出: #没有输出内容,表明已经写进去了
# 练习二 - 追加(append)模式 'w' => 'a'
str = r'E:\00_python\Python\22_\TEXT\text2.txt'
with open(str,'a') as file:
file.write('\ngo go go')
# 输出:哈喽! #运行几次出现几次 go go go
# 输出:Leif Ava 祝你一切顺利!
# 输出:go go go
# 输出:go go go
# 输出:go go go
# 输出:go go go
# 输出:go go go
4.复制档案(文件)
·shutil 模块
·源文件 src ·目标文件 dst
shutil.copyfile(src, dst)
功能:内容复制 (只复制文件内容,不复制权限和时间戳)
2. shutil.copy(src, dst)
功能:内容复制 权限复制 (复制文件内容和权限,但不复制时间戳 )
3. shutil.copy2(src, dst)
功能:内容复制 权限复制 时间戳复制 (复制文件内容、权限和时间戳)
# copyfile
# copy
# copy2
import shutil
w = r'E:\00_python\Python\22_\TEXT'
text2 = f'{w}/text2.txt'
text3 = f'{w}/text3.txt'
shutil.copyfile(text2,text3)
# 输出: #没有输出内容,表明已经复制了,并命名:text3.txt
5.删除档案(文件)
1)os模块
· os.remove(path)或者os.unlink( )。:删除指定路径的文件。如果文件不存在,会抛出 FileNotFoundError。
· os.rmdir(path):删除空目录。如果目录不为空,将抛出 OSError。
· os.removedirs(path):递归删除空目录。如果目录中有文件或其他目录,将引发错误。
2) shutil 模块
shutil 模块主要用于删除目录(包括文件和子目录),而不常用于删除单个文件。不过,shutil 模块可以删除整个目录及其内容。
· shutil.rmtree( ):递归地删除目录及其所有内容。
import os
import shutil
path =r'E:\00_python\Python\22_\TEXT'
#删除档案
os.remove(f'{path}/text3.txt')
#删除空资料夹
os.rmdir(f'{path}/dirc')
#删除资料夹及其内容
shutil.rmtree()
#丢进垃圾桶(python没有装send2trash)
# import send2trash
# send2trash.send2trash(fr'{path}\text3.txt')
四:物件导向程式设计(面向对象编程)Object-Oriented Programming,简称 OOP)
·类(Class):类是对象的模板或蓝图,定义了对象的属性和行为。
·实例(Instance)是通过类(Class)创建的具体物件,类是蓝图,而实例是具体的物件。是对象的一种,特指“某个类对象。”
·物件/对象(Object):物件是类的实例,代表实际存在的实体。物件具有类所定义的属性和方法。是一个更宽泛的术语,指所有从类创建出来的具体东西。
·方法(Method):方法是类中定义的函数,表示物件的行为或操作。
·属性(Attribute):属性是类中定义的变量,表示物件的特征或状态。
# 1)创建一个 Car 类的实例(属性)
class Car:
def __init__(self,make,model,year,color): #初始化
self.make = make #制造商
self.model = model #型号
self.year =year #年份
self.color =color #颜色
car1 = Car('BYD',"宋plus",'2023','蓝色')
car2 = Car('Ford',"Kuga",'2020','白色')
print(car1.make)
print(car1.model)
print(car2.year)
print(car2.color)
# 输出:BYD
# 输出:宋plus
# 输出:2020
# 输出:白色
# 2)创建一个 Car 类的实例(行为)
class Car:
def __init__(self,make,model,year,color): #初始化
self.make = make #制造商
self.model = model #型号
self.year =year #年份
self.color =color #颜色
def drive(self):
print(self.model + '正在行驶')
def stop(self):
print(self.model + '已停止')
car1 = Car('BYD',"宋plus",'2023','蓝色')
car2 = Car('Ford',"Kuga",'2020','白色')
car1.drive()
car2.stop()
# 输出:宋plus正在行驶
# 输出:Kuga已停止
五:类别变数(类变量)
1)属于类本身:
· 类别变数是所有这个类的实例(对象)共享的变量。
· 类别变数只有一份,所有实例都可以访问或修改它。
2)与实例变数不同:
· 实例变量是每个实例(对象)独有的,每个对象的实例变量互不影响。
· 类别变数是所有实例共有的,修改它会影响到所有实例。
3)定义位置:
类别变数通常定义在类的内部,但在 __init__ 方法之外。
# 类别变数通常定义在类的内部,但在 __init__ 方法之外。
class Car:
wheels = 4 # 类别变数(类变量) # 默认所有车都有 4 个轮子
def __init__(self,make,model,year,color): #初始化
self.make = make # 实例变数(实例变量) #制造商
self.model = model # 实例变数(实例变量) #型号
self.year =year # 实例变数(实例变量) #年份
self.color =color # 实例变数(实例变量) #颜色
car1 = Car('BYD',"宋plus",'2023','蓝色')
print(car1.wheels)
# 输出:4
# 用类别变数建立的物件有时候会不符合使用,比如摩托车/机车
car2 = Car('春风','250sr','2024','蓝色')
print(car2.model)
print(car2.wheels)
# 输出:250sr
# 输出:4 #这里很明显机车不会是四个轮子,所以改成下面的内容
car2.wheels = 2
print(car2.wheels)
# 输出:2
六:继承关系 - 父类 / 子类
1)继承的作用
1.代码复用:子类可以直接使用父类的代码,不用重新写一遍。
2.扩展功能:子类可以在父类的基础上添加自己的方法和属性。
3.修改行为:子类可以通过重写(override)父类的方法来改变行为。
· 子类可以继续被其他类继承,这样就形成了一个继承链。
# 一.代码复用 扩展功能 # 1. 动物 (父类)
class Animal:
alive = True # 预设 活着的
def eat(self): # 定义一个吃东西的方法
print('这个动物正在吃东西')
def sleep(self):
print('这个动物正在睡觉')
# 2. 兔子 (子类)
class Rabbit(Animal):
def jump(self):
print('这个兔子正在跳')
animal = Animal()
rabbit = Rabbit()
animal.eat()
animal.sleep()
rabbit.jump()
rabbit.eat()
# 输出:这个动物正在吃东西
# 输出:这个动物正在睡觉
# 输出:这个兔子正在跳
# 输出:这个动物正在吃东西
# 二.修改行为:子类可以通过重写(override)父类的方法来改变行为。 # 重写(override)父类的方法,也叫方法覆盖
class Animal:
def eat(self):
print('动物正在吃东西')
class Rabbit(Animal):
def eat(self):
print('兔子正在吃胡萝卜')
animal = Animal()
animal.eat()
rabbit = Rabbit()
rabbit.eat()
# 输出:动物正在吃东西
# 输出:兔子正在吃胡萝卜
# 三.方法链(Method Chaining)是指将多个方法调用连接在一起的编程风格。
class Car:
def turn_on(self):
print('你打开了引擎')
return self # 回传物件本身
def drive(self):
print('你开车了')
return self
def brake(self):
print('你踩了刹车')
return self
def turn_off(self):
print('你关闭了引擎')
return self
car = Car()
car.turn_on().drive().brake().turn_off()
# 输出:你打开了引擎
# 输出:你开车了
# 输出:你踩了刹车
# 输出:你关闭了引擎
#四.Super()内置函数: 用于调用父类(超类)的方法。
class Rectengle:
def __init__(self,length,width):
self.length = length
self.width = width
print('矩形的初始化已执行')
class Square(Rectengle):
def __init__(self,length,width):
super().__init__(length,width) #先调用父类执行
print('正方形的初始化已执行') #在执行子类
# 练习一
square = Square(20,23) #目前代码中没有强制要求正方形长宽一样
# 输出:矩形的初始化已执行
# 输出:正方形的初始化已执行
七:传递物件为引数
class Car:
color = None
def change_color(car,color):
car.color = color
car1 = Car()
car2 = Car()
car3 = Car()
print(car1.color)
print(car2.color)
print(car3.color)
change_color(car1,'红色')
change_color(car2,'白色')
change_color(car3,'蓝色')
print(car1.color)
print(car2.color)
print(car3.color)
# 输出:None
# 输出:None
# 输出:None
# 输出:红色
# 输出:白色
# 输出:蓝色
八:Duck Typing (鸭子类型)
是 Python 中的一种编程理念,鸭子类型关注的是一个对象能够做什么,而不是是什么类型的对象。
换句话说,Python 强调“行为决定类型”,而不是“类型决定行为”。
class Duck:
def walk(self):
print('鸭子在走路')
def talk(self):
print('鸭子在呱呱呱')
class Chicken:
def walk(self):
print('鸡在走路')
def talk(self):
print('鸡在咕咕叫')
#上方即使没有继承的关系,也可以当作同一类型的类别使用
class Person(): #创建一个 Person 对象
def catch(self,duck): #`catch` 方法接收一个参数 `duck`
duck.walk() # 调用 duck 对象的 walk 方法
duck.talk() # 调用 duck 对象的 talk 方法
duck = Duck()
person = Person() # 创建一个 Person 对象
chicken = Chicken()
person.catch(duck) #定义catch方法,调用walk和talk方法
person.catch(chicken)
# 输出:鸭子在走路
# 输出:鸭子在呱呱呱
# 输出:鸡在走路
# 输出:鸡在咕咕叫
九:赋值运算符(Assignment Operator)
1. 基本赋值运算符 = ,用于将右侧的值或表达式的结果赋给左侧的变量。
2. 海象运算符 := (walrus operator),主要用于 赋值表达式
#练习 1 # 没有海象运算符的传统写法 happy = True print(happy) # 使用海象运算符的简洁写法 print(happy := True) # 输出:True #两个输出的都是一样的 # 输出:True #练习 2 # 没有海象运算符的传统写法 foods = [] while True: food = input('你喜欢什么食物?') if food == 'quit': break foods.append(food) #将所有食物加入列表里面 print(foods) # 输出:你喜欢什么食物?薯条 # 输出:你喜欢什么食物?quit # 输出:['薯条'] # 使用海象运算符的简洁写法 foods = [] while (food := input('你喜欢什么食物?')) != 'quit': # != 是不等于运算符(not equal to operator) foods.append(food) print(foods)
十:函数指派给变量(也叫做 函数赋值给变量)
将函数指派给变量,意味着把一个函数的引用赋值给一个变量,使得你可以通过该变量调用函数。
def hello():
print('hello')
hi = hello # 将函数 hello 指派给变量 hi
hi() # 使用 hi 来调用 hello 函数
# 输出:hello
# 练习 2 - 内建函式
say = print # 将内建函数 print 指派给变量 say
say('hello') # 使用 say 来调用 print 函数
say('hi')
# 输出:hello
# 输出:hi
十一:Lambda 函式 (或匿名函数)
Lambda 函数(或匿名函数)是 Python 中一种 简洁 的函数定义方式。它允许你创建一个简单的 一次性 函数,而不需要使用传统的 def 关键字。
# 1).在函数中直接使用 Lambda
# 练习一 double # 传入一个参数
# 没有用 Lambda 的传统写法
def double(x):
return x * 2
print(double(10))
# 输出:20
# 用 Lambda 的简写写法
double2 = lambda x: x*3
print(double2(30))
# 输出:90
# 练习二 multiply 乘法 # 传入两个参数
multiply = lambda x,y : x * y
print(multiply(5,10))
# 输出:50
# 练习三 if else 条件语句 - 判断 偶数还是奇数?
result = lambda x : f'{x}是偶数' if x % 2 == 0 else f'{x}是奇数'
print(result(4))
print(result(9))
# 输出:4是偶数
# 输出:9是奇数
# 2).使用 Lambda 和 Sort 排序
# Sort 排序 sort(reverse=True) 倒序 内建 sorted()方法
# 练习一 列表 list
num_list = [2,8,4,1,6]
print(num_list)
num_list.sort()
print(num_list)
num_list.sort(reverse=True)
print(num_list)
# 输出:[2, 8, 4, 1, 6] #排序前
# 输出:[1, 2, 4, 6, 8] #排序后
# 输出:[8, 6, 4, 2, 1] #倒序
# 3). map( ) 内置函数 map(function, iterable, ...)
store = [
('衬衫',20),
('裤子',30),
('夹克',60),
('袜子',10)
]
to_euros = lambda data:(data[0],data[1] * 0.82) #to_euros 将价格转换成欧元
store_euros = list(map(to_euros,store)) #list() 函数将 map() 返回的结果转换为一个列表
print(store_euros)
# 输出:[('衬衫', 16.4), ('裤子', 24.599999999999998), ('夹克', 49.199999999999996), ('袜子', 8.2)]
# 4).filter( ) 内置函数 filter(function, iterable)
friends = [
('Bob',18),
('Leif',29),
('Ava',24),
('susan',15)
]
age_filter = lambda data: data[1] >=18
can_drink_friends = list(filter(age_filter,friends))
for friend in can_drink_friends:
print(friend[0])
print(friend[1])
# 输出:Bob
# 输出:18
# 输出:Leif
# 输出:29
# 输出:Ava
# 输出:24
十二:列表推导式(list comprehension)
基本语法:
[expression for item in iterable]
· expression:对每个元素进行的操作或变换。可以是任何有效的表达式,甚至是函数调用。
· item:表示从 iterable 中提取出来的每个元素。
iterable:是一个可迭代对象(如列表、元组、字符串等)。
# 练习一 - 平方
# for循环 写法
def square(x):
return x * x
list = []
for i in range(1,11): #range(1, 11)(即数字 1 到 10)中遍历每个元素。
list.append(square(i))
print(list)
# 输出:[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
# 用列表推导式写法
squares = [i * i for i in range(1,11)]
print('列表推导式')
print(squares)
# 输出:列表推导式
# 输出:[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
十三:字典推导式(Dictionary Comprehension)
基本语法:
{key_expression: value_expression for item in iterable}
· key_expression:用于生成字典键的表达式。
· value_expression:用于生成字典值的表达式。
· item:是迭代过程中每个元素的代表。
· iterable:一个可迭代对象(如列表、元组、范围、字典等)。
# 练习一 - 运算
cities_in_f = {'LA':120,'New York':65,'Chicago':50,'Miami':150}
cities_in_c = {key:(value - 32) * 5/9 for key,value in cities_in_f.items()}
print(cities_in_f)
print(cities_in_c)
# 输出:{'LA': 120, 'New York': 65, 'Chicago': 50, 'Miami': 150}
# 输出:{'LA': 48.888888888888886, 'New York': 18.333333333333332, 'Chicago': 10.0, 'Miami': 65.55555555555556}
# 练习二 - 条件判断
weather = {'上海':'大晴天','安徽':'大晴天','湖北':'下雨','台湾':'下雨'}
sunny_weather = {key: value for key,value in weather.items() if value == '大晴天'}
print(sunny_weather)
# 输出:{'上海': '大晴天', '安徽': '大晴天'}
十四:Zip( ) 函式
# Zip( ) 函式 通常需要通过 list() 或 tuple() 来查看结果。
基本语法:
zip(iterable1, iterable2, ...)
· 参数:可以传入多个可迭代对象。
· 返回值:返回一个 迭代器,它生成的每个元素是一个元组,元组中包含了来自不同可迭代对象的对应元素。
usernames = ['Bob','Leif','Ava']
passwords = ('123','564','751')
users = zip(usernames,passwords)
# 练习1) - 返回的实际上是一个 迭代器,而不是一个列表或元组。
print(users)
# 输出: #zipped 是一个 zip 对象,并显示它的内存地址。
# 练习2) - 返回转换成 元组
for i in users:
print(i)
# 输出:('Bob', '123')
# 输出:('Leif', '564')
# 输出:('Ava', '751')
# 练习3) - 返回转换成 列表 list()
print(list(users))
# 输出:[('Bob', '123'), ('Leif', '564'), ('Ava', '751')]
# 练习4) - 返回转换成 字典 dict()
user_dict = dict(users)
print(user_dict) # key -> username
# 输出:{'Bob': '123', 'Leif': '564', 'Ava': '751'}
# 练习4-2) - 迭代字典
user_dict = dict(users)
for key,value in user_dict.items():
print(key + ':'+ value)
# 输出:Bob:123
# 输出:Leif:564
# 输出:Ava:751
# 练习5) - 传入的可迭代对象长度不相等时
usernames = ['Bob','Leif','Ava']
passwords = ('123','564')
users = zip(usernames,passwords)
user_dict = dict(users)
for key,value in user_dict.items():
print(key + ':'+ value)
# 输出:Bob:123 #ip() 会根据最短的那个可迭代对象来决定配对的次数。
# 输出:Leif:564
# 练习6) - 合并三个列表
usernames = ['Bob','Leif','Ava']
passwords = ('123','564')
dates = ['1998-02-05','1995-08-28','2000-10-25']
users = zip(usernames,passwords,dates)
print(users)
for i in users:
print(i)
# 输出:
# 输出:('Bob', '123', '1998-02-05')
# 输出:('Leif', '564', '1995-08-28')
# 练习6-2) - 合并三个列表 - 转换成 列表 list()
print(list(users))
# 输出:[] #输入两个以上的元素是不能直接转换成 列表 或者 字典
# 练习6-3) - 合并三个列表 - 转换成 字典 dict()
# 输出:{} #输入两个以上的元素是不能直接转换成 列表 或者 字典