目录
前言
Python是一种具有面向对象编程(OOP)特性的高级编程语言,主要包括:类和实例、封装和抽象、继承、多态。
1.类和实例
类(class)是一种面向对象编程的基本概念,通过定义类可以创建一个对象的蓝图。下面是Python中类和实例的基本操作方法:
(1)定义类
定义类是指在程序代码中声明一个新类,用于描述一组具有相同属性和行为的对象。定义类使用关键字class,语法如下:
class ClassName:
# 类的属性
attribute = value
# 类的方法
def method(self, arg1, arg2, ...):
# 方法体
其中,class后面跟着类名ClassName,类名通常采用骆驼拼写法(UpperCamelCase);然后是一个或多个变量定义语句和函数定义语句,它们构成了该类的属性和方法。
(2)创建对象实例
类只是一个对象的模板,它本身并不占用内存空间。要使用一个类创建一个对象实例(instance),需要调用类的构造函数(init())来初始化对象属性。创建对象实例使用以下语法:
instance = ClassName()
其中,instance是一个类的具体实例化过程,等式右边的ClassName()是类的一个构造函数,会返回类的一个对象实例。
(3)访问对象的属性和方法
创建了类的对象实例后,就可以使用点号运算符(.)来访问它的属性和方法。例如,如果a是一个类的对象实例,那么可以使用以下语法来访问它的属性和方法:
a.attribute # 访问属性
a.method(arg1, arg2, ...) # 调用方法
其中,attribute是类的一个属性,method(arg1, arg2, ...)是类的一个方法。
(4)实例化时传参
有时候需要在创建类对象实例的时候,向类初始化一些数据。可以在创建类的对象实例时,为其传入参数。 在创建对象实例时调用类的构造函数,并向构造函数传递初始化参数,构造函数将这些参数存储在实例的实例变量中,如下所示:
class ClassName:
def __init__(self, *args):
self.args = args
instance = ClassName(arg1, arg2, ...)
print(instance.args) # (arg1, arg2, ...)
其中,*args表示不定长参数,允许我们在构造函数中传入任意长度的参数列表。
2.封装
Python中的封装(Encapsulation)是一种面向对象编程的基本特性,它指的是将数据属性和方法组合在一个单独的小单元中,并通过限制其访问权限来保护这些数据。通过封装,我们可以隐藏对象内部的细节,使代码更加模块化、可复用和可靠。
在Python中,通过以下两种方式实现封装:
(1)私有属性和方法
Python本身并没有提供类属性和方法的私有化机制,但是可以使用双下划线前缀(__)的命名约定来实现伪私有化。使用双下划线进行命名的属性或方法会被解释为私有的属性或方法,只能在类内部访问,无法从外部访问。例如:
class Person:
def __init__(self, name):
self.__name = name # 私有属性
def __say_hello(self): # 私有方法
print('Hello, {}'.format(self.__name))
p = Person('Alice')
print(p.__name) # 报错:'Person' object has no attribute '__name'
p.__say_hello() # 报错:'Person' object has no attribute '__say_hello'
虽然私有属性和方法可以阻止直接从外部操作类的内部数据,但也不是完全不能访问,可以通过特殊变量_ClassName__attr(比如p._Person__name)来访问到私有属性和方法。然而,在代码开发时,应该尽量遵守私有属性和方法的约定,并将其视为类的内部实现细节。
(2)公共接口
封装的另一个重要概念是公共接口(public interface),指类暴露给外部的可供调用的方法。通过合理设计公共接口,我们可以使类的行为更加规范化、易于使用。例如:
class BankAccount:
def __init__(self, balance=0):
self.balance = balance
def deposit(self, amount):
if amount < 0:
print('Invalid amount')
return False
self.balance += amount
print('Deposit successful, current balance is {:.2f}'.format(self.balance))
def withdraw(self, amount):
if amount < 0 or amount > self.balance:
print('Withdrawal failed, insufficient balance')
return False
self.balance -= amount
print('Withdrawal successful, current balance is {:.2f}'.format(self.balance))
account = BankAccount(1000)
account.deposit(500)
account.withdraw(200)
在上述例子中,BankAccount类定义了一种银行账户的数据类型,只有deposit和withdraw方法对外界可见,其他属性和方法都被隐藏起来。这个类模块化程度更高,通过禁止外部代码直接操作对象内的变量(比如balance),从而提高了安全性和可靠性。
3.继承
继承是面向对象编程中一个重要的特性,它允许一个类从另一个类继承属性和方法,并在此基础上添加新的功能或修改现有的行为。继承的主要内容包括:
(1)父类(base class)和子类(derived class):父类是被继承的类,它可以定义一些通用的属性和方法;子类是从父类继承并派生出来的类,可以使用父类中的属性和方法,并且可以添加新的属性和方法。
(2)继承关系(inheritance relationship):父类和子类之间形成了继承关系,子类拥有父类的所有属性和方法。子类可以覆盖(override)继承自父类的属性和方法,或者增加新的属性和方法。
(3)实现继承(implementation inheritance):通过创建新类来实现继承,即子类继承父类的所有属性和方法,并完全继承它们。接口继承(interface inheritance):子类只继承父类的接口(即方法),而不继承其实现。这种继承方式需要在子类中重新定义接口中的方法。
Python中实现继承的方法为:
class BaseClass:
# 定义父类
class DerivedClass(BaseClass):
# 定义子类
在这里,BaseClass是父类,DerivedClass是继承自BaseClass的子类。子类可以重写父类中的方法或属性来实现特化的功能。此外,Python还支持多重继承,即一个子类可以同时继承多个父类。
在使用继承时,需要注意以下几点:
(1)子类需要调用父类的构造函数(__init__方法):在子类的构造函数中需要调用父类的构造函数来初始化父类的属性,例如 BaseClass.__init__(self, arg1, arg2)。
(2)单一职责原则:子类应该具有单一的职责,也就是只负责实现一个明确定义的功能模块。
(3)依赖倒置原则:子类需要依赖于抽象而不是具体的类。因此,在设计类结构时,应该将共同的行为抽象成接口或者父类,让子类去实现具体的行为。
4.多态
多态(polymorphism)是面向对象编程的一个重要概念,可以通过同名方法实现对不同类对象的不同响应。要实现多态操作,需要借助于继承、接口和抽象类等面向对象编程的特性。
(1)继承多态
继承是实现多态最简单也是最常见的方式之一。在继承关系中,子类通过重写或覆盖父类的方法来实现自己的特定行为。当调用该方法时,根据传入的对象类型的不同,会自动调用合适的方法,产生不同的行为。例如:
class Animal:
def speak(self):
raise NotImplementedError("Method not implemented")
class Cat(Animal):
def speak(self):
return "Meow"
class Dog(Animal):
def speak(self):
return "Woof"
def animal_speak(animal):
print(animal.speak())
cat = Cat()
dog = Dog()
animal_speak(cat) # Meow
animal_speak(dog) # Woof
(2)接口多态
接口是一种更纯粹的多态,其中接口本身没有任何具体的实现。它只定义了一组方法、成员变量、属性等接口规范,由子类去实现具体的功能。接口在Python中通常使用抽象基类(ABC)实现,例如:
import abc
class Person(metaclass=abc.ABCMeta):
@abc.abstractmethod
def talk(self):
pass
class Teacher(Person):
def talk(self):
return "I am a teacher"
class Student(Person):
def talk(self):
return "I am a student"
def person_talk(person):
print(person.talk())
teacher = Teacher()
student = Student()
person_talk(teacher) # I am a teacher
person_talk(student) # I am a student
(3)抽象类多态
抽象类是一种包含了抽象方法的类,这些方法只定义了接口但没有具体的实现。抽象类不可直接实例化,需要通过继承来实现,子类必须实现抽象方法才能被实例化。在Python中,使用abc模块可以实现抽象基类,例如:
import abc
class Vehicle(metaclass=abc.ABCMeta):
@abc.abstractmethod
def drive(self):
pass
class Car(Vehicle):
def drive(self):
return "Driving car"
class Bicycle(Vehicle):
def drive(self):
return "Riding bicycle"
def vehicle_drive(vehicle):
print(vehicle.drive())
car = Car()
bicycle = Bicycle()
vehicle_drive(car) # Driving car
vehicle_drive(bicycle) # Riding bicycle
5.魔术方法
魔术方法(Magic methods),又称为特殊方法(Special method)或双下划线方法(Double underscore method),是Python中的一种特殊的内置方法,用于实现类的特定行为。这些方法都以双下划线开头和结尾(例如:__init__、__str__、__lt__ 等),因此也被称为双下划线方法。
以下是常用的魔术方法:
(1)__init__(self[, args...]):构造函数,用于初始化对象,在对象创建时自动调用。
(2)__repr__(self):返回一个供开发者阅读的字符串表示形式,通常用于调试和开发阶段。
(3)__str__(self):返回一个供用户阅读的字符串表示形式,通常用作显示或输出对象的信息。
(4)__len__(self):返回对象的长度,通常用于序列类型的对象。(例如:列表、元组等)
(5)__add__(self, other):重载加号运算符,在两个对象相加时自动调用,返回一个新的对象。
(6)__lt__(self, other):重载小于号运算符,用于比较两个对象是否小于。
(7)__eq__(self, other):重载等于号运算符,用于比较两个对象是否相等。
(8)__getattr__(self, name):在访问未定义属性时自动调用,并返回一个值或引发异常。
(9)__setattr__(self, name, value):在设置属性时自动调用,可以在此处添加一些限制条件。
魔术方法的使用非常灵活,可以根据需要进行重载。但是,由于一些特殊方法会被Python解释器自动调用,可能对程序性能产生不利影响。因此,在使用这些方法时应该谨慎使用,避免过度使用导致代码难以维护和理解。
此致与君共勉