[toc]
Python笔记3
此笔记初次更新于2021-03-30。现在对该笔记进行重新编写。
目前此笔记中的Python版本为3.12.3
Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对象是很容易的。
面向对象常用名词解释
- 类(Class): 一个描述属性和方法的集合。它定义了该集合中每个对象所共有的属性和方法。
- 方法:类中定义的函数。
- 类变量(公共类属性):类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
- 实例变量(普通类属性):在类的声明中,属性是用变量来表示的,这种变量就称为实例变量,实例变量就是一个用 self 修饰的变量。
- 局部变量:定义在方法中的变量。
- 继承:Python允许一个派生类(derived class)继承基类(base class)的字段和方法。
- 实例化对象:创建一个类的实例,类的具体对象。
- 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
类
类语法格式
class 类名:
代码块1
代码块2
.....类的属性
在类中,我们可以定义变量。这些变量就是类的属性。类的属性分为两种:基本属性和私有属性。
基本属性就是类中的普通变量,基本属性可以在类外部被直接访问。
私有属性的特点
- 私有属性的属性名称以两个下划线
_ _开头。这样python会将该属性声明为私有属性。 - 私有属性不能在类的外部被其他代码使用或直接访问。
# people 类定义
class people:
# 定义基本属性name,age
name = ''
age = 0
# 定义私有属性weight
# 私有属性在类外部无法直接进行访问
__weight = 0类的方法
在类中,我们可以定义函数。这些函数就是类的方法。
在类的内部,使用 def 关键字来定义一个方法,与一般函数定义不同,类方法必须包含参数 self, 且为第一个参数。self 代表的是类的实例化对象。
self 的名字并不是规定死的,也可以使用 this,但是最好还是按照约定使用 self。
普通方法
# people类定义
class people:
name = ''
age = 0
# 定义普通方法speak
def speak(self,n,a):
self.name = n
self.age = a
print(self.name,self.age)
# 实例化类
p = people()
# 调用普通方法speak
p.speak(10,30)私有方法
私有方法的特点
- 私有方法的方法名称以两个下划线
_ _开头。这样python会将该方法声明为私有方法。 - 私有方法只能在类的内部调用 ,不能在类的外部调用。
# people 类定义
class people:
# 定义私有方法__foo
def __foo(self):
print('这是私有方法')
x = people()
x.__foo() # 外部调用类的私有方法,会直接报错类的构造方法
类中可以有一个名为__init__() 的特殊方法(构造方法),该方法在类实例化为对象的时候会自动调用一次。
class people:
name = ""
age = 0
# 定义people类的构造方法
def __init__(self, name, age):
self.name = name
self.age = age
# 实例化people类对象x。
x = people("bob",10)
print(x.name, x.age) # 输出结果:"bob",10类对象
当我们创建好一个类的时候,我们可以实例化类,将该类变为一个类对象。
类对象可以访问类中的属性和方法。
# 定义MyClass类
class MyClass:
i = 12345
def f(self):
return 'hello world'
# 实例化MyClass类,将其转换为类对象x
x = MyClass()
# 类对象x可以访问类的属性和方法
print("MyClass 类的属性 i 为:", x.i)
print("MyClass 类的方法 f 输出为:", x.f())cls 和 self 的区别
- self 通常是指类的实例化对象。
- cls 通常是指类本身。
继承
Python 同样支持类的继承。子类会继承父类的属性和方法。
单继承
继承的语法格式如下
class 子类名称(父类名称):
代码块1
代码块2
....例子
# people类定义
class people:
name = ''
age = 0
#定义构造方法
def __init__(self,n,a):
self.name = n
self.age = a
#单继承示例
# student类继承people类
class student(people):
grade = ''
# 定义构造方法
def __init__(self,n,a,g):
#调用父类的构造方法
people.__init__(self,n,a)
self.grade = g
# 实例化student类
s = student('ken',10,60,3)多继承
Python同样支持多继承形式。
多继承的语法格式如下
class 子类名称(父类名称1,父类名称2,父类名称3):
代码块1
代码块2
....例子
# people类定义
class people:
name = ''
age = 0
#定义构造方法
def __init__(self,n,a):
self.name = n
self.age = a
#另一个类,多继承之前的准备
class speaker:
topic = ''
name = ''
def __init__(self,n,t):
self.name = n
self.topic = t
#多继承示例
class sample(speaker,people):
def __init__(self,n,a,w,g,t):
people.__init__(self,n,a)
speaker.__init__(self,n,t)
# 实例化类sample
test = sample("Tim",25,80,4,"Python")方法重写
如果你的父类方法的功能不能满足你的需求,你可以在子类重写你父类的方法。
# 定义父类
class Parent:
def myMethod(self):
print ('调用父类方法')
# 定义子类
class Child(Parent):
def myMethod(self):
print ('调用子类方法')
# 实例Child类对象c
c = Child()
c.myMethod() # 调用子类的重写方法
super(Child,c).myMethod() # 用子类对象调用父类已被覆盖的方法
# 输出结果
# 调用子类方法
# 调用父类方法super() 函数是用于调用父类的一个方法。
异常和错误
Python assert(断言)用于判断一个表达式,在表达式条件为 false 的时候触发异常。
语法错误
# while语句,此处有语法错误
>>> while True print('Hello world')
# 报错信息
File "<stdin>", line 1, in ?
while True print('Hello world')
^
SyntaxError: invalid syntax此处while语句没有冒号:,有语法错误。
异常
假如 Python 程序的语法是正确的,在运行它的时候,也有可能发生错误。这种语法没有错误,但是运行会出现的错误被称为异常。
异常例子
# python终端
>>> 10 * (1/0) # 0 不能作为除数,触发异常
Traceback (most recent call last):
File "<stdin>", line 1, in ?
ZeroDivisionError: division by zero
>>> 4 + spam*3 # spam变量未定义,触发异常
Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: name 'spam' is not defined
>>> '2' + 2 # int 不能与 str 相加,触发异常
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only concatenate str (not "int") to str异常处理
try/except语句
对于代码中可能会发生异常的地方。我们可以通过 try/except 语句对可能出现的异常进行处理。

