python面向对象
1.类和对象
在Python中,类和对象是面向对象编程(OOP)的核心概念。类(Class)是创建对象的蓝图或模板,它定义了对象将拥有的属性和方法。对象(Object)则是根据类创建的具体实例,它包含了类的属性和方法,并且可以在运行时使用这些属性和方法。
定义类:定义一个类使用class关键字,后面跟着类名和一个冒号。类的主体由缩进的代码块组成,通常包含属性和方法的定义。
创建对象:使用类名并调用它(通常带有参数)来创建对象。
类: 是对象的模版(共同的特性),抽象的
对象: 是类的实例化, 看的见,摸的着的具体的对象,万事万物皆为对象
# 1.创建类
class Student:
pass
# 2.创建对象
zs = Student()
ls = Student()
print(zs == ls)
print(id(zs), id(ls))
# 3.查看类型
print(type(zs)) # <class '__main__.Student'>
print(zs.__class__) # <class '__main__.Student'>
print(isinstance(zs, Student)) # True
# 4.销毁对象
del zs
print(ls)
2.实例属性
实例属性通常在类的初始化方法__init__中定义。这个方法是一个特殊的方法,当创建类的新实例时,Python会自动调用它。
class Person:
def __init__(self, first_name, last_name, age):
self.first_name = first_name # 实例属性
self.last_name = last_name # 实例属性
self.age = age # 实例属性
def greet(self):
print(f"Hello, my name is {self.first_name} {self.last_name}.")
# 创建Person类的实例
p1 = Person("John", "Doe", 30)
p2 = Person("Jane", "Smith", 25)
# 访问实例属性
print(p1.first_name) # 输出: John
print(p2.age) # 输出: 25
# 修改实例属性
p1.age = 31
print(p1.age) # 输出: 31
# 调用方法
p1.greet() # 输出: Hello, my name is John Doe.
实例属性的特性:
- 独立性:每个对象实例都有自己的实例属性副本,修改一个对象的属性不会影响其他对象。
- 动态性:可以在对象创建后随时添加或修改实例属性。
- 封装:实例属性通常被封装在类的内部,通过类的方法访问和修改,以维护数据的完整性和安全性。
3.实例方法
实例方法是在类体内部定义的,除了self之外,它们还可以接受其他参数。self参数在调用方法时不需要显式传递,Python会自动将调用方法的对象实例作为self参数传入。
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
raise NotImplementedError("Subclass must implement abstract method")
class Dog(Animal):
def __init__(self, name, age):
super().__init__(name) # 调用父类的初始化方法
self.age = age
def speak(self):
return f"{self.name} says Woof!"
class Cat(Animal):
def speak(self):
return f"{self.name} says Meow!"
# 创建对象实例
dog = Dog("Rex", 3)
cat = Cat("Whiskers")
# 调用实例方法
print(dog.speak()) # 输出: Rex says Woof!
print(cat.speak()) # 输出: Whiskers says Meow!
实例方法的特性:
- 访问实例属性:实例方法可以访问和修改对象的实例属性。
- 绑定到对象:实例方法与特定的对象实例绑定,每个对象都可以有自己的方法实现(尽管它们通常是通过类定义的共享方法)。
- 可覆盖性:在子类中,可以覆盖父类的实例方法以提供不同的实现。
4.字符串表示
1.__str__方法
__str__方法定义了一个对象的“非正式”或可打印的字符串表示。当你想要给用户一个友好的、易读的表示时,应该实现这个方法。print()函数和其他期望字符串表示的内置函数(如format())通常会调用__str__方法。
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return f"Dog(name={self.name}, age={self.age})"
d = Dog("Buddy", 5)
print(d) # 输出: Dog(name=Buddy, age=5)
2.__repr__方法
_ repr_ 方法定义了一个对象的“正式”字符串表示,旨在是准确的、无歧义的,并且尽可能表达对象是如何被创建的。这通常用于调试和开发,因为repr()函数和交互式解释器会调用它。一个好的__repr__方法应该允许开发者通过eval(repr(obj))重新创建出该对象(尽管这并不总是可能的或必要的)。
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age
def __repr__(self):
return f"Dog(name='{self.name}', age={self.age})"
d = Dog("Buddy", 5)
print(repr(d)) # 输出: Dog(name='Buddy', age=5)
# 在交互式解释器中,直接输入对象名也会调用 __repr__
# d # 输出: Dog(name='Buddy', age=5)
注意事项
- _ str _ 和 _ repr_ 都应该返回字符串。
- 如果你的类表示的是某种可以被直接解释的数据结构(如列表、字典或自定义的数据结构),那么__repr__的输出应该尽可能能够重新创建出该对象。
- 对于简单的类,_str _ 和 __repr __ 可以返回相同的值,但对于更复杂的类,你可能希望为它们提供不同的输出。
- 在实现这些方法时,避免产生无限递归或抛出异常,因为这可能会导致调试变得困难。