with 关键字
with关键字为我们提供了一种优雅的方式来处理文件操作、数据库连接等需要明确释放资源的场景
with是python中的一个关键字,用于上下文管理协议(context Mangement protocol),它简化了资源管理代码,特别是那些需要明确释放或者清理的资源(如文件,网络连接,数据库连接等)
传统资源管理的问题
file = open('example.txt', 'r')
try:content = file.read()# 处理文件内容
finally:file.close()
- 容易忘记关闭资源:如果没有try-finally块,可能会忘记close()
- 代码冗长
- 异常处理复杂
with语句的优势
with语句通过上下文管理协议解决了这些问题:
- 自动资源释放:确保资源在使用后正确关闭
- 代码简洁
- 异常安全:即使在代码块中发生异常,资源也会被正确释放
- 可读性强
with语句的基本语法
基本形式如下:
with expression [as variable]:# 代码块
expression
返回一个支持上下文管理协议的对象as variable
是可选的,用于将表达式结果赋值给变量- 代码块执行完毕后,自动调用清理方法
实际应用场景
-
文件操作
# 同时打开多个文件 with open('input.txt', 'r') as infile, open('output.txt', 'w') as outfile:content = infile.read()outfile.write(content.upper())
-
数据库连接
import sqlite3with sqlite3.connect('database.db') as conn:cursor = conn.cursor()cursor.execute('SELECT * FROM users')results = cursor.fetchall() # 连接自动关闭
-
线程锁
import threadinglock = threading.Lock()with lock:# 临界区代码print("这段代码是线程安全的")
面向对象
类(Class)与对象(Object)
类(class)是用来描述具有相同属性(Attribute)和方法(Method)对象的集合。对象(Object)是类(Class)的具体实例。
- 属性(Attribute):类里面用于描述所有对象共同特征的变量和数据。
- 方法(Method):类里面的函数,用量区别外面的函数,用来实现某些功能。
# 创建一个学生类
class Student:# 定义学生属性,初始化方法 构造方法def __init__(self, name, score):self.name = nameself.score = score# 定义打印学生信息的方法def show(self):print("Name: {}. Score: {}".format(self.name, self.score))
创建具体的学生对象(Object):
student1 = Student("john",100)
当我们输入上述代码时,Python会自动调用默认的__init__
初始构造函数来生成具体的对象。关键字self
是个非常重要的参数,代表创建的对象本身。
类变量(Class variables)与实例变量(Instance variables)
# 创建一个学生类
class Student:# number属于类变量,不属于某个具体的学生实例number = 0# 定义学生属性,初始化方法# name和score属于实例变量def __init__(self, name, score):self.name = nameself.score = scoreStudent.number = Student.number + 1# 定义打印学生信息的方法def show(self):print("Name: {}. Score: {}".format(self.name, self.score))# 实例化,创建对象
student1 = Student("John", 100)
student2 = Student("Lucy", 99)print(Student.number) # 打印2
print(student1.__class__.number) # 打印2
类变量与实例变量的区别:
- 类变量:类变量在整个实例化的对象中是公用的,类变量定义在类中且在函数体之外。访问或调用类变量的正确方式是类名.变量名或者
self.__class__.变量名
。self.__class__
自动返回每个对象的类名。 - 实例变量:定义在方法中的变量,属于某个具体的对象,访问或调用实例变量的正确方式是
对象名.变量名
或者self.变量名
.
类的私有属性(private attribute)和私有方法(private method)
类里面的私有属性和私有方法以双下划线__
开头。私有属性或方法不能在类的外部被使用或直接访问
# 创建一个学生类
class Student:# 定义学生属性,初始化方法# name和score属于实例变量, 其中__score属于私有变量def __init__(self, name, score):self.name = nameself.__score = score# 定义打印学生信息的方法def show(self):print("Name: {}. Score: {}".format(self.name, self.__score))# 实例化,创建对象
student1 = Student("John", 100)student1.show() # 打印 Name: John, Score: 100
student1.__score # 打印出错,该属性不能从外部访问。
@property的用法与神奇之处
在上述案例中用户不能用student1.__score
方式访问学生分数,然而用户也就知道了__score
是个私有变量。我们有没有一种方法让用户通过student1.score
来访问学生分数而继续保持__score
私有变量的属性呢?这时我们就可以借助python的@property
装饰器了
# 创建一个学生类
class Student:# 定义学生属性,初始化方法# name和score属于实例变量, 其中score属于私有变量def __init__(self, name, score):self.name = nameself.__score = score# 利用property装饰器把函数伪装成属性@propertydef score(self):print("Name: {}. Score: {}".format(self.name, self.__score))# 实例化,创建对象student1 = Student("John", 100)student1.score # 打印 Name: John. Score: 100
注意:一旦给函数加上一个装饰器@property 调用函数的时候不用加括号就可以直接调用函数了
静态变量和静态方法
静态变量和静态方法都属于类的静态成员,它们与普通的实例变量和实例方法不同,静态变量和静态方法只属于定义它们的类,而不属于某一个实例对象
把类中的方法声明为静态方法,可以使用@staticmethod
装饰器
# 创建一个学生类
class Student:# number属于类变量,定义在方法外,不属于具体实例number = 0# 定义学生属性,初始化方法# name和score属于实例变量,定义在方法里def __init__(self, name, score):self.name = nameself.score = scoreStudent.number = number + 1# 定义打印学生信息的方法def show(self):print("Name: {}. Score: {}".format(self.name, self.score))# 静态方法无法使用cls和self参数访问类或实例的变量@staticmethoddef func1():print("this is static function!")
静态变量和静态方法都可以通过类名和实例对象进行访问,同时不像类方法和实例方法,静态方法无法接收
cls
和self
作为第一个参数。