try/except 语句格式。
try:
print("开始。。。。")
## 此处是可能发生异常的代码
print("结束。。。。")
except ValueError:
# 当代码发生异常的时候,会执行except中的代码块
print("发生ValueError异常!")
except RuntimeError:
print("发生RuntimeError异常!")
except (IOError, NameError):
print("发生NameError和IOError异常!")一个 try 语句可能包含多个except子句,分别来处理不同的特定的异常。最多只有一个分支会被执行。
try/except 语句处理流程:
- 首先执行 try 语句块
- 如果没有异常发生,忽略 except 子句,try 子句执行后结束。
- 如果在执行 try 子句的过程中发生了异常,那么 try 子句余下的部分将被忽略。如果异常的类型和 except 之后的名称相符,那么对应的 except 子句将被执行。
- 如果一个异常没有与任何的 except 匹配,那么这个异常将会传递给上层的 try 中。
try/except...else语句
else 子句将在 try 子句没有发生任何异常的时候执行。
这样的好处是避免一些意想不到,而 except 又无法捕获的异常。

try/except...else 语句格式。
try:
print("开始。。。。")
## 此处是可能发生异常的代码
print("结束。。。。")
except ValueError:
# 当代码发生异常的时候,会执行except中的代码块
print("发生ValueError异常!")
except (IOError, NameError):
print("发生NameError和IOError异常!")
else:
print("无异常时,执行else语句代码。")
try-finally语句
try-finally 语句无论是否发生异常都将执行最后的代码。

