面向过程和面向对象的区别
(1)面向过程编程的核心是过程,就是需要分析出实现这些步骤,通过函数一步一步实现这些步骤在接着在依次调用即可,简单理解就是程序从上到下一步一步执行,从头到尾的解决问题
(2)面向对象编程是把构成事物的整个需求按照特点、功能划分,将这些存在共性的部分封装成对象,创建对象的目的不是为了完成某一个步骤,而是为了描述某个事物在整个解决问题得步骤中的行为。
面向对象编程的好处:
面向对象编程以对象作为程序的基本单元,将方法和数据封装其中,它具有继承、封装、多态三大特性,可以提高代码的重用性、灵活性和拓展性。
1、创建类的一个示例
创建一个Dog类,Dog后面的括号可写可不写,默认继承Object类,__init__是类的初始化方法,需要给类设置实例属性就写该方法,不需要可以不写。__init__会在创建类的实例时被自动调用,第一个参数是self。它是一个指向实例本身的引用,让实例能够访问类中的属性和方法。 我们创建Dog实例时,Python将调用Dog类的方法__init__()。我们将通过实参向Dog()传递名字和 年龄;self会自动传递,因此我们不需要传递它。每当我们根据Dog类创建实例时,都只需给最 后两个形参(name和age)提供值
class Dog(): #括号可写可不写,默认继承Object类
def __init__(self,name,age): ##init方法会在初始化一个类的实例时候被自动调用
self.name = name
self.age = age
def sit(self):
print(self.name.title())
def roll_over(self):
print(self.name.title()+"roll over")
my_dog = Dog('kk',18) #创建一个类的实例
my_dog.sit() #调用实例方法
my_dog.roll_over() #调用实例方法
print("My dog's name is "+ my_dog.name.title()) #调用实例属性
2、属性方法、实例方法、类方法
类方法:使用@classmethod来修饰,类方法默认以cls参数作为第一个参数,调用时可以使用类名直接调用,也可以用实例调用,但是类方法不能访问对象属性(即通过self.xxx定义的属性)只能访问类属性。
实例方法:只能由类的的实例,也就是对象调用,方法的第一个参数必须是self,调用时可以不传递self,默认传递。
属性方法:可以像属性一样进行调用的方法,目的是为了防止直接对属性到的值进行修改
类属性:可以通过类名和实例名调用
实例属性:可以通过实例名调用
示例:类方法、实例方法、类属性和实例属性的使用
class Student:
age = 12 #类属性
def __init__(self,gender):
self.gender = gender
def study(self,name): #创建了一个实例方法
print("{}在学习".format(name))
@classmethod
def running(cls,name): #创建了一个类方法
print("{}在跑步".format(name))
stu = Student("女") #创建一个类实例
stu.study("小狗") #通过类的实例调用实例方法
Student.running("小猫") #通过类名调用类方法
stu.running("大象") #通过实例调用类方法
print(Student.age) #用类名输出类属性的值
print(stu.age) #用类的实例输出类属性的值
print(stu.gender) #通过类的实例调用实例属性
属性方法的使用
场景一:求长方形的面积,给定长方形的长和宽,返回长方形的面积,但是这种情况把面积属性暴露出去,有可能会导致其他人直接通过调用属性赋值的方式,出现问题。
class Rectangle:
def __init__(self,height,width):
self.height = height
self.width = width
self.area = self.height * self.width
rect = Rectangle(8,10)
rect.area = 50
print(rect.area)
解决方式一:通过方法返回
class Rectangle:
def __init__(self,height,width):
self.height = height
self.width = width
def get_area(self):
return self.height * self.width
rect = Rectangle(8,10)
print(rect.get_area())
解决方式二:通过属性方法返回,在不改变调用方式的情况下,增加一个属性方法。而且用户无法通过实例.属性修改。
class Rectangle:
def __init__(self,height,width):
self.height = height
self.width = width
@property #属性方法
def area(self):
return self.height * self.width
rect = Rectangle(8,10)
print(rect.area) #直接像调用属性一样调用属性方法,返回长方形面积
三、类的继承
创建一个父类Car和子类ElectricCar,子类继承父类要在类名括号里面写上父类名字,需要在初始化的时候用super()放着第一行初始化父类。子类可以继承父类的属性和方法,子类如果重写了和父类同名的方法,子类调用时,会调用自己的方法。
class Car(): #定义一个Car父类
def __init__(self,make,model,year):
self.make = make #制造商
self.model = model #型号
self.year = year #生成年份
self.odometer_reading = 0 #给属性设置默认值 读取汽车里程表
def get_descriptive_name(self): #打印汽车的详细信息
long_name = str(self.year)+' ' +self.make+' '+self.model
return long_name.title()
def read_odometer(self): #读取里程信息
print("This car has "+str(self.odometer_reading)+" miles on it")
def increment_odometer(self,miles): #通过方法修改默认属性值
self.odometer_reading += miles
def car_running(self):
print("汽车开始启动了")
class ElectricCar(Car):
def __init__(self,make,model,year):
super().__init__(make,model,year) #初始化父类属性
self.battery_size = 30 #定义子类特有属性 电瓶容量
def describe_battery(self):
print("The Car has a "+str(self.battery_size)+"-KWH battery")
def car_running(self): #重写与父类同名的方法
print("电瓶车开始启动了")
my_tesla = ElectricCar('tesla','models',2016) #创建一个子类的实例
print(my_tesla.get_descriptive_name()) #调用父类方法、获取my_tesla详细信息
my_tesla.describe_battery() #调用子类特有方法、输出电瓶容量
my_tesla.car_running() #子类重写父类方式时,调用的是子类独有方法
输出结果:
2016 Tesla Models
The Car has a 30-KWH battery
电瓶车开始启动了