面向对象编程1.编程范式 我们写代码的目的是什么?就是为了能够让计算机识别我们所写的代码并完成我们的需求,规范点说,就是通过编程,用特定的语法+数据结构+特殊算法来让计算机执行特定的功能,实现一个功能的方式有很多种,对这些不同编程方式的特点进行归纳总结出来的编程方式类别,就叫做编程范式。最重要的两个编程范式就是面向过程编程和面向对象编程。发展到现在,编程已经从简单控制流中按步的指令集转变为依靠代码块完成既定的功能。 2.面向过程编程(Procedural Programming) 面向过程是一种以过程为中心的编程思想,先分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个一次调用就可以了,以孩子上学这件事用面向过程的编程思想说明的话,可以粗略的将该过程模拟为: 这四步就是一步一步的完成的,它的顺序很重要,只需要一步一步去实现就好了,这就是面向过程编程思想
通过下面一个例子使用面向对象的编程方法实现数据库备份的功能,首先需要将这一事件分解为三个过程:连接数据库-备份数据-测试,代码如下: [AppleScript] 纯文本查看 复制代码 def db_con():
print("连接数据库")
def db_backup():
print("进行数据备份")
def db_backup_test():
print("备份数据可用性测试")
def main():
db_con()
db_backup()
db_backup_test()
if __name__ == "__main__":
main()
这就是面向过程的编程方式,缺点显而易见的,如果要对该程序进行修改,那么对所修改部分有所依赖的其他部分也需要进行修改,程序越大越复杂,这种编程方式的维护难度就会越来越高,所以,如果要处理的任务是复杂的,需要不断的迭代和维护,选择面向对象的编程方式是更合适的。 3.面向对象编程(Object Oriented Programming) 面向对象编程思想更像是一个真实的世界,通过创建类和对象来描述这个世界,对函数进行封装和分类,让开发变得更快,Python从设计之初就是一门面向对象的编程语言,正因为如此,在Python中创建一个类和对象是很容易,面向对象编程其实就是对类和对象的使用。一句话:玩好面向对象,就是玩好类和对象。为了让大家能更好的理解,我通过一个小案例来引出类和对象。
首先有这样一个需求:有很多只小狗,需要打印出哪只小狗正在跳,通过函数的方法,我可以这样实现: [AppleScript] 纯文本查看 复制代码 dog_1={ 定义第一个小狗的属性,包含小狗的姓名和年龄
"name":"AA",
"age":2,
}
dog_2={ 定义第二个小狗的属性,包含小狗的姓名和年龄
"name":"BB",
"age":3,
}
def cry(*args):
print("一个名叫%s的%s岁小狗正在“汪汪~”的叫"%(dog_1["name"],dog_1["age"]))
cry(dog_1["name"],dog_1["age"]) 调用cry()函数
这样写,有如下几个缺点:
第一:如果需要打印无数多个小狗正在叫的信息,要从dog_1定义到dog_n,这样既会拉低效率,又会出现大量的重复代码。
第二:如果修改了调用的小狗(如我不传入dog_1的属性,改为传入dog_2),那么在函数cry()中也要进行相应的修改。那显然是不行的。
第三:人是不具备“汪汪”叫这个动作的,我如果定义一个人的信息,按照上述的代码写法,也是可以调用cry()函数的,那我们怎么实现将cry()函数只提供给dog这一类使用呢?带着这三个疑问,通过改为如下的代码来解决上述的三个问题: [AppleScript] 纯文本查看 复制代码 def dog(name,age): 首先定义一个狗的函数,传入两个参数,即小狗的姓名和年龄
def cry(dog): 在dog()函数内定义嵌套函数cry,该函数只能在函数dog()内被调用
print("一个名叫%s的%s岁小狗正在“汪汪~”的叫"%(dog["name"],dog["age"]))
def init(name,age): 定义一个初始化函数
dog_1={
"name":name,
"age":age,
"cry":cry,
}
return dog_1
return init(name,age)
d_1=dog("AA",23) 该方式实质上是通过调用init函数,生成一个具有年龄,名字的小狗d_1
print(d_1)
d_1["cry"](d_1) 调用cry函数
代码通过这种改变,cry()就只能被狗这一类调用,在外面定义一个人的属性去调用cry()函数,很明显是无法调用的。
  接下来我就引出类的概念。什么是类呢?为什么要使用类* 3.1 定义类 类,既类别,种类,是面向对象设计中最重要的概念,类是一种数据结构,可以用它来定义对象,把数据值和行为特性融合在一起,在上面的例子中,小狗的属性“姓名”、“年龄”是所有小狗都具有的属性,这就是数据值,特定行为就是cry(),只有狗 这一类的叫声才是“汪汪”,其它的都不具备该行为特性。定义类与定义函数很类似,定义函数使用关键字def,定义类需要用到关键字class
  在python中,类的声明就是通过关键字class,后面紧跟一个类名如下: [AppleScript] 纯文本查看 复制代码 def dog(): 函数
