面试复习-Python-面向对象

2024-10-09 21:16:58 浏览数 (4)

面向对象编程的特点

封装是将数据和操作数据的方法封装在一个类中,对外隐藏内部的实现细节,只提供一些公共的方法来访问和修改数据。这样可以提高代码的安全性和可维护性,避免外部直接访问和修改内部数据,导致程序出现错误。

继承允许一个类(子类)继承另一个类(父类)的属性和方法,从而实现代码的复用和扩展。子类可以继承父类的所有公共属性和方法,并可以根据需要添加自己的属性和方法,或者重写父类的方法

多态是指同一个方法可以根据调用对象的不同而表现出不同的行为。在 Python 中,多态是通过方法重写和方法重载来实现的。方法重写是指子类重写父类的方法,方法重载是指在同一个类中定义多个同名方法,但参数列表不同。

抽象类是一种不能被实例化的类,它只能作为其他类的父类,用于定义一些抽象方法,这些方法没有具体的实现,需要在子类中实现

代码语言:javascript复制
from abc import ABC, abstractmethod

class Shape(ABC):
    @abstractmethod
    def area(self):
        pass

    @abstractmethod
    def perimeter(self):
        pass

Python类的基础知识

类的定义
代码语言:javascript复制
>>> class Student(object):
...   'student class'
...   def __init__(self, name, age):
...     self.name = name
...     self.age = age
...   def get_name(self):
...     return self.name
...   def get_age(self):
...     return self.age
...
>>> sen = Student('sen', 18)
>>> sen.get_name()
'sen'
>>> sen.get_age()
子类的定义:
代码语言:javascript复制
>>> class BoyStudent(Student):
...   def __init__(self, name, age):
...     super().__init__(name, age)
...     self.sex = 'male'
...   def get_sex(self):
...     return self.sex
...
>>> sen = BoyStudent('sen', 18)
>>> sen.get_sex()
'male'
类的特殊属性
代码语言:javascript复制
>>> BoyStudent.__doc__
>>> BoyStudent.__name__
'BoyStudent'
>>> BoyStudent.__bases__
(<class '__main__.Student'>,)
>>> BoyStudent.__dict__
mappingproxy({'__module__': '__main__', '__init__': <function BoyStudent.__init__ at 0x104681800>, 'get_sex': <function BoyStudent.get_sex at 0x104681620>, '__doc__': None})
>>> BoyStudent.__module__
'__main__'
>>> BoyStudent.__class__
<class 'type'>
>>> sen.__class__
<class '__main__.BoyStudent'>
静态方法

在 Python 中,静态方法是一种不依赖于类实例和类本身的方法。它可以通过类名直接调用,而不需要创建类的实例。使用 @staticmethod 装饰器来定义静态方法。例如:

代码语言:javascript复制
class MyClass:
    version = '1.0' # 静态属性
    @staticmethod
    def static_method():
        print("这是一个静态方法。")
MyClass.static_method() #调用静态方法
类方法

使用 @classmethod 装饰器定义,并且第一个参数通常命名为 cls,代表类本身。

类方法:

可以访问类变量,通过 cls 参数可以访问和修改类的属性。不能直接访问实例变量,因为没有实例对象的引用。

静态方法:

不能访问类变量和实例变量,它完全独立于类和实例的状态。通常用于与类或实例没有直接关系的通用功能。

代码语言:javascript复制
class MyClass:
    class_variable = 0

    def __init__(self, instance_variable):
        self.instance_variable = instance_variable

    @classmethod
    def class_method(cls):
        print(f"Class variable: {cls.class_variable}")

    @staticmethod
    def static_method():
        print("This is a static method.")
MyClass.class_method()
MyClass.static_method()

obj = MyClass(10)
obj.class_method()
obj.static_method()
其他要点
  • 组合类似于js中类的聚合,新类直接将旧类的实例包含在自己的属性中,从而达到访问旧类中属性和方法的目的
  • Python的多重继承在查找属性和方法是广度优先搜索的

类相关的内建函数

代码语言:javascript复制
>>> issubclass(BoyStudent, Student)
True
>>> isinstance(sen, BoyStudent)
True
>>> hasattr(BoyStudent, 'name')
False
>>> hasattr(sen, 'name')
True
>>> dir(Student)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'get_age', 'get_name']
>>> hasattr(Student, 'get_name')
True
>>> getattr(sen, 'name')
'sen'
>>> setattr(sen, 'name', 'sen001')
>>> getattr(sen, 'name')
'sen001'
>>> delattr(sen, 'name')
>>> getattr(sen, 'name')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'BoyStudent' object has no attribute 'name'
>>> vars(sen)
{'age': 18, 'sex': 'male'}

类的特殊属性和方法

slots
  • 当定义了 slots 时,Python 不会为每个实例创建一个 dict 属性字典来存储实例的属性。这可以显著减少内存使用,特别是在创建大量实例的情况下。
  • slots 可以明确地指定一个实例可以拥有的属性列表
代码语言:javascript复制
>>> class BoyStudent(Student):
...   'boy student'
...   __slots__ = ['name', 'age', 'sex']
...   def __init__(self, name, age):
...     super().__init__(name, age)
...     self.sex = 'male'
...   def get_sex(self):
...     return self.sex
...
>>> sen = BoyStudent('sen', 18)
>>> sen.phone = 123 # 没有限制住,因为父类中没有__slot__,所以父类中存在__dict__
>>> vars(sen) # 新的属性存进了父类的__dict__
{'phone': 123}

>>> class Student(object):
...   def __init__(self, name, age):
...     self.name = name
...     self.age = age
...   __slots__ = ['name', 'age']
...
>>> sen = Student('sen', 18)
>>> sen.phone = 123
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute 'phone'
AttributeError: 'Student' object has no attribute 'phone'
>>> vars(sen)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: vars() argument must have __dict__ attribute
描述符方法 get set delete

在 Python 中,描述符是一种实现了特定协议(__get____set____delete__方法)的对象,用于控制对另一个对象属性的访问。主要用于自定义 实例属性访问时的一些操作。

代码语言:javascript复制
class IntegerValidator:
  def __set_name__(self, owner, name):
    self.name = name
  def __set__(self, instance, value):
    if not isinstance(value, int):
      raise ValueError(f'{self.name} must be an integer.')
    instance.__dict__[self.name] = value
  def __get__(self, instance, owner):
    if instance is None:
      return self
    return instance.__dict__.get(self.name)
  def __delete__(self, instance):
    print(f"Deleting {self.name} from {instance}")
    del instance.__dict__[self.name]

class Student:
  age = IntegerValidator()

>>> s = Student()
>>> s.age = '28'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 6, in __set__
ValueError: age must be an integer.
>>> s.age = 28
>>> s.age
28
>>> del s.age
Deleting age from <__main__.Student object at 0x1007714f0>

0 人点赞