python入门(9)面向对象 :封装、继承、多态与垃圾回收
标签: python入门(9)面向对象 :封装、继承、多态与垃圾回收
2023-05-29 18:23:30 43浏览
1. 封装
在Python中,封装是面向对象编程中的一个重要概念,它允许将数据和方法隐藏在类的内部,只暴露一部分接口供外部访问。通过封装,可以有效地控制数据的访问权限,提高代码的可维护性和安全性。
1.1 修饰符
Python中的封装通过使用访问修饰符来实现,主要有三种访问修饰符:
(1)公有访问修饰符(Public):使用默认的访问权限,没有任何修饰符,所有成员都可以在类的内部和外部访问。示例代码如下:
class MyClass:
def __init__(self):
self.public_var = 10
def public_method(self):
print("This is a public method.")
obj = MyClass()
print(obj.public_var) # Output: 10
obj.public_method() # Output: This is a public method.
(2)私有访问修饰符(Private):使用双下划线__
作为前缀,将属性或方法标记为私有的,表示只能在类的内部访问。示例代码如下:
class MyClass:
def __init__(self):
self.__private_var = 20
def __private_method(self):
print("This is a private method.")
def public_method(self):
self.__private_method()
obj = MyClass()
print(obj.__private_var) # Error: 'MyClass' object has no attribute '__private_var'
obj.__private_method() # Error: 'MyClass' object has no attribute '__private_method'
obj.public_method() # Output: This is a private method.
尽管私有属性和方法在类的外部无法直接访问,但可以通过公有方法间接访问私有成员。
(3)保护访问修饰符(Protected):使用单下划线_
作为前缀,将属性或方法标记为受保护的,表示只能在类的内部和子类中访问。示例代码如下:
class MyBaseClass:
def __init__(self):
self._protected_var = 30
def _protected_method(self):
print("This is a protected method.")
class MyDerivedClass(MyBaseClass):
def access_protected(self):
print(self._protected_var)
self._protected_method()
obj = MyDerivedClass()
obj.access_protected() # Output: 30\nThis is a protected method.
尽管受保护的成员可以在子类中访问,但在类的外部仍然可以直接访问。因此,保护访问修饰符主要起到一种命名约定的作用,表示某个成员是受保护的,不应该在类的外部直接访问。
封装可以帮助我们隐藏实现的细节,提供清晰的接口供外部使用。
1.2 self 参数
在Python中,self
是一个约定俗成的参数名,用于表示对象自身。它是一个指向当前实例的引用,类中的方法通过 self
参数来访问对象的属性和方法。
在类定义中,使用 self
作为第一个参数声明方法时,表示该方法是对象的实例方法,可以通过实例调用。例如,__init__(self)
方法用于初始化对象,在方法内部可以通过 self
访问对象的属性和方法。
示例代码:
class MyClass:
def __init__(self, x):
self.x = x
def print_x(self):
print(self.x)
obj = MyClass(10)
obj.print_x() # Output: 10
在调用 obj.print_x()
时,self
参数会自动传递实例对象 obj
,使得在 print_x
方法内部可以通过 self.x
访问到对象的属性。
需要注意的是,self
不是Python的关键字,可以使用其他名称代替,但约定俗成的做法是使用 self
来表示对象自身。
2. 继承
在Python中,继承是一种面向对象编程的重要概念,它允许一个类继承另一个类的属性和方法,从而实现代码的重用和扩展。
要定义一个继承关系,可以在定义类时在类名后面加上要继承的父类名,用括号括起来。例如,下面是一个简单的继承示例:
class ParentClass:
def __init__(self, x):
self.x = x
def print_x(self):
print("ParentClass: ", self.x)
class ChildClass(ParentClass):
def __init__(self, x, y):
super().__init__(x) # 调用父类的初始化方法
self.y = y
def print_y(self):
print("ChildClass: ", self.y)
obj = ChildClass(10, 20)
obj.print_x() # Output: ParentClass: 10
obj.print_y() # Output: ChildClass: 20
在上面的示例中,ChildClass
继承了 ParentClass
,因此它可以访问和使用 ParentClass
中定义的属性和方法。子类可以添加新的属性和方法,也可以重写父类中的方法。
在子类的初始化方法中,可以使用 super().__init__(args)
来调用父类的初始化方法,并传递相应的参数。这样可以确保子类对象在创建时先调用父类的初始化逻辑,然后再进行自己的初始化操作。
通过继承,子类可以继承父类的属性和方法,并且可以添加、修改或覆盖这些属性和方法,从而实现代码的复用和扩展。继承是面向对象编程中重要的特性之一,可以建立类之间的层次关系,提高代码的可维护性和可扩展性。
关于多重继承
Python 支持多重继承,这意味着一个类可以继承自多个父类。
在定义一个类时,可以在类名后面的括号中指定多个父类,多个父类之间使用逗号进行分隔。例如:
class ParentClass1:
def method1(self):
print("ParentClass1: method1")
class ParentClass2:
def method2(self):
print("ParentClass2: method2")
class ChildClass(ParentClass1, ParentClass2):
def method3(self):
print("ChildClass: method3")
obj = ChildClass()
obj.method1() # Output: ParentClass1: method1
obj.method2() # Output: ParentClass2: method2
obj.method3() # Output: ChildClass: method3
在上述示例中,ChildClass
继承了 ParentClass1
和 ParentClass2
两个父类。因此,它可以访问和使用两个父类中定义的属性和方法。通过多重继承,子类可以从多个父类中继承不同的功能,从而实现更灵活和复杂的代码结构。
需要注意的是,多重继承可能导致类之间的复杂关系,特别是当不同的父类中有相同的方法名时,可能会引起命名冲突。在这种情况下,可以使用方法解析顺序(Method Resolution Order,MRO)来确定调用哪个父类的方法。Python 使用 C3 算法来计算 MRO,确保方法的调用顺序是按照一定规则确定的。
尽管多重继承可以提供更大的灵活性和代码重用性,但在使用时需要注意设计和维护的复杂性。合理使用多重继承可以充分利用面向对象编程的优势,但需要注意避免过度复杂化和混乱的继承结构。
3. 多态
多态是面向对象编程的一个重要概念,它允许不同的对象对相同的消息做出不同的响应。在 Python 中,多态性是通过方法的动态绑定实现的。
当一个对象调用一个方法时,Python 会根据对象的类型确定要调用的方法实现。如果该对象是一个特定类的实例,Python 将搜索该类及其父类中的方法,并调用与该方法名匹配的方法实现。
下面是一个简单的示例,演示多态的概念:
class Animal:
def sound(self):
pass
class Cat(Animal):
def sound(self):
print("Meow!")
class Dog(Animal):
def sound(self):
print("Woof!")
def make_sound(animal):
animal.sound()
cat = Cat()
dog = Dog()
make_sound(cat) # Output: Meow!
make_sound(dog) # Output: Woof!
在上述示例中,我们定义了一个基类 Animal
,以及两个子类 Cat
和 Dog
。这两个子类都重写了基类中的 sound
方法,实现了各自的声音输出。
然后,我们定义了一个名为 make_sound
的函数,该函数接受一个 Animal
类型的参数,并调用该参数的 sound
方法。通过传入不同的实例对象,我们可以看到函数根据对象的类型调用不同的 sound
方法,实现了多态性。
多态性能够提高代码的灵活性和可扩展性。通过面向对象的多态性,可以编写通用的代码,适用于不同的对象类型,并根据实际对象的类型来调用正确的方法。这样可以使代码更加模块化和可维护,同时减少了冗余的条件判断语句。
4. 多态与 is instance 关键字
is instance
是 Python 中的一个关键字,用于检查一个对象是否属于指定的类型或其子类。它与多态性密切相关,可以在代码中判断对象的类型,并根据需要执行相应的操作。
is instance
的语法如下:
isinstance(object, classinfo)
其中,object
是要检查的对象,classinfo
是要检查的类型或类型元组。
下面是一个示例,演示 isinstance
的用法和多态的概念:
class Animal:
def sound(self):
pass
class Cat(Animal):
def sound(self):
print("Meow!")
class Dog(Animal):
def sound(self):
print("Woof!")
def make_sound(animal):
if isinstance(animal, Animal):
animal.sound()
else:
print("Invalid animal!")
cat = Cat()
dog = Dog()
make_sound(cat) # Output: Meow!
make_sound(dog) # Output: Woof!
make_sound("Invalid") # Output: Invalid animal!
在上述示例中,我们使用 is instance
来检查传入 make_sound
函数的参数是否属于 Animal
类或其子类。如果是,我们调用 animal.sound()
来执行相应的动作;否则,我们打印出 "Invalid animal!"。
is instance
的使用可以帮助我们在多态的情境中正确地处理不同类型的对象。它允许我们根据对象的类型执行不同的操作,提高代码的可读性和可维护性。
5. python对象的垃圾回收
在 Python 中,垃圾回收是自动进行的,开发者不需要手动管理内存。Python 通过引用计数和垃圾回收器来处理对象的内存管理。
引用计数: Python 使用引用计数来跟踪对象的引用情况。每当对象被引用时,它的引用计数增加1;当对象不再被引用时,它的引用计数减1。当一个对象的引用计数变为0时,表示没有任何引用指向它,该对象将被垃圾回收器回收并释放内存。
循环引用: 循环引用指的是一组对象之间形成了一个环状的引用关系,导致它们的引用计数都不为0,即使没有外部引用指向它们,它们也无法被垃圾回收。为了解决这个问题,Python 使用了一个垃圾回收器来检测和处理循环引用的情况。
垃圾回收器: Python 中的垃圾回收器是一个独立的线程,它会周期性地扫描所有的对象,并判断它们的引用计数是否为0。对于引用计数为0的对象,垃圾回收器将释放它们所占用的内存空间。除了引用计数,垃圾回收器还会检测和处理循环引用,确保不会有任何对象被遗漏。
需要注意的是,虽然垃圾回收是自动进行的,但它可能会导致一些额外的开销和性能损失。在大多数情况下,Python 的垃圾回收机制是高效且无需干预的。然而,对于一些特殊情况,比如大量创建临时对象或使用循环引用的复杂数据结构,开发者可能需要考虑优化内存管理以提高性能。
总结:Python 中的垃圾回收是通过引用计数和垃圾回收器来自动管理对象的内存。引用计数用于跟踪对象的引用情况,当引用计数为0时,对象将被回收。垃圾回收器处理循环引用和其他特殊情况,确保不会有任何对象被遗漏。开发者无需手动管理内存,可以专注于编写代码逻辑。
6. 类的垃圾回收机制
在 Python 中,垃圾回收是由解释器自动进行的,开发者不需要显式地实现垃圾回收。Python 使用引用计数和垃圾回收器来处理对象的内存管理,这些功能由解释器内部实现并进行管理。
引用计数是 Python 主要的垃圾回收机制。每个对象都有一个引用计数器,当有一个引用指向对象时,引用计数加1;当引用离开作用域或被重新赋值时,引用计数减1。当一个对象的引用计数变为0时,表示没有任何引用指向它,该对象就可以被回收。
除了引用计数,Python 还有一个垃圾回收器(Garbage Collector),它会定期扫描所有的对象,并检查是否有循环引用的情况。如果发现循环引用,垃圾回收器会标记这些对象,并将它们回收。
开发者可以通过 `gc` 模块来控制和调整垃圾回收器的行为,例如手动触发垃圾回收、禁用垃圾回收等。`gc` 模块提供了一些函数和方法,如下所示:
- `gc.collect()`:手动触发一次垃圾回收。
- `gc.disable()`:禁用垃圾回收器。
- `gc.enable()`:启用垃圾回收器。
- `gc.get_count()`:返回当前垃圾回收的计数器。
- `gc.get_threshold()`:返回垃圾回收器的阈值。
- `gc.set_threshold()`:设置垃圾回收器的阈值。
需要注意的是,大多数情况下,Python 的垃圾回收是自动进行的,无需开发者干预。开发者只需关注对象的创建和使用,由解释器自动管理内存和垃圾回收。但在某些特殊情况下,如处理大量临时对象或使用循环引用的复杂数据结构时,了解垃圾回收机制和相应的调优技巧可能会对性能有所帮助。
好博客就要一起分享哦!分享海报
此处可发布评论
评论(0)展开评论
展开评论