文章目录
python面向对象编程
面向对象(Object Oriented)是软件开发方法,一种编程范式。
面向对象是相对于面向过程来讲的,面向对象方法是把相关的数据和方法组织为一个整体来看待,从更高的层次来进行系统建模,更贴近事物的自然运行模式,即将程序中的数据和操作封装在一个对象中,从而使得程序更加模块化、可重用和易于维护。面向对象编程的核心思想是封装、继承和多态。
【类】是一种抽象的数据类型,定义了一组属性和方法。
【对象】是类的实例化,类只有实例化为对象了才可以调用其属性、方法。
【封装】是将数据和操作封装在一个对象中,隐藏对象的内部实现细节,只暴露必要的接口给外部访问。
【继承】是类与类的一种关系,是一种“is a”的关系。创建一个新的子类,子类会继承父类的属性和方法、也可以重写父类的属性和方法,从而实现更加灵活的功能。
【父类、子类】一个类可以从另一个类继承,被继承的类称为父类(又叫基类), 继承的类称为子类(又叫派生类)。比如“狗”继承“动物”,这里动物类是狗类的父类或者基类,狗类是动物类的子类或者派生类。
【多态】是指同一个方法可以根据不同对象的实现方式,实现不同的行为。是通过继承父类的属性和方法,
【方法重载】在同一个类中处理不同数据的多个相同方法名的多态手段。
【方法重写】相对继承而言,子类中对父类已经存在的方法进行区别化的修改。
类的定义
在成员变量或成员方法名称前加上双下划线“__”即可将其定义为私有的,外部程序无法直接访问。
私有成员变量,可以通过定义类的公有成员变量的setter、getter方法,让外部程序可以访问。
Python使用class关键字定义类,例如下面定义的Animal类:
class Animal:
__id # 显式定义类的私有成员变量(private【成员变量或成员方法前加双下划线修饰表示为私有成员变量】)
color # 显式定义类的公开成员变量(public)
# __init__函数表示构造函数,是特殊的函数,在创建对象时被自动调用
# self关键字表示实例化对象本身,相当于Java语言中的this
# self.name表示给类的成员变量name赋值,类中不需要显性声明name
def __init__(self, name): # 【构造函数一】Animal类的构造函数
self.name = name # 给Animal类的实例成员变量赋值
def __init__(self, name, weight): # 【构造函数一】Animal类的构造函数
self.name = name # 给Animal类的实例成员变量赋值
self.weight = weight # 给Animal类的实例成员变量赋值
# 定义类的成员方法
def run(self): # 通过函数定义动物的奔跑形为
print(self.name + " running.")
def sleep(self): # 通过函数定义动物的睡觉形为
print(self.name + " sleeping.")
def speak(self): # 通过函数定义动物的吃喝形为
raise NotImplementedError("Subclass must implement abstract method")
def set_id(self, id): # 成员变量的setter方法
self.__id = id
def get_id(self): # 成员变量的getter方法
return self.__id
类的实例化
将Animal类例化,即创建Animal类的对象,如下:
animal = Animal("dog", 10) # 实例化Animal后的对象名为animal,它的name属性为"dog",weight属性为10。
print(dog.name) # 访问dog对象的name属性,输出:dog
print(dog.weight) # 访问dog对象的weight属性,输出:10
animal.run() # 访问dog对象的run方法,输出:dog runing.
animal.sleep() # 访问dog对象的sleep方法,输出:dog sleeping.
animal.speak() # 访问dog对象的speak方法异常:"Subclass must implement abstract method"
animal.color = 'black' # 给dog对象的color属性赋值
print(dog.color) # 访问dog对象的color属性,输出:black
类的静态变量与静态方法
1、类变量和类方法都属于类的成员,它们与普通的成员变量和成员方法不同,类变量和类方法只属于定义它们的类,而不属于某一个对象。
2、类变量和类方法都可以通过类名和对象进行访问。
3、类变量的值可以修改,如果通过“类名.变量名”修改,则对所有实例对象都生效;如果通过“实例名.变量名”修改后,则只对实例生效,再通过“类名.变量名”修改不会影响此“实例名.变量名”的值。
类的静态变量
python不同于java、c++语言,Python没有严格的静态变量概念,因为其并没有static关键字作为对变量的修饰。
python的静态变量其实就是类变量,对应的非静态变量就是实例变量
类变量可以通过类名和对象进行访问。
类变量的值可以修改,如果通过“类名.变量名”修改,则对所有实例对象都生效;如果通过“对象名.变量名”修改后,则只对实例生效,再通过“类名.变量名”修改不会影响此“对象名.变量名”的值。
class Animal:
color = 'black' # 类变量,不需要显示的声明
def __init__(self):
Animal.color = 'white' # 直接访问类的类变量,在实例化时修改类变量的值
print('Animal:%s' % (Animal.color)) # 通过类名调用类变量,输出Animal:black
Animal.color = 'green' # 通过类名调用类变量,修改类变量的值
print('Animal:%s' % (Animal.color)) # 通过类名调用类变量,输出Animal:green
animal = Animal() # 创建对象实例
print('Animal:%s' % (Animal.color)) # 通过类名调用类变量,实例化时调用了构造函数,输出Animal:white
animal.color = 'red' # 通过对象实例操作类变量,修改类变量的值
print('Animal:%s' % (animal.color)) # 通过对象实例调用类变量,输出Animal:red
print('Animal:%s' % (Animal.color)) # 通过类名调用类变量,输出Animal:white
Animal.color = 'orange' # 通过类名调用类变量,修改类变量的值
print('Animal:%s' % (animal.color)) # 通过类名调用类变量,输出Animal:red
print('Animal:%s' % (Animal.color)) # 通过类名调用类变量,输出Animal:orange
类的静态方法@staticmethod
用装饰符@staticmethod修饰的方法,就是类的静态方法,通过“类名.方法名”和“对象名.方法名”进行访问。
静态方法中不传入self参数,在静态方法中无法访问静态实例变量,但可以通过类名引用静态变量,其通常用于那些不需要访问类属性或实例属性的情况。
class Animal:
@staticmethod # 装饰符@staticmethod修饰的方法,就是类的静态方法
def run():
print("run() is static function!")
Animal.run() # 输出run() is static function!
animal = Animal()
animal.run() # 输出run() is static function!
类的类方法@classmethod
用装饰符@classmethod修饰的方法就是类方法,这个方法接收一个特殊参数cls,代表类本身,而不是实例。
类方法可以访问和修改类属性,并且它也可以被继承和覆盖。通常,类方法用于创建工厂方法,用于创建类的实例,或者用于对类属性进行操作。
class Animal:
color = 'black'
@classmethod
def run(cls):
cls.color = 'red'
print("run() is static function! " + cls.color)
Animal.run() # 输出run() is static function! red
animal = Animal()
animal.run() # 输出run() is static function! red
# @classmethod的高级用法
class Date:
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
@classmethod
def from_string(cls, date_string):
year, month, day = map(int, date_string.split('-')) # 解析参数字符串
return cls(year, month, day) # 这里通过特殊参数cls调用构造函数
# 使用类方法来初始化日期对象
date1 = Date(2023, 8, 17)
date2 = Date.from_string("2023-08-17")
print(date1.year, date1.month, date1.day) # 输出: 2023 8 17
print(date2.year, date2.month, date2.day) # 输出: 2023 8 17
如果方法不需要这些访问类属性,并且在逻辑上与类密切相关,但不依赖于类状态,那么可以使用静态方法@classmethod。
如果方法需要访问类属性、类状态或执行类相关操作,那么可以使用类方法@classmethod。
类的继承
单继承
class Dog(Animal): # 定义Dog类继承Animal类
def __init__(self, name, breed): # Dog类的构造函数
super().__init__(self, name, weight) # 调用父类的构造函数
self.breed = breed # 给Dog类的成员变量赋值
def speak(self): # 实现父类的抽象成员方法
return "Woof"
def look_house(self): # 定义Dog类专用的成员方法
print(self.name + " can look house.")
多继承
多继承是指一个类可以同时继承多个父类的特性和方法。
多继承需要在子类时在类名通过括号,将被继承的多个类的名字用逗号隔开即可。
class A:
def method1(self):
print("Method 1 of A be called.")
class B:
def method2(self):
print("Method 2 of B be called.")
class C(A, B): # 将被继承的多个类的名字用逗号隔开即可
def method3(self):
print("Method 3 of C be called.")
c = C()
c.method1() # 输出"Method 1 of A be called."
c.method2() # 输出"Method 2 of B be called."
c.method3() # 输出"Method 3 of C be called."
多层继承
多层继承是指一个类的父类也有父类,这个类同时继承了父类以及祖类的成员属性和成员方法。
class A:
def method1(self):
print("Method 1 of A be called.")
class B(A): # B继承了A
def method2(self):
print("Method 2 of B be called.")
class C(B): # C继承了B
def method3(self):
print("Method 3 of C be called.")
c = C()
c.method1() # 输出"Method 1 of A be called."
c.method2() # 输出"Method 2 of B be called."
c.method3() # 输出"Method 3 of C be called."
类方法的重写
子类可以重写(覆盖)父类的方法,以实现自己的功能。重载,需要注意以下几点:
- 子类的方法名与父类的方法名相同。
- 子类的方法参数与父类的方法参数相同。
- 子类的方法返回值类型与父类的方法返回值类型相同或者是父类方法返回值类型的子类型。
类方法的重载
类方法的重载是指,多个方法同名、但参数不一样,调用的时候根据参数匹配相应的方法执行。
class A:
def method1(self):
print("Method 1 of be called.")
def method1(self, name): # 重载method1()方法
print("Method 1 (name) of be called.")
def method1(self, name, age): # 重载method1()方法
print("Method 1 (name, age) of be called.")
a = A()
a.method1() # 输出"Method 1 of be called."
a.method1('zhangsan') # 输出"Method 1 (name) of be called."
a.method1('zhangsan', 18) # 输出"Method 1 (name, age) of be called."
调用父类的方法
方法一:通过super()函数调用父类的方法。
方法二:直接使用父类的类名调用父类的方法。
class Dog(Animal):
def __init__(self, name, breed):
super().__init__(name, weight) # 【方法一】调用父类的构造函数
self.breed = breed
def __init__(self, name):
Animal.__init__(self, name) # 【方法二】调用父类的构造函数
self.breed = breed
super函数
super()函数用于调用父类的方法。使用super()函数调用父类的方法时,可以不使用父类的类名,而是使用super()函数自动识别出需要调用的父类的方法。
super()函数的语法如下:super([type[, object-or-type]])
,type是子类的类型,object-or-type是子类的对象或类型。如果只有一个参数,则默认为子类的类型。