try-finally 语句格式。
try:
print("开始。。。。")
## 此处是可能发生异常的代码
print("结束。。。。")
except ValueError:
# 当代码发生异常的时候,会执行except中的代码块
print("发生ValueError异常!")
else:
print("无异常时,执行else语句代码。")
finally:
print('无论异常是否发生都会执行finally子句。')抛出异常
Python 中可以使用 raise 语句手动抛出一个指定的异常。

例子
x = 10
if x > 5:
# raise手动抛出一个异常
raise Exception('x 不能大于 5。')用户自定义异常
我们可以通过创建一个新的异常类来拥有自己的异常处理方式。异常类继承自 Exception 类,可以直接继承,或者间接继承。
# 定义MyError类,继承Exception类
class MyError(Exception):
# 构造方法
def __init__(self, value):
self.value = value
# 测试例子,手动抛出MyError异常
try:
raise MyError(2*2)
except MyError as e:
print('My exception occurred, value:', e.value)
# 输出结果
# My exception occurred, value: 4Python 装饰器
装饰器(decorators)是 Python 中的一种高级功能,它允许你动态地修改函数或类的行为。
装饰器本质上是一种函数,它接受一个函数作为参数,并返回一个新的函数或修改原来的函数。
装饰器的应用场景
- 日志记录: 你可以使用装饰器在函数执行前后添加日志记录,以便跟踪函数的调用和返回值。
- 性能分析: 装饰器可以用于测量函数的执行时间,帮助你分析代码的性能问题。
- 输入验证: 你可以使用装饰器来验证函数的输入参数,确保它们符合预期的格式和范围。
- 缓存: 装饰器可以用于缓存函数的结果,避免重复计算,提高程序的性能。
- 权限检查: 你可以使用装饰器来检查用户是否有执行某个函数的权限,从而实现权限控制。
简单装饰器
简单示例如下
# 定义一个装饰器函数my_decorator, 它接受一个原函数func作为参数
def my_decorator(func):
# 定义一个内部函数wrapper, 它接受任意数量的位置参数 *args 和关键字参数 **kwargs
def wrapper():
print("在原函数之前执行")
# 执行原函数func
func()
print("在原函数之后执行")
return wrapper
# 此处定义一个函数say_hello,该函数用装饰器my_decorator进行装饰
@my_decorator
def say_hello():
print("Hello!")
# 调用say_hello函数
say_hello()输出结果如下
在原函数之前执行
Hello!
在原函数之后执行说明如下
- 定义一个装饰器函数 my_decorator,它接受一个原函数func作为参数。
- 在装饰器函数中定义一个内部函数 wrapper。在内部函数 wrapper 中,可以先执行一些前置操作(如日志记录、性能分析等),然后调用原始函数func。然后执行一些后置操作(如日志记录、性能分析等)
- 最后返回 wrapper 函数作为装饰器函数my_decorator 的结果。
带参数的装饰器
如果原函数需要参数,可以在装饰器的 wrapper 函数中传递参数。
下面代码定义了一个装饰器 my_decorator,它接受一个原函数func作为参数。装饰器通过 wrapper 内部函数包裹原函数func,并在调用原函数func前后添加额外操作。
# 装饰器函数my_decorator
def my_decorator(func):
def wrapper(*args, **kwargs):
print("在原函数之前执行")
func(*args, **kwargs)
print("在原函数之后执行")
return wrapper
# 定义一个函数greet, 用装饰器my_decorator进行装饰
@my_decorator
def greet(name):
print(f"Hello, {name}!")
# 执行greet函数
greet("Alice")输出结果如下
在原函数之前执行
Hello, Alice!
在原函数之后执行类装饰器
除了函数装饰器,Python 还支持类装饰器。
类装饰器是一种用于动态修改类行为的装饰器,它接收一个类作为参数,并返回一个新的类或修改后的类。
类装饰器的应用场景
- 添加/修改类的方法或属性
- 拦截实例化过程
- 实现单例模式、日志记录、权限检查等功能
基本示例如下
# 定义一个类装饰器SingletonDecorator
class SingletonDecorator:
"""类装饰器,使目标类变成单例模式"""
def __init__(self, cls):
self.cls = cls
self.instance = None
def __call__(self, *args, **kwargs):
"""拦截实例化过程,确保只创建一个实例"""
if self.instance is None:
self.instance = self.cls(*args, **kwargs)
return self.instance
# 定义一个类Database, 用装饰器SingletonDecorator进行装饰
@SingletonDecorator
class Database:
def __init__(self):
print("Database 初始化")
# 实例化Database类
db1 = Database()
db2 = Database()
print(db1 is db2) # True,说明是同一个实例输出结果
Database 初始化
True内置装饰器
Python 提供了一些内置的装饰器。
- @staticmethod 装饰器: 将类中的一个方法定义为静态方法,不需要实例化类即可调用该静态方法。
- 静态方法不接收类的实例对象(self)或类本身(cls)作为第一个参数。因此不需要对类实例化,就可以直接被调用,但静态方法内部不能访问类或实例属性。
- @classmethod 装饰器: 将类中的一个方法定义为类方法,第一个参数是类本身(通常命名为 cls)。
- 类方法无需实例化可以被类直接调用,但是类方法需要接受类本身(cls)作为第一个参数传入。在类方法中不能调用实例属性和实例方法,只能调用类属性和类方法。但是,在实例方法中可以调用类属性和类方法。
- @property 装饰器: 将类中的一个方法转换为属性,使其可以像属性一样访问。
示例如下
class MyClass:
@staticmethod
def static_method():
print("This is a static method.")
@classmethod
def class_method(cls):
print(f"This is a class method of {cls.__name__}.")
@property
def name(self):
return self._name
@name.setter
def name(self, value):
self._name = value
# 调用静态方法和类方法
MyClass.static_method()
MyClass.class_method()
# 调用属性方法
obj = MyClass()
obj.name = "Alice"
print(obj.name)多个装饰器组合使用
可以将多个装饰器组合在一起,它们会按照从下到上的顺序依次应用。
示例如下
# 定义两个装饰器函数decorator1和decorator2
def decorator1(func):
def wrapper():
print("Decorator 1")
func()
return wrapper
def decorator2(func):
def wrapper():
print("Decorator 2")
func()
return wrapper
# 定义一个函数say_hello, 用装饰器decorator1和decorator2进行装饰
@decorator1
@decorator2
def say_hello():
print("Hello!")
# 调用say_hello函数
say_hello()
# 输出结果
# Decorator 1
# Decorator 2
# Hello!Python 泛型
泛型(Generics)是一种编程范式,允许编写能够处理多种类型的代码,从而提高代码的复用性、可读性和类型安全性。
在 Python 中,泛型主要通过 typing 模块实现,适用于函数、类和接口设计。
泛型在函数中的使用
一个简单的泛型示例
from typing import TypeVar, List
# 定义一个泛型类型变量
T = TypeVar('T')
# 定义一个函数,函数可以接受任意类型的列表,并返回列表中的第一个元素
def get_first_element(elements: List[T]) -> T:
return elements[0]
# 调用函数
print(get_first_element([1, 2, 3])) # 输出: 1
print(get_first_element(["a", "b", "c"])) # 输出: "a"泛型在类中的使用
一个类可以通过继承 Generic 类,来创建支持类型参数的泛型类。
from typing import Generic, TypeVar, List
# 定义一个泛型类型变量
T = TypeVar('T')
# 定义一个类,该类继承自 Generic[T]。则该类是一个泛型类,可以接受任意类型的参数
class Stack(Generic[T]):
def __init__(self) -> None:
self.items: List[T] = []
def push(self, item: T) -> None:
self.items.append(item)
def pop(self) -> T:
return self.items.pop()
# 使用
int_stack = Stack[int]()
int_stack.push(1)
int_stack.push(2)
print(int_stack.pop()) # 输出: 2上面代码中,Stack 是一个泛型类,可以操作任意类型的数据,并在静态类型检查中确保类型一致性。
