面向对象是程序开发领域的重要思想,这种思想模拟了人类认识客观世界的思维方式,将开发中遇到的事物皆看
类与对象的基础应用
面向对象的编程中有2个核心概念:类和对象。类是抽象的,是一群具有相同特征和行为的事物的统称;对象是类的实例。
类的定义
class 类名:
属性名 = 属性值
def 方法名(self):
方法体
class:标识类的开始
类名:类的标识符,首字母一般大写
冒号:不能少!!!
属性:类似于变量
方法:类似于函数,但方法参数列表中的第一个参数是一个指代对象的默认参数self,在定义时括号内必须有”self“,调用时可不写
对象的创建与使用
程序若想要使用类,需根据类创造一个对象。
对象名 = 类名() #创建对象
对象名.属性名 #访问属性
对象名.方法名() #调用方法
类的成员
属性
属性按照声明的方式可分为两类:类属性和实例(对象)属性。
1.类属性
声明在类内部,方法外部的属性;可通过类或对象进行访问,但只能通过类进行修改。
2.实例属性
声明在方法内部,支持动态添加实例属性;实例属性只能通过对象访问,不能通过类访问。
实例属性通过对象进行修改&动态添加实例属性:
#代码1
class Car:
def drive(self):
self.wheels = 4 #添加实例属性
car = Car() #创建对象car
car.drive()
car.wheels = 3 #修改实例属性
car.color = '红色' #动态的添加实例属性
print(car.wheels) #通过对象car访问实例属性
print(car.color) #通过对象car访问实例属性
方法
Python中的方法按照定义方法和用途可分为3类:实例方法、类方法、静态方法。
1.实例方法
形似函数,定义在类内部、以self为第一个形参。实例方法中的self参数代表对象本身,会在实例方法被调用时自动接收由系统传递的调用该方法的对象。实例方法只能通过对象调用,上述代码1就是实例方法。
2.类方法
定义在类内部、使用装饰器@classmethod修饰的方法。类方法中参数列表第一个参数为cls,代表类本身,会在类方法被调用时自动接收由系统传递的调用该方法的类。类方法可以通过类和对象调用。
class 类名:
@classmethod
def 类方法名(cls):
方法体
#代码2
class Car:
wheels = 3 # 类属性
@classmethod
def stop(cls): # 类方法
print(cls.wheels) # 使用cls访问类属性
cls.wheels = 4 # 使用cls修改类属性
print(cls.wheels)
car = Car()
car.stop()
3.静态方法
定义在类内部、使用装饰器@staticmethod修饰的方法。静态方法没有任何默认参数,适用于与类无关的操作或者无须使用类成员的操作,常见于一些工具类中。静态方法可以通过类和对象调用。静态方法内部不能直接访问属性或方法,但可以使用类名访问类属性或调用类方法。
class 类名:
@staticmethod
def 静态方法名():
方法体
#代码3
class Car:
wheels = 3 # 类属性
@staticmethod
def test():
print("我是静态方法")
print(f"类属性的值为{Car.wheels}") # 静态方法中访问类属性
car = Car()
car.test() # 通过对象调用静态方法
Car.test() # 通过类调用静态方法
私有成员
类的成员默认为公有成员,可以在类的外部通过类或对象随意访问。私有成员只能在类的内部直接访问,在类的外部通过调用类的公有方法进行访问。
私有成员的表示:在类成员的名称前添加双下划线。
__属性名
__方法名
class Car:
__wheels = 4 # 私有属性
def __drive(self): # 私有方法
print("行驶")
def test(self):
print(f"轿车有{self.__wheels}个车轮") # 公有方法中访问私有属性
self.__drive() # 公有方法中调用私有方法
car = Car()
# print(car.__wheels) # 类外部访问私有属性
# car.__drive() # 类外部调用私有方法
car.test() #类外部通过公有方法访问私有属性
特殊方法
构造方法和析构方法都是系统内置方法。
构造方法 (__int__()方法)
负责在创建对象时对对象进行初始化。每个类默认有一个__int__()方法,若一个类显式的定义了__int__()方法,那么创建对象时调用显式的,否则使用默认的。
无参构造方法:所有对象的属性都有相同的初始值。
class Car:
def __init__(self): # 无参构造方法
self.color = "红色"
def drive(self):
print(f"车的颜色为:{self.color}")
car_one = Car() # 创建对象并初始化
car_one.drive()
car_two = Car() # 创建对象并初始化
car_two.drive()
有参构造方法:所有对象的属性可以有不同的初始值。
class Car:
def __init__(self, color): # 有参构造方法
self.color = color # 将形参赋值给属性
def drive(self):
print(f"车的颜色为:{self.color}")
car_one = Car("红色") # 创建对象,并根据实参初始化属性
car_one.drive()
car_two = Car("蓝色") # 创建对象,并根据实参初始化属性
car_two.drive()
析构方法(__del__()方法)
销毁对象时系统自动调用的特殊方法。每个类默认有一个__int__()方法,若一个类显式的定义了__int__()方法,那么创建对象时调用显式的,否则使用默认的。
class Car:
def __init__(self):
self.color = '蓝色'
print("对象被创建")
def __del__(self): #析构方法
print("对象被销毁")
car = Car()
print(car.color)
del car #使用del语句删除对象的引用
print(car.color) #报错,销毁Car类对象car后,无法使用Car类的对象访问属性
销毁对象
与文件类似,每个对象都会占用系统的一部分内存,使用之后若不及时销毁,会浪费系统资源。Python通过引用计数器记录所有对象的引用数量,一旦某个对象的引用计数器的值为0,系统就会销毁这个对象。
封装
封装的基本思想:对外隐藏类的细节,提供用于访问类成员的公共接口。
为契合封装思想,定义类时需满足以下2点需求: 1、将属性声明为私有属性; 2、添加2个供外界调用的公有方法,分别用于设置或获取私有属性的值。
class Person:
def __init__(self,name):
self.name = name #公有属性,name
self.__age = 1 #设置年龄的私有属性默认为1
#公有方法1,为外界提供设置__age属性的接口
def set_age(self,new_age):
if 0<new_age<=120:
self.__age = new_age
#公有方法2:为外界提供获取__age属性的接口
def get_age(self):
return self.__age
person = Person("小明")
person.set_age(20)
print(f"年龄为{person.ger_age()}岁)
继承
继承主要用来描述类与类之间的关系,在不改变原有类的基础上扩展原有类的功能。被继承的类称为父类或基类,继承其他类的类称为子类;子类自动拥有父类的公有成员,但子类不会拥有且不能访问父类的私有成员。
单继承
子类只继承一个父类。
class 子类名(父类名):
#定义一个猫类Cat和一个继承Cat类的折耳猫类ScottishFold
class Cat(object):
def __init__(self, color):
self.color = color
def walk(self):
print("走猫步~")
# 定义继承Cat的ScottishFold类
class ScottishFold(Cat):
pass
fold = ScottishFold("灰色") # 创建子类的对象
print(f"{fold.color}的折耳猫") # 子类访问从父类继承的属性
fold.walk() # 子类调用从父类继承的方法
class Cat(object):
def __init__(self, color):
self.color = color
def walk(self):
print("走猫步~")
def __test(self):
print("父类的私有方法")
# print(fold.__age) # 子类访问父类的私有属性
# fold.__test() # 子类调用父类的私有方法
多继承
子类具有多个父类,自动拥有所有父类的公有成员。如果多个父类中拥有一个同名的方法,且子类继承的多个父类是平行关系,那么子类先继承哪个类,便会先调用哪个类的方法。
class 子类名(父类名1,父类名2,...):
# 定义一个表示房屋的类House
class House(object):
def live(self): # 居住
print("供人居住")
def test(self):
print("House类测试")
# 定义一个表示汽车的类Car
class Car(object):
def drive(self): # 行驶
print("行驶")
def test(self):
print("Car类测试")
# 定义一个表示房车的类,继承House和Car类
class TouringCar(House, Car):
pass
tour_car = TouringCar()
tour_car.live() # 子类对象调用父类House的方法
tour_car.drive() # 子类对象调用父类Car的方法
tour_car.test() # 子类对象调用两个父类的同名方法
#运行结果
供人居住
行驶
House类测试
重写
子类需要按照自己的需求对继承来的方法进行调整,即在子类中重写从父类继承来的方法。
重写方法:
在子类中定义与父类方法同名的方法,在方法中按照子类需求重新编写功能代码。
若子类重写了父类的方法,子类对象默认调用的是子类重写的方法。
子类重写父类方法后,无法直接访问父类同名方法,使用super()函数间接调用。
# 定义一个表示人的类
class Person(object):
def say_hello(self):
print("打招呼!")
# 定义一个表示中国人的类
class Chinese(Person):
def say_hello(self): # 重写的方法
print("吃了吗?")
chinese = Chinese()
chinese.say_hello() # 子类调用重写的方法
#输出结果:吃了吗?
class Chinese(Person):
def say_hello(self):
super().say_hello() # super()函数调用父类被重写的方法
print("吃了吗?")
#输出结果:打招呼!吃了吗?
多态
多态的直接表现:让不同类的同一功能可以通过同一个接口调用,并表现出不同的行为。
class Car:
def shout(self):
print("喵喵喵")
class Dog:
def shout(self):
print("汪汪汪")
#定义接口,调用方法
def shout(self):
obj.shout()
cat=Car()
dog=Dog()
shout(cat)
shout(dog)
运算符重载
赋予内置运算符新的功能,使内置运算符能适应更多的数据类型。
#定义一个表示计算器的类
class Calculator(object):
def __init__(self,number):#记录数值
self.number = number
def __add__(self, other):#重载运算符+
self.number = self.number + other
return self.number
def __sub__(self, other):#重载运算符-
self.number = self.number - other
return self.number
def __mul__(self, other):#重载运算符*
self.number = self.number * other
return self.number
def __truediv__(self, other):#重载运算符/
self.number = self.number / other
return self.number
calculator = Calculator(10)
print(calculator + 5)
print(calculator - 5)
print(calculator * 5)
print(calculator / 5)