1. 面向对象基础
1.1 面向对象思想
面向对象是将功能通过对象来实现,将功能封装进对象之中,让对象实现具体的细节。这种方法将数据作为第一位,方法或者算法作为其次,是对数据的一种优化,操作起来更加方便,过程简化。面向对象的三大特征:封装、继承和多态。
- 封装性:将数据和方法封装到一个类中,外部无法直接访问内部数据,只能通过类提供的方法访问。
- 继承性:子类可以继承父类的属性和方法,减少代码重复。
- 多态性:同一个方法在不同子类中可以有不同的实现。
1.2 类和对象
对象是类的实例化,类是对象特征的提取和封装。先定义一个类,通过类创建一个对象,对象 = 类名()。类就像一个模型,对象是通过类这个模型创建出来的。
1.3 属性和方法
- 属性:对象的特征。
- 方法:对象的动作。
1.4 类属性和对象属性
- 类属性:在类空间中,类属性既可以被类访问又可以被对象访问。
- 对象属性:在对象空间中,对象属性只能被当前对象访问。
python
# 1.4 类属性和对象属性
class MyClass:
class_attribute = "I am a class attribute" # 类属性
def __init__(self, value):
self.instance_attribute = value # 对象属性
# 创建对象
obj = MyClass("I am an instance attribute")
# 访问类属性
print(MyClass.class_attribute) # 输出: I am a class attribute
print(obj.class_attribute) # 输出: I am a class attribute
# 访问对象属性
print(obj.instance_attribute) # 输出: I am an instance attribute
1.5 检索原则
从对象自身检索,去对象模板(类)中检索。类属性在创建对象的时候不会在对象中实例化,之所以可以通过(对象名.属性名)获取到,那是因为在对象中没有找到的时候会在类模板中进行查找。
1.6 创建对象经历了什么
创建一个对象时,Python 会经历以下步骤:
- 通过
__new__()申请空间。 - 调用
__init__()初始化对象。 - 最后调用
__del__()销毁对象。
python
class User:
def __new__(cls, *args, **kwargs):
print("new")
return super().__new__(cls)
def __init__(self, name):
print("init")
self.name = name
def __del__(self):
print("del")
# 创建对象
user = User("Marry")
2. 面向对象方法
2.1 普通方法(对象方法)
普通方法是绑定到对象上的方法,调用时会自动传递 self 参数。
python
class Dog:
def eating(self):
print('Eating food')
# 创建对象并调用方法
dog = Dog()
dog.eating() # 输出: Eating food
2.2 类方法
类方法是绑定到类上的方法,调用时会自动传递 cls 参数。
python
class Dog:
@classmethod
def eating(cls):
print('Eating food')
# 通过类调用类方法
Dog.eating() # 输出: Eating food
# 通过对象调用类方法
dog = Dog()
dog.eating() # 输出: Eating food
2.3 静态方法
静态方法是类中的普通函数,不绑定到类或对象上,调用时不会自动传递 self 或 cls 参数。
python
import time
class Tool:
@staticmethod
def get_time():
print(time.time())
# 通过类调用静态方法
Tool.get_time()
# 通过对象调用静态方法
tool = Tool()
tool.get_time()
2.4 魔术方法
魔术方法是类的特殊方法,由系统自动调用,用于实现特定的行为。
2.4.1 常见魔术方法
__new__():创建对象时调用,用于申请空间。__init__():对象创建后调用,用于初始化对象。__del__():对象销毁时调用。__call__():使对象可以像函数一样被调用。__str__()和__repr__():将对象转换为字符串表示。__len__():返回对象的长度。
python
class User:
def __new__(cls, *args, **kwargs):
print("new")
return super().__new__(cls)
def __init__(self, name):
print("init")
self.name = name
def __del__(self):
print("del")
def __call__(self):
print("call")
def __str__(self):
return f"User(name={self.name})"
def __repr__(self):
return f"User({self.name})"
def __len__(self):
return len(self.name)
# 创建对象
user = User("Marry")
user() # 调用 __call__
print(user) # 调用 __str__
print(repr(user)) # 调用 __repr__
print(len(user)) # 调用 __len__
3. 运算相关的魔术方法
通过重写这些方法,可以实现对象之间的运算操作。
python
class Cat:
def __init__(self, nickname, age):
self.nickname = nickname
self.age = age
def __gt__(self, other):
return self.age > other.age
def __lt__(self, other):
return self.age < other.age
def __eq__(self, other):
return self.age == other.age
def __add__(self, other):
return self.age + other.age
def __str__(self):
return f"Cat(name={self.nickname}, age={self.age})"
# 创建对象
c1 = Cat("花花", 2)
c2 = Cat("小猫1", 1)
c3 = Cat("小猫2", 4)
# 比较大小
print(c1 > c2) # 输出: True
print(c1 < c2) # 输出: False
print(c1 == c2) # 输出: False
# 加法操作
result = c1 + c2
print(result) # 输出: 3
4. 属性相关的魔术方法
通过这些方法,可以实现对对象属性的动态访问和设置。
python
class Person:
def __init__(self, name):
self.name = name
def __getattr__(self, item):
if item == 'age':
return 20
elif item == 'gender':
return '男'
else:
return f"Attribute {item} does not exist"
def __setattr__(self, key, value):
if key == 'phone' and value.startswith('139'):
super().__setattr__(key, value)
else:
raise ValueError(f"Invalid value for {key}")
# 创建对象
p = Person("Alice")
print(p.name) # 输出: Alice
print(p.age) # 输出: 20
print(p.gender) # 输出: 男
print(p.address) # 输出: Attribute address does not exist
# 设置属性
p.phone = "13912345678" # 成功
# p.phone = "1234567890" # 抛出 ValueError
5. 几种方法的区别和联系
- 对象方法:描述的是当前对象所独有的方法。
- 类方法:描述的是这一类具有的特性,可以通过类或对象调用。
- 静态方法:类中的函数,不绑定到类或对象上,主要用于存放逻辑性的代码。
6. 注意点
- 类方法能否被对象调用?能。
- 类方法中能否访问对象属性?不能。
- 对象能否调用静态方法?能。
- 类方法能否调用静态方法?能。
- 静态方法能否调用类方法?不能。
- 类方法和静态方法能否调用普通方法?都不能。