我的Python学习日记
Date | Log |
---|---|
2023.12.05 | 完成编写 |
8. Class 类
Python是一种面向对象的编程(Object-Oriented Programming, OOP),所以在Python中创建一个类和对象是很方便的
8.1 面向对象编程
面向对象编程是一种计算机编程范式,它基于对象的概念,其中对象是程序中的基本单元,并且这些对象可以通过定义类(Class)来创建。每个类可以包含数据与数据相关的方法。OOP 的设计理念是将程序的数据和操作数据的方法封装在一个单元中,这个单元就是对象。
OOP有以下几个核心概念:
- 类(Class)
类是一种用户定义的数据类型,用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。 - 对象(Object)
对象是类的实例,包含类定义的属性(数据成员)和方法(成员函数)。- 方法:类中定义的函数。
- 数据成员:数据成员包括类变量和实例变量,用于处理类及其实例对象的相关数据。数据成员定义了类的属性。
- 类变量:通常定义在类之中,函数之外,是类中所有实例化对象共享的,通常用于表示该类的所有实例共有的属性或状态。
- 实例变量:在类的声明中用变量表示的属性,每个对象实例都有自己的一组实例变量,用
self
修饰,可以在整个类的方法中访问
- 局部变量:在方法中定义的变量,作用范围限定在当前方法内。
- 封装(Encapsulation)
封装是将类的实现细节隐藏起来,只暴露必要的接口,将对象内部的状态保护起来,只能通过类的方法进行访问和修改- 私有成员:使用私有成员(通常在属性名前加上双下划线
__
)可以限制外部直接访问
- 私有成员:使用私有成员(通常在属性名前加上双下划线
- 继承(Inheritance)
继承允许一个类(子类)继承另一个类(父类)的属性和方法。子类可以重用父类的代码,并可以在其基础上进行扩展或修改,即子类是父类的一种特例。
8.2 类的定义与对象
定义格式如下:
class myclass:
var1 = value # 类变量
def func1(): # 方法(函数)
函数体
类对象
类对象支持两种操作:属性引用和实例化
实例化是创建一个类的实例,即类的具体对象
属性引用和其他引用一致,即A.B
形式
class myclass:
def greet(self):
return 'Hello World!'
s = myclass() # 实例化,这里s就是类的一个实例
print(s.greet()) # 属性引用
8.3 类的方法
类的方法定义也是使用def
关键字,一般有实例方法、静态方法、类方法和特殊方法四种。
8.3.1 实例方法
实例方法是最常见的方法类型。它们在类中被定义,并且至少有一个参数,通常被称为self
,用于引用类的实例。
- 一般来说不用装饰器的方法就是实例方法。
- 实例方法可以访问和修改实例变量,也可以调用其他实例方法。
class myclass:
def greet(self):
print('Hello World!')
8.3.2 静态方法
静态方法与类相关联,但与实例无关,没有访问实例的权限,通常与类的状态无关,仅依赖于传入的参数。
- 定义静态方法前要用
@staticmethod
装饰器
class myclass:
@staticmethod
def greet():
print('Hello World!')
myclass.greet() # 可以跳过实例化直接调用
s = myclass # 也可以实例化后再调用
s.greet()
8.3.3 类方法
类方法与整个类相关联,而不是与实例相关
- 定义类方法前要用
@classmethod
装饰器 - 类方法第一个参数通常被命名为 ‘cls’,用于引用类本身,而不是实例
8.3.4 特殊方法
特殊方法是以双下划线__
开头和结尾的方法,在特定的操作发生时被调用,一般不是直接调用的
__init__(self, ...)
:初始化方法,用于在创建对象时进行初始化操作,它在对象被创建时自动调用__str__(self)
:用于返回对象的字符串表示,在使用str()
或print()
打印一个对象时,会自动调用对象的__str__
方法-
class myclass: def __str__(self) -> str: return 'Hello World!' print(myclass()) # Hello World!
-
__len__(self)
:用于返回对象的长度,通常与内置函数len()
一起使用。
Python 中还有更多特殊方法,以后再进行补充
8.3.5 一个例程
class Employee:
total_employees = 0
def __init__(self, name, salary): # 特殊方法__init__
self.name = name
self.salary = salary
Employee.total_employees += 1 # 每次创建一个实例就相当于录入一个员工,员工数量+1
print(f"{self.name}'s information has been uploaded.") # 每次创建一个实例输出一次
def __str__(self): # 特殊方法__str__
return f"{self.name} - Salary: ${self.salary}"
def apply_raise(self, raise_percentage): # 实例方法,加薪
self.salary *= (1 + raise_percentage)
print(f"{self.name}'s salary after raise: ${self.salary}")
@classmethod
def get_total_employees(cls): # 类方法,获取类变量总员工数
return cls.total_employees
@staticmethod
def is_high_salary(salary): # 静态方法,无关实例
return salary > 50000
# 创建员工实例
employee1 = Employee("Alice", 45000)
employee2 = Employee("Bob", 60000)
# 打印员工信息
print(employee1)
print(employee2)
# 调用实例方法,给员工加薪
employee1.apply_raise(0.1)
# 调用类方法,获取总员工数
total_employees = Employee.get_total_employees()
print(f"Total employees: {total_employees}")
# 调用静态方法,判断是否为高薪水
is_high_salary = Employee.is_high_salary(employee1.salary)
print(f"Is {employee1.name}'s salary considered a high salary? {is_high_salary}")
8.4 封装
封装是指将某些属性或方法封装在一个类的内部,无法从外部访问,隐藏了某些实现的细节,可以防止外部代码无意中修改内部状态,提高了数据的安全性。
一般来说,将类内的属性和方法封装的方式是以双下划线__
开头来命名:
- 私有属性:私有属性是类中用于存储数据的变量,只能在类的内部访问。在类的外部,我们不能直接访问私有属性。
- 私有方法:私有方法是类中定义的用于实现某些功能的函数,只能在类的内部调用。
此外还有一种以单下划线_
开头的命名方法,这是一种约定,告诉其他开发者这类成员是受保护的,但这只是一种约定,并没有真正的访问控制。
8.5 继承
8.5.1 基本信息
类的继承的逻辑是:子类会继承父类的属性和方法,也可以根据需要进行修改或扩展,基本语法为:
class ParentClass:
# 父类的属性和方法
class ChildClass:
# 子类的属性和方法
class Animal: # 父类
def __init__(self, name):
self.name = name
def make_sound(self):
pass
class Dog(Animal): # 子类继承父类,并对父类的make_sound函数进行重写
def make_sound(self):
return "Woof!"
class Cat(Animal):
def make_sound(self):
return "Meow!"
# 创建 Animal 类的实例
animal = Animal("Generic Animal")
print(f"{animal.name} says: {animal.make_sound()}") # Generic Animal says: None (父类中的make_sound函数并没有返回值)
dog = Dog("DaHuang")# 创建 Dog 类的实例
print(f"{dog.name} says: {dog.make_sound()}")
Cat = Cat("MiMi") # 创建 Cat 类的实例
print(f"{cat.name} says: {cat.make_sound()}")
8.5.2 方法重写
在上面的例子中,子类Cat和Dog对父类的make_sound函数进行了重写,以满足子类的需要
如果想重新调用父类中的同名方法,可以使用super()
方法来调用:
class Dog(Animal):
def make_sound(self):
return super().make_sound() + " Bark!"
super([class,...])
函数一般在实例方法内部调用,而不是在类的实例化时调用
8.5.3 多继承
多继承是指一个类可以继承自多个父类的属性和方法:
class ParentClass1:
# 父类1的属性和方法
class ParentClass2:
# 父类2的属性和方法
class ChildClass(ParentClass1, ParentClass2):
# 子类的属性和方法
- 需要注意圆括号中父类的顺序,若是父类中有相同的方法名,而在子类使用时未指定,则会从左至右搜索括号中的父类包含的方法