pass 函数体代码
class dog: 类
pass 类体代码,通常由各种各样的定义和声明组成
经典类与新式类的区别,经典类 class dog:;新式类 class dog(object),所以如果大家见到定义类后面有括号的,一定要认得。 3.2 类对象 类对象支持两种操作:属性引用和实例化
属性引用:当创建类对象的时候,所有在类命名空间中的名称也都是有效的属性名,对最开始说到的那个例子,我用类来实现,代码如下: [AppleScript] 纯文本查看 复制代码 class Dog(object): 定义一个类Dog
"这是一个小狗的类"
def __init__(self,name,age): 使用__init__函数进行初始化
self.name=name
self.age=age
def cry(self):
print("一个名叫%s的%s岁小狗正在“汪汪~”的叫"%(self.name,self.age))
d_1=Dog("AA",2) 类的实例化 -->d_1
d_1.cry() 使用创建的实例,调用类方法
属性引用与python标准语法中所有属性引用一样的语法:obj.name,在上面的例子中,Dog.name;Dog.age;Dog.cry等都是有效的属性引用,分别反馈整数和一个函数的对象。类的实例化使用函数(调用)表示法,将类对象看作是一个新的类实例的无参函数,如d_1=Dog("AA",2),该实例化就可以理解为:我定义了一条小狗d_1,它的名字是AA,它的年龄是2岁,这就相当于d_1={"name":AA,"age":2},这样定义出来的实例,就可以调用类的特定行为函数方法。当一个类定义了__init__()方法时,类实例化会为新创建的类实例自动调用__init__()发法,会将定义时传入的参数传递给该方法。
类相关知识
还是上面那个简单的例子: [AppleScript] 纯文本查看 复制代码 d_1=Dog("AA",2) #创建一个实例
print(Dog.color) #调用类的局部变量,类的作用于问题,我会在稍后进行详细解答
Dog.cry(d_1) #通过类名.函数名的方式,传入一个实例
self是代表类的实例,在定义类的时候是必须有的,但是在调用的时候不必传入相应的参数,类的方法与普通的函数只有一个特殊的区别--它们必须有一个额外的第一个参数名称self,self返回的是当前对象的内存地址。
python为类内置的特殊属性 [AppleScript] 纯文本查看 复制代码 print(dir(Dog)) #返回对象的一个字符串列表的目录
print(Dog.__name__) #返回一个类的名字
print(Dog.__bases__) #类的第一个父类(在后面叫讲继承的时候会将)
print(Dog.__doc__) #返回类的字符串文档
print(Dog.__bases__) #类所有父类构成的元祖(同样,在继承的时候会将)
print(Dog.__dict__) #返回一个类的字典属性
print(Dog.__module__) #返回类定义所在的模块
print(d_1.__class__) #返回一个实例对应的类
类属性的增删改查 [AppleScript] 纯文本查看 复制代码 print(Dog.color) #查看
Dog.color = "red" #修改
print(Dog.color)
Dog.hand=4 #增加
print(Dog.hand)
del Dog.hand #删除
print(Dog.hand)
类,其实总体就包含了两个大的“模块”,1.数据属性;2.函数属性
对象相关知识
还是这样的一个例子: [AppleScript] 纯文本查看 复制代码 class Dog(object):
"这是一个小狗的类"
def __init__(self,name,age):
self.name=name
self.age=age
def cry(self):
print("一个名叫%s的%s岁小狗正在“汪汪~”的叫"%(self.name,self.age))
[AppleScript] 纯文本查看 复制代码 d_1=Dog("AA",2) #实例化,实质就是在运行__init__(self,name,age)函数
d_1.cry() #创建的实例调用类中的方法,self的功能其实就是将实例自动传入,所以我们看到,在类中定义cry函数的时候加
#了参数self,但在调用该函数的时候不需要再次传入d_1
print(d_1.name) #调用类中的变量
Dog.cry(d_1) #将实例传入类的方法中
实例属性的增删改查 [AppleScript] 纯文本查看 复制代码 d_1=Dog("aa",2)
print(d_1.name) #查看
d_1.age = 6
print(d_1.age) #修改
d_1.type = "藏獒" #增加
print(d_1.type)
del d_1.type #删除
print(d_1.type